【问题标题】:Canonical way to stop boost::asio operations停止 boost::asio 操作的规范方法
【发布时间】:2012-10-04 13:03:30
【问题描述】:

我有一个boost::asio::io_service 在执行某些操作的线程中运行:

struct clicker
{
    clicker(boost::asio::io_service& io) : timer_(io) { wait_for_timer(); }

    void stop() { timer_.cancel(); }

    void wait_for_timer()
    {
        timer_.expires_from_now(std::chrono::milliseconds(500));
        timer_.async_wait(std::bind(&clicker::wait_completed, this, _1));
    }

    void wait_completed(const boost::system::error_code& err)
    {
        if (!err) {
            std::cout << "Click" << std::endl;
            wait_for_timer();
        }
    }

    boost::asio::steady_timer timer_;
};

int main()
{
    boost::asio::io_service io;
    clicker cl(io);

    std::thread io_thread(&boost::asio::io_service::run, &io);

    while (true) { // the run loop
        // gather input
        if (user_clicked_stop_button()) { cl.stop(); break; }
    }

    io_thread.join();
}

现在调用stop() 应该取消等待计时器并触发wait_completed() 并出现错误。然而,我们这里有一个竞争条件:有时,stop() 将在 wait_for_timer() 运行时和 async_wait 被安排之前被调用。然后,代码将无限期地运行。

处理这种情况的推荐方法是什么?在 wait_completed 中测试的 clicker 中的布尔标志?互斥体?

更新:

这只是一个简化的例子,在实际代码中我有几个操作在io_service 中运行,所以这里不能调用io_service::stop()

【问题讨论】:

    标签: c++ multithreading boost-asio


    【解决方案1】:

    将操作发布到 io_service 线程:

    void stop() 
    { 
      timer_.get_io_service().post([=] { timer_.cancel(); }); 
    } 
    

    (如果您的编译器不兼容 c++11,请使用 bind 创建 lambda。)

    【讨论】:

      【解决方案2】:

      我想你想调用io.stop() 来停止 io_service 对象。

      【讨论】:

      • 这只是一个简化的例子。我希望其他操作继续进行。
      • 啊,我错过了。在这种情况下,将取消操作发布到 io_service。 io.post(boost::bind(&clicker::stop, cl));
      猜你喜欢
      • 2011-06-16
      • 1970-01-01
      • 1970-01-01
      • 2010-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-10
      • 1970-01-01
      相关资源
      最近更新 更多