0

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调度之前调用。然后,代码将无限期地运行。

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

更新:

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

4

2 回答 2

2

将操作发布到 io_service 线程:

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

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

于 2012-10-04T13:15:35.927 回答
0

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

于 2012-10-04T13:11:33.897 回答