Date: Tue, 14 Apr 2026 19:58:36 +0800 (CST)
I used to think the same way, but let me tell you:
Since C++20, coroutines have had several critical design flaws. I've submitted code multiple times to demonstrate and address these issues, but they persist and have even been inherited by std::execution and std::task.
Other open-source third-party libraries have also inherited these coroutine design flaws, including the lack of a manual resume method and the failure to decouple coroutines from I/O.
You can take a look at my code, the design logic is highly abstract yet very simple, and the core logic has been rigorously tested.
If you insist on using the standard library, you might as well wait for C++29.
At 2026-04-14 18:05:26, "Rhidian De Wit" <rhidiandewit_at_[hidden]> wrote:
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_at_[hidden]>:
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:
A co_event that supports manual suspension and resumption, giving you full control!!!
wait_for_all, wait_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_at_lenardszolnoki.com>
>To: std-proposals_at_[hidden]
>Subject: Re: [std-proposals] Automatic Coroutine Cancellation
>Message-ID: <a94be06c-ec0a-444c-8982-c1f6511e1921_at_[hidden]>
>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_at_lists.isocpp.org <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
>
Since C++20, coroutines have had several critical design flaws. I've submitted code multiple times to demonstrate and address these issues, but they persist and have even been inherited by std::execution and std::task.
Other open-source third-party libraries have also inherited these coroutine design flaws, including the lack of a manual resume method and the failure to decouple coroutines from I/O.
You can take a look at my code, the design logic is highly abstract yet very simple, and the core logic has been rigorously tested.
If you insist on using the standard library, you might as well wait for C++29.
At 2026-04-14 18:05:26, "Rhidian De Wit" <rhidiandewit_at_[hidden]> wrote:
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_at_[hidden]>:
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:
A co_event that supports manual suspension and resumption, giving you full control!!!
wait_for_all, wait_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_at_lenardszolnoki.com>
>To: std-proposals_at_[hidden]
>Subject: Re: [std-proposals] Automatic Coroutine Cancellation
>Message-ID: <a94be06c-ec0a-444c-8982-c1f6511e1921_at_[hidden]>
>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_at_lists.isocpp.org <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
>
-- Std-Proposals mailing list Std-Proposals_at_[hidden] https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals -- Rhidian De Wit Software Engineer - Barco
Received on 2026-04-14 11:58:44
