Description
when_all
's start
function executes this code:
state.on_stop.emplace(
get_stop_token(get_env(rcvr)),
on-stop-request{state.stop_src});
if (state.stop_src.stop_requested()) {
state.on_stop.reset();
set_stopped(std::move(rcvr));
} else {
(start(ops), ...);
}
...so it checks the receivers stop token and calls set_stopped
if this is set. The problem with this is that I as the user cannot really disable this behavior. If I wrap the when_all
in unstoppable
the whole thing cannot be stopped any longer. But I might want the child operations to react to cancellation requests from the outside.
Opting into this behavior is much easier, by wrapping the when_all
sender into a sender that does this checking.
This makes it sometimes impossible to use when_all
as a building block for other things. For example, the current wording of let_async_scope
(https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3296r1.html) uses when_all
to ensure the async scope is joined, like this:
auto result_sender = when_all(just_error(std::current_exception()), state.scope.join());
...the problem with this is that when the environment sent a cancellation request earlier, neither of the two senders will be called, not even the async scope's join sender, making this incorrect, I believe.