Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 21 additions & 23 deletions include/stdexec/__detail/__when_all.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,15 @@ namespace STDEXEC {
__on_stop_.reset();
// All child operations have completed and arrived at the barrier.
switch (__state_.load(__std::memory_order_relaxed)) {
case __stopped:
if constexpr (_SendsStopped) {
STDEXEC::set_stopped(static_cast<_Receiver&&>(__rcvr_));
break;
}
// This is reachable because the stop callback sets __stopped whether
// or not any child can send set_stopped, therefore we handle this the
// same as __started
[[fallthrough]];
case __started:
if constexpr (!__std::same_as<_ValuesTuple, __ignore>) {
// All child operations completed successfully:
Expand All @@ -298,13 +307,6 @@ namespace STDEXEC {
__mk_completion_fn(set_error, __rcvr_), static_cast<_ErrorsVariant&&>(__errors_));
}
break;
case __stopped:
if constexpr (_SendsStopped) {
STDEXEC::set_stopped(static_cast<_Receiver&&>(__rcvr_));
} else {
STDEXEC_UNREACHABLE();
}
break;
default:;
}
}
Expand Down Expand Up @@ -489,23 +491,19 @@ namespace STDEXEC {
__state.__stop_source_.request_stop();
}
} else if constexpr (!__same_as<_ValuesTuple, __ignore>) {
// We only need to bother recording the completion values
// if we're not already in the "error" or "stopped" state.
if (__state.__state_.load() == __started) {
auto& __opt_values = STDEXEC::__get<_Index::value>(__state.__values_);
using _Tuple = __decayed_tuple<_Args...>;
static_assert(
__same_as<decltype(*__opt_values), _Tuple&>,
"One of the senders in this when_all() is fibbing about what types it sends");
if constexpr ((__nothrow_decay_copyable<_Args> && ...)) {
auto& __opt_values = STDEXEC::__get<_Index::value>(__state.__values_);
using _Tuple = __decayed_tuple<_Args...>;
static_assert(
__same_as<decltype(*__opt_values), _Tuple&>,
"One of the senders in this when_all() is fibbing about what types it sends");
if constexpr ((__nothrow_decay_copyable<_Args> && ...)) {
__opt_values.emplace(_Tuple{static_cast<_Args&&>(__args)...});
} else {
STDEXEC_TRY {
__opt_values.emplace(_Tuple{static_cast<_Args&&>(__args)...});
} else {
STDEXEC_TRY {
__opt_values.emplace(_Tuple{static_cast<_Args&&>(__args)...});
}
STDEXEC_CATCH_ALL {
__set_error(__state, std::current_exception());
}
}
STDEXEC_CATCH_ALL {
__set_error(__state, std::current_exception());
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/stdexec/algos/adaptors/test_when_all.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ namespace {
ex::completion_signatures_of_t<decltype(snd), decltype(env)>,
ex::completion_signatures<ex::set_value_t()>
>);
auto op = ex::connect(snd, expect_void_receiver{});
auto op = ex::connect(snd, expect_void_receiver(env));
ex::start(op);
}

Expand Down