【问题标题】:boost::asio io_service thread poolboost::asio io_service 线程池
【发布时间】:2011-12-18 21:56:49
【问题描述】:

为 io_service 设置线程池的正确用法是什么?来自documentation 的这两条语句让我大吃一惊:

io_service::run

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

io_service::reset

当由于 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() 放入无限循环中,一切似乎都可以正常工作(文档似乎表明不是应该是这种情况)。 正确的方法是什么?

【问题讨论】:

  • 据我了解,您只调用了一次 run,它仅在没有更多工作排队时才返回。我从来没有循环调用它。不过我可能误解了一些东西
  • @JohnB 好吧,我已经得到了所有这些对象,这些对象在整个地方都使用 io_service 读写等等。完全有可能 io_service 会暂时停止工作,然后再次排队等待更多工作,不是吗?我正在尝试处理这种情况,并且还分布在多个线程上。
  • 这个想法是,在完成处理您正在处理的请求之前,您总是将下一个读取或写入请求排队。如果你不能这样做,你可以使用这里描述的工作对象boost.org/doc/libs/1_42_0/doc/html/boost_asio/reference/…
  • @JohnB 解决你的第一句话:在我的代码中,许多系统/线程在他们认为合适的时候执行读/写。他们彼此不了解,并且可能有也可能没有足够的work 来保持 io_service 的队列在应用程序的整个生命周期内不为空。我无法想象 asio 的重要用途可以保证 io_service 的不间断工作流。

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


【解决方案1】:

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

【讨论】:

  • 随机线程问题:m_IoService.run()之后需要调用boost::this_thread::yield()吗?
  • @Dave - 这毫无意义,只有在run() 退出后才会执行到该点。
  • 我认为总是让run() 干净地退出会更干净。如果您需要确保在没有事件时io_service 保持活动状态,请创建一个work 对象并在退出时将其销毁。这样,所有未决事件都会触发,从而清理所有内容。
  • 如果我把帖子改成派送怎么办?作业会被不同的线程执行吗?
  • @jean,post()始终排队(因此在不同的上下文中执行),dispatch()可以在 中执行 i>当前上下文如果可能,否则将排队(如post())。
猜你喜欢
  • 2017-09-17
  • 2016-01-07
  • 2018-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多