Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-threaded alternative to waiting on a condition. (Edit: Proactor pattern with boost.asio?)

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?

like image 579
Tom Avatar asked Apr 22 '11 09:04

Tom


1 Answers

I guess what you are looking for is the reactor pattern. This is where most of the activities do not take too much time and they are doing co-operative multitasking. See node.js for a JavaScript implementation of the idea, but in C++ the ACE library provides this concept out-of-the-box allowing multiple threads based on the number of cores in the system.

These libraries all depend on some OS APIs that support non-blocking IO on disks, network, etc. When you are not waiting for the OS, but another message source in your app, they provide you with the tools for that.

like image 89
wigy Avatar answered Oct 14 '22 19:10

wigy