boost :: asio io_service线程池

时间:2011-10-31 17:08:38

标签: c++ networking boost boost-asio c++11

为io_service设置线程池的正确用法是什么?来自documentation的这两个陈述让我失望:

io_service::run

  

run()函数的正常退出意味着io_service对象已停止(stopped()函数返回true)。除非事先调用reset(),否则对run(),run_one(),poll()或poll_one()的后续调用将立即返回。

io_service::reset

  

当由于io_service被停止或者由于io_service被停止而返回先前调用这些函数时,必须在run(),run_one(),poll()或poll_one()函数的任何第二次或更高版本的调用之前调用此函数。失业了。

以下是我目前正在做的事情:

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 个答案:

答案 0 :(得分:17)

run()是一个阻塞调用,将在返回之前执行它可以执行的所有事件。只有在没有更多事件需要处理时它才会返回。返回后,您必须在io_service上调用reset(),然后再次调用run()

你可以让多个线程调用run() - 这不是问题,只要io_service有一些工作要做,你就不需要无限循环。正常模式是在io_service上创建一个work对象,这将迫使run()永远不会返回。这意味着你必须在完成后明确地在io_service上调用stop(),因为它永远不会自然退出。

如果您在io_service上设置work,它将永远不会自然退出,因此您永远不需要致电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