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してラムダを作成します。)

于 2012-10-04T13:15:35.927 に答える
0

io.stop()を呼び出してio_serviceオブジェクトを停止したいと思います。

于 2012-10-04T13:11:33.897 に答える