boost :: asio io_service пул потоков - PullRequest
       52

boost :: asio io_service пул потоков

15 голосов
/ 31 октября 2011

Как правильно использовать настройки пула потоков для io_service? Эти 2 утверждения из документации сбивают меня с толку:

io_service :: пробег

Обычный выход из функции run () подразумевает, что объект io_service остановлен (функция stop () возвращает true). Последующие вызовы run (), run_one (), poll () или poll_one () будут возвращаться немедленно, если не было предварительного вызова reset ().

io_service :: сброс

Эта функция должна вызываться перед любым вторым или более поздним набором вызовов функций run (), run_one (), poll () или poll_one (), если предыдущий вызов этих функций возвращался из-за остановки io_service или уходит с работы.

Вот что я сейчас делаю:

boost::thread_group     m_Threads;
boost::asio::io_service m_IoService;
boost::barrier          m_Barrier(numThreads);

for( unsigned int i = 0; i < numThreads; ++i )
{
    m_Threads.create_thread(
        [&]()
        {
            for(;;)
            {
                m_IoService.run();

                if( m_Barrier.wait() )  //  will only return true for 1 thread
                {
                    m_IoService.reset();
                }
                m_Barrier.wait();
            }
        });
}

m_IoService.stop();
m_Threads.interrupt_all();
m_Threads.join_all();

Кажется, все работает нормально, если я просто поместил m_IoService.run() в бесконечный цикл (что, как представляется, документация указывает на то, что не имеет место). Что такое правильный способ?

1 Ответ

17 голосов
/ 31 октября 2011

run() является блокирующим вызовом и выполнит все возможные события перед возвратом. Он вернется, только если больше нет событий для обработки. Как только он вернется, вы должны вызвать reset() на io_service перед повторным вызовом run().

Вы можете иметь несколько потоков, вызывающих run() - это не проблема, и вам не нужен бесконечный цикл, если у io_service есть работа. Обычный шаблон для этого - создать work объект на io_service, который заставит run() никогда не возвращаться. Это означает, что вам явно нужно вызвать stop() на io_service, когда вы закончите, поскольку он никогда не завершится естественным образом.

Если вы настроите work на io_service, он никогда не выйдет естественным образом и, следовательно, вам никогда не потребуется вызывать reset().

work some_work(m_IoService); // this will keep the io_service live.

for( unsigned int i = 0; i < numThreads; ++i )
{
  m_Threads.create_thread(
    [&]()
    {
      m_IoService.run();
    });
}

Теперь все потоки отправляют события на io_service

// Now post your jobs
m_IoService.post(boost::bind(...)); // this will be executed in one of the threads
m_IoService.post(boost::bind(...)); // this will be executed in one of the threads
m_IoService.post(boost::bind(...)); // this will be executed in one of the threads

m_IoService.stop(); // explicitly stop the io_service
// now join all the threads and wait for them to exit
...