Непоточная альтернатива ожиданию по условию. (Изменить: шаблон Proactor с boost.asio?) - PullRequest
6 голосов
/ 22 апреля 2011

Я реализую алгоритм передачи сообщений. Сообщения передаются между соседними узлами, когда у них достаточно информации на узле, чтобы составить сообщение - информация, которая передается на узел от соседних узлов. Реализация будет тривиальной, если я сделаю каждое сообщение потоком и использую boost :: condition, чтобы перевести поток в спящий режим, пока не будет доступна необходимая информация.

К сожалению - у меня есть 100k узлов на графике, что означало бы 300k потоков. Когда я спросил , как создать такое количество потоков, я ответил, что не должен - и вместо этого изменил дизайн.

Мой вопрос: существует ли стандартная схема проектирования для ожидания условия? Возможно, какой-то асинхронный шаблон управления?

РЕДАКТИРОВАТЬ: Я думаю, что я могу сделать это с паттерном proacator. Я отредактировал теги, чтобы включить boost :: asio - чтобы узнать, есть ли у кого-нибудь предложения с этим.

Таким образом, обсуждение может быть конкретным, вот как определяются сообщения:

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;
};

Эти функторы сообщений в настоящее время запускаются с boost :: thread. Тогда у нас есть

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;
}

Мне нравится прозрачность кода и, если возможно, хотелось бы сохранить те же интерфейсы, имея какую-то альтернативу условной блокировке?

1 Ответ

3 голосов
/ 22 апреля 2011

Полагаю, вы ищете реактор . Именно здесь большинство видов деятельности не занимают слишком много времени, и они выполняют совместную многозадачность. См. node.js для реализации этой идеи на JavaScript, но в C ++ библиотека ACE предоставляет эту концепцию из коробки, позволяя создавать несколько потоков на основе количества ядер в система.

Все эти библиотеки зависят от некоторых API-интерфейсов ОС, которые поддерживают неблокирующий ввод-вывод на дисках, в сети и т. Д. Когда вы не ожидаете ОС, а только другого источника сообщений в своем приложении, они предоставляют вам инструменты для этого.

...