Home > Article > Backend Development > How to reliably cancel a Boost ASIO Deadline Timer in a separate thread?
Cancelling Boost ASIO Deadline Timer Safely
The provided code is intended to cancel a boost::asio::basic_waitable_timer safely within a separate thread. However, it appears that the cancellation is not working as expected due to an underlying issue.
Understanding the Issue:
The issue stems from the fact that the provided code attempts to cancel the timer using the post function, which adds the cancellation operation to the event queue of the timer's io_service. This approach is problematic because if the timer has already expired before the cancellation operation is executed, the cancel operation will be ignored, effectively leaving the timer in an active state.
Resolving the Issue:
To address this issue, we need to devise a robust way to cancel the timer regardless of its current state. One effective approach is to introduce a sentinel value for the timer's expiry time point that signifies an invalid state. By setting the timer's expiry to this sentinel value during the cancellation process, we can ensure that even if the timer has expired before the cancellation, it will be placed in an invalid state, effectively preventing any further asynchronous operations.
Modified Code:
Implement the sentinel value approach:
<code class="cpp">timer.get_io_service().post([](){ std::cerr << "tid: " << std::this_thread::get_id() << ", cancelling in post\n"; // Cancel: timer.expires_at(Timer::clock_type::time_point::min()); });</code>
Completion Handler Handling:
In the completion handler, check for the sentinel value to detect shutdown:
<code class="cpp">void handle_timeout(const boost::system::error_code& ec) { if (!ec) { started = true; if (timer.expires_at() != Timer::time_point::min()) { timer.expires_from_now(std::chrono::milliseconds(10)); timer.async_wait(&handle_timeout); } else { std::cerr << "handle_timeout: detected shutdown\n"; } } else if (ec != boost::asio::error::operation_aborted) { std::cerr << "tid: " << std::this_thread::get_id() << ", handle_timeout error " << ec.message() << "\n"; } }</code>
With the sentinel value approach, you can now reliably cancel the timer even if it has already expired.
The above is the detailed content of How to reliably cancel a Boost ASIO Deadline Timer in a separate thread?. For more information, please follow other related articles on the PHP Chinese website!