How do I cancel coroutines and handle timeouts?

Coroutines in C++ are a powerful tool for writing asynchronous code. However, managing their lifecycle, especially when needing to cancel them or handle timeouts, requires careful design. In this example, we will see how to create a coroutine with cancellation support and implement timeout functionality using C++20 coroutines.

Keywords: C++, Coroutines, Cancellation, Timeouts, Asynchronous Programming
Description: This article explains how to manage coroutine execution in C++ by implementing cancellation and timeout mechanisms, ensuring smoother asynchronous operations.

#include <iostream>
#include <coroutine>
#include <thread>
#include <atomic>
#include <chrono>

struct CancelableTask {
    struct promise_type {
        CancelableTask get_return_object() {
            return {}; // Returning a CancelableTask instance
        }

        std::suspend_never initial_suspend() {
            return {};
        }

        std::suspend_always final_suspend() noexcept {
            return {};
        }

        void unhandled_exception() {
            std::terminate();
        }

        void return_void() {}
    };

    std::atomic canceled{false};

    void cancel() {
        canceled = true;
    }

    bool is_canceled() const {
        return canceled;
    }
};

CancelableTask sleep_for(int seconds) {
    for (int i = 0; i < seconds; ++i) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        std::cout << "Slept for " << (i + 1) << " seconds" << std::endl;

        if (canceled) {
            std::cout << "Cancelled!" << std::endl;
            co_return; // Exiting the coroutine
        }
    }
    co_return; // Normal exit
}

int main() {
    CancelableTask task;
    auto coroutine = sleep_for(5); // Execute sleep_for coroutine

    std::this_thread::sleep_for(std::chrono::seconds(2)); // Wait for 2 seconds
    task.cancel(); // Cancel the coroutine

    std::this_thread::join(); // Wait for the coroutine to finish
    return 0;
}
    

Keywords: C++ Coroutines Cancellation Timeouts Asynchronous Programming