C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Automatic Coroutine Cancellation

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Thu, 9 Apr 2026 15:23:23 +0100
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_at_[hidden] <mailto:std-proposals_at_[hidden]>> 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

>
> HTH,
> Arthur
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2026-04-09 14:23:31