Home  >  Article  >  Backend Development  >  How to reliably cancel a Boost ASIO Deadline Timer in a separate thread?

How to reliably cancel a Boost ASIO Deadline Timer in a separate thread?

Barbara Streisand
Barbara StreisandOriginal
2024-10-29 07:03:30477browse

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&amp; ec)
{
    if (!ec) {
        started = true;
        if (timer.expires_at() != Timer::time_point::min()) {
            timer.expires_from_now(std::chrono::milliseconds(10));
            timer.async_wait(&amp;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!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn