如何在停止io_service之前等待所有挂起的完成处理程序执行?

时间:2016-10-14 15:52:11

标签: c++ multithreading boost boost-asio

我正在使用boost::asio编写服务器。我有多个线程,每个线程拥有它自己的io_service对象。当没有要执行的完成处理程序时,我使用io_service::work对象来保持io_service运行。在某些时刻,我调用stopio_service对象的方法来完成调用io_serice::run的线程。但在某些情况下,当我调用stop时,我已在io_service对象竞争处理程序中发布了未完成的操作。调用stop会阻止发布的竞争处理程序执行,但这对我来说是不可接受的,因为我需要在停止线程之前完成所有待处理的工作。如何在调用stop的{​​{1}}方法之前先等待所有挂起的完成处理程序执行?

1 个答案:

答案 0 :(得分:2)

只需重置work

当所有待处理的工作完成后,任何io_service::run()都会返回。

常见模式是使用optional<work>,以便您可以清除它。如果这是一个常见的事情,你可以通过将它包装在启用RAII的类中来减少一些心理开销:

<强> Live On Coliru

#include <boost/asio.hpp>
#include <boost/optional.hpp>

struct work {
    using io_service = boost::asio::io_service;
    work(io_service& svc) : _work(io_service::work(svc)) 
    { }

    void release() {
        _work.reset();
    }

    void enlist(io_service& svc) {
        _work.emplace(io_service::work(svc));
    }

  private:
    boost::optional<io_service::work> _work;
};

#include <thread>
#include <iostream>
using namespace std::chrono_literals;

int main() {
    boost::asio::io_service svc;
    work lock(svc);

    std::thread background([&] { svc.run(); });

    std::this_thread::sleep_for(1s);

    std::cout << "releasing work";
    lock.release();

    background.join();
}

1秒后完成后台线程。