I am implementing a message passing algorithm. Messages pass between adjacent nodes when they have enough information at the node to compose the message - information that is passed to the node from neighbouring nodes. The implementation is trivial if I make each of messages a thread and use boost::condition to put the thread to sleep until the required information is available.
Unfortunately - I have 100k nodes in the graph which would mean 300k threads. When I asked how to make that many threads the answer was that I shouldn't - and re-design instead.
My question is: is there a standard design pattern for waiting for a condition? Perhaps some asynchronous control pattern?
EDIT: I think I can do this with the proacator pattern. I have edited to tags to include boost::asio - to see if anyone has suggestions with this.
So the discussion can be concrete, here is how the messages are defined so far:
class
Message
{
public:
Message(const Node* from, Node* to)
: m_from(from), m_to(to)
{}
void
operator()()
{
m_to->ReceiveMessage( m_from->ComposeMessage() );
}
private:
Node *m_from, *m_to;
};
These message functors are currently launched with boost::thread. Then we have
class Node
{
Node(Node* Neighbour1, Node* Neighbour2, Node* Neighbour3);
// The messages (currently threads) are created on construction,
// The condition locks then sort out when they actually get passed
// without me having to think too hard.
void ReceiveMessage(const Message&);
//set m_message from received messages;
//EDIT This looks like an async write - use boost asio here?
Message
ComposeMessage()
{
// If possible I want to implement this function without threads
// It works great but it if every message is a thread
// then I have 300k threads.
// EDIT: this looks like an async read (use boost asio here?)
boost::mutex::scoped_lock lock(m_mutex);
while (!m_message) //lock the thread until parameter is set.
m_cond.wait(lock);
return *m_message;
}
private:
boost::optional<Message> m_message;
boost::mutex m_mutex;
boost::condition m_cond;
}
I like the transparency of the code and if possible would like to keep the same interfaces by having some alternative to the conditional lock?