There's plenty of coroutine frameworks out there with cancellation built-in, but I'd like it to be part of the C++ standard, not yet another library someone must include to be able to use the C++ coroutines.
Currently, people have no choice but to:
A) implement their own promise types (with all of the required knowledge potentially being a problem), or
B) Rely on external libraries

C++20 introduced coroutines, so I find it pretty natural that the next step is to also provide a standardized way to use coroutines rather than just providing the framework.

Op zo 12 apr 2026 om 14:35 schreef Zhao YunShan via Std-Proposals <std-proposals@lists.isocpp.org>:

I can provide a comprehensive solution, a complete coroutine framework. You can find the source code  [https://github.com/dou1984/coev.git]
Key features include:
  1. co_event that supports manual suspension and resumption, giving you full control!!!
  2. wait_for_allwait_for_any, and co_task primitives.
Based on your requirements, I can also provide some pseudocode for reference.

class Router
{
    std::map<int , co_event> m_cancellation;

    awaitable<int> handle_message(session& sess)
    {
        auto& cancel = m_cancellation[sess->Id()];
        defer(m_cancellation.erase(sess->id());

        auto client = co_await g_client_pool.get();
        defer(client.release(client));

        co_task _task; 
        auto request_id = _task << [](auto& client) -> awaitable<void> 
        { 
            auto r = client.request(...); 
            if (r == INVALID) 
            { 
                LOG(...); 
            } 
        }(client); 

        auto cancel_id = _task << [](auto& cancel) -> awaitable<void> 
       { 
            co_await cancel.suspend(); 
        }(cancel); 

        auto ret_id = co_await _task.wait(); 
        if (ret_id == cancel_id) 
        { 
            LOG("cancel"); 
            co_return INVALID; 
        } 

        LOG("success"); 
        return 0; 
    }
     void cancel(int id)
    {
        if (auto it = m_cancellation.find(id); it != m_cancellation.end())
        {
            it->second.resume();
        }
    }
};

>Date: Thu, 9 Apr 2026 15:23:23 +0100
>From: L?n?rd Szolnoki <cpp@lenardszolnoki.com> >To: std-proposals@lists.isocpp.org >Subject: Re: [std-proposals] Automatic Coroutine Cancellation >Message-ID: <a94be06c-ec0a-444c-8982-c1f6511e1921@lenardszolnoki.com> >Content-Type: text/plain; charset=UTF-8; format=flowed > > > >On 09/04/2026 14:42, Arthur O'Dwyer via Std-Proposals wrote: >> On Sat, Apr 4, 2026 at 5:04?AM Rhidian De Wit via Std-Proposals <std- >> proposals@lists.isocpp.org <mailto:std-proposals@lists.isocpp.org>> wrote: >> >> >> I've been reading up a bit on C++26 std::execution and I noticed that for cancellation >> we still use the `std::stop_token` approach to be able to "cancel" a coroutine by >> forcing the user to always call `stop_requested()` before continuing the coroutine, in >> addition to needing to pass a `std::stop_source` or `std::stop_token` around, making >> it pretty inconvenient to use. >> >> Now, there are ways to make this more automatic, for example, by embedding the >> `std::stop_source` in the coroutine's?promise type and checking at every suspension / >> resumption point (`await_suspend()` and `await_resume()` respectfully) whether or not >> the coroutine has been cancelled. If so, you can throw an exception and let the >> coroutine unwind itself. >> >> I was wondering if there is a proposal for such an automatic cancellation feature in >> the works or already present? >> >> >> I am relatively uneducated in this area; but no, I'm not aware of any plan or proposal to >> embed a stop_token into every coroutine. >> My kneejerk reaction was "That sounds bad! Every suspend point would become an invisible >> interruption point ? you couldn't hold a resource across a suspend point without careful >> planning!" >> But then I thought again, and realized that we already have /that/. The caller is the one >> who decides whether to resume a coroutine_handle<>; if the caller decides to destroy() it >> instead, well, that suspend point just turned into an invisible abort anyway, from the >> coroutine's?point of view. >> Example of safely holding a resource across a suspend: https://godbolt.org/z/azTW57qf8 >> <https://godbolt.org/z/azTW57qf8> >> Example of unsafely (leakily) holding the same: https://godbolt.org/z/f4rTG7Kh3 <https:// >> godbolt.org/z/f4rTG7Kh3> >> >> But then I'm afraid I don't understand what feature you're asking for. You can already >> "tell a coroutine to unwind itself" by just destroying the handle you were using to talk >> to it. Why would you also need a stop_token/stop_source to be involved? Are you trying to >> stop someone /else's/ coroutine, like from another thread, without the participation of >> its owner? But then what do you expect the coroutine to do ? report .done() despite not >> having reached the co_return statement, I guess? Which means what ? call .final_suspend() >> on the promise without having first called either `.return_value()` or `.return_void()`? >> Is that something that's possible to do today (except manually)? Why would I want that? >> In particular, adding the ability for the compiler to generate a new and unusual?sequence >> of calls to my promise type means suddenly there's a lot more surface area I'd?need to >> cover in my promise types' unit tests to make sure they're not buggy/leaky even in this >> new special case. > >For precedence, python's asyncio has the exception model for cancellation (an exception of >type asyncio.CancelledError from a suspension point when a task is cancelled). > >One thing it allows is to have asynchronous teardown logic, like gracefully terminating >network sessions, deregistering from mDNS (zeroconf), etc... . > >In comparison simply "dropping" the coroutine (destroying the handle) forces the teardown >to be either synchronous, or schedule teardown tasks elsewhere, but it's unclear to me >where tasks scheduled from the destruction of coroutines can be cleanly joined. From what >I heard Rust (or tokio?) has this cancellation model, but I can't comment on that. > >I know very little about std::execution to comment on that. My gut feeling is that >exceptions are too heavy for C++ for a general cancellation solution (but I agree that it >is ergonomic, I use it with ASIO), the stop_token is probably sufficiently light, but >verbose to use, and just dropping coroutines is missing out on async teardown. > >I wish herbceptions were pursued, I think herbception cancellation in coroutines would hit >the sweet spot. > >Cheers, >L?n?rd >
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals


--
Rhidian De Wit
Software Engineer - Barco