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
27 changes: 19 additions & 8 deletions include/beman/execution/detail/when_all.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ import beman.execution.detail.meta.size;
import beman.execution.detail.meta.to;
import beman.execution.detail.meta.transform;
import beman.execution.detail.meta.unique;
import beman.execution.detail.never_stop_token;
import beman.execution.detail.on_stop_request;
import beman.execution.detail.prop;
import beman.execution.detail.sender;
import beman.execution.detail.sender_in;
import beman.execution.detail.sends_stopped;
Expand Down Expand Up @@ -85,6 +87,7 @@ import beman.execution.detail.value_types_of_t;
#include <beman/execution/detail/meta_transform.hpp>
#include <beman/execution/detail/meta_unique.hpp>
#include <beman/execution/detail/on_stop_request.hpp>
#include <beman/execution/detail/prop.hpp>
#include <beman/execution/detail/sender.hpp>
#include <beman/execution/detail/sender_in.hpp>
#include <beman/execution/detail/sends_stopped.hpp>
Expand Down Expand Up @@ -117,13 +120,20 @@ concept valid_when_all_sender = ::beman::execution::dependent_sender<Sender> ||
inline constexpr auto make_when_all_env = [](const ::beman::execution::inplace_stop_source& stop_src,
const auto& env) noexcept {
return ::beman::execution::detail::join_env(
::beman::execution::detail::make_env(::beman::execution::get_stop_token, stop_src.get_token()), env);
::beman::execution::env{::beman::execution::prop{::beman::execution::get_stop_token, stop_src.get_token()}},
env);
};

template <typename Env>
using when_all_env =
decltype(make_when_all_env(::std::declval<::beman::execution::inplace_stop_source>(), ::std::declval<Env>()));

static_assert(std::same_as<::beman::execution::never_stop_token,
decltype(::beman::execution::get_stop_token(::std::declval<::beman::execution::env<>>()))>);
static_assert(std::same_as<::beman::execution::inplace_stop_token,
decltype(::beman::execution::get_stop_token(
::std::declval<when_all_env<::beman::execution::env<>>>()))>);

struct when_all_t {
template <::beman::execution::sender... Sender>
requires(0u != sizeof...(Sender)) && (... && beman::execution::detail::valid_when_all_sender<Sender>) &&
Expand Down Expand Up @@ -155,13 +165,14 @@ struct when_all_t {

using value_types =
typename ::beman::execution::detail::when_all_value_types<::beman::execution::detail::meta::combine<
::beman::execution::
value_types_of_t<Sender, Env, ::beman::execution::detail::type_list, ::std::type_identity_t>...>>::
type;
::beman::execution::value_types_of_t<Sender,
when_all_env<Env>,
::beman::execution::detail::type_list,
::std::type_identity_t>...>>::type;
using error_types = ::beman::execution::detail::meta::unique<::beman::execution::detail::meta::combine<
::beman::execution::error_types_of_t<Sender, Env, error_comps>...>>;
::beman::execution::error_types_of_t<Sender, when_all_env<Env>, error_comps>...>>;
using stopped_types =
::std::conditional_t<(false || ... || ::beman::execution::sends_stopped<Sender, Env>),
::std::conditional_t<(false || ... || ::beman::execution::sends_stopped<Sender, when_all_env<Env>>),
::beman::execution::completion_signatures<::beman::execution::set_stopped_t()>,
::beman::execution::completion_signatures<>>;
using type = ::beman::execution::detail::meta::combine<value_types, error_types, stopped_types>;
Expand Down Expand Up @@ -202,7 +213,7 @@ struct when_all_t {
template <typename Receiver, typename... Sender>
struct state_type {
struct nonesuch {};
using env_t = ::beman::execution::env_of_t<Receiver>;
using env_t = when_all_env<::beman::execution::env_of_t<Receiver>>;
using copy_fail = ::std::conditional_t<
(... && ::beman::execution::value_types_of_t<Sender,
env_t,
Expand Down Expand Up @@ -291,7 +302,7 @@ struct when_all_t {

template <typename Receiver>
struct make_state {
template <::beman::execution::sender_in<::beman::execution::env_of_t<Receiver>>... Sender>
template <::beman::execution::sender_in<when_all_env<::beman::execution::env_of_t<Receiver>>>... Sender>
auto operator()(auto, auto, Sender&&...) const {
return state_type<Receiver, Sender...>{};
}
Expand Down
22 changes: 22 additions & 0 deletions tests/beman/execution/exec-read-env.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@
#include <test/execution.hpp>
#ifdef BEMAN_HAS_MODULES
import beman.execution;
import beman.execution.detail.join_env;
#else
#include <beman/execution/detail/read_env.hpp>
#include <beman/execution/detail/common.hpp>
#include <beman/execution/detail/get_domain.hpp>
#include <beman/execution/detail/join_env.hpp>
#include <beman/execution/detail/sender.hpp>
#include <beman/execution/detail/sender_in.hpp>
#include <beman/execution/detail/receiver.hpp>
#include <beman/execution/detail/connect.hpp>
#include <beman/execution/detail/start.hpp>
#include <beman/execution/detail/get_stop_token.hpp>
#include <beman/execution/detail/sync_wait.hpp>
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the non-modules include path this test uses test_std::prop but does not include <beman/execution/detail/prop.hpp> directly, relying on it being pulled in transitively (currently via <beman/execution/detail/when_all.hpp>). Other tests that use test_std::prop include prop.hpp explicitly (e.g. tests/beman/execution/exec-affine-on.test.cpp:19). Consider adding the direct include to avoid brittle header dependencies.

Suggested change
#include <beman/execution/detail/sync_wait.hpp>
#include <beman/execution/detail/sync_wait.hpp>
#include <beman/execution/detail/prop.hpp>

Copilot uses AI. Check for mistakes.
#include <beman/execution/detail/when_all.hpp>
#endif

// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -74,7 +78,25 @@ auto test_read_env_completions() -> void {
auto r{test_std::read_env(test_std::get_stop_token)};
test::check_type<test_std::completion_signatures<test_std::set_value_t(test_std::never_stop_token)>>(
test_std::get_completion_signatures<decltype(r), test_std::env<>>());
test::check_type<test_std::completion_signatures<test_std::set_value_t(test_std::never_stop_token)>>(
test_std::get_completion_signatures<decltype(r), decltype(test_std::env{})>());
test::check_type<test_std::completion_signatures<test_std::set_value_t(test_std::inplace_stop_token)>>(
test_std::get_completion_signatures<decltype(r),
decltype(test_std::env{
test_std::prop{test_std::get_stop_token,
std::declval<test_std::inplace_stop_token>()}})>());
test::check_type<test_std::completion_signatures<test_std::set_value_t(test_std::inplace_stop_token)>>(
test_std::get_completion_signatures<
decltype(r),
decltype(test_detail::join_env(
test_std::env{test_std::prop{test_std::get_stop_token, std::declval<test_std::inplace_stop_token>()}},
test_std::env{
test_std::prop{test_std::get_stop_token, std::declval<test_std::never_stop_token>()}}))>());
Comment on lines +89 to +94
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test now uses test_detail::join_env(...), but in the BEMAN_HAS_MODULES configuration the file only imports beman.execution (which does not re-export detail::join_env). This will fail to compile with modules enabled. Add import beman.execution.detail; (or import beman.execution.detail.join_env;) under the #ifdef BEMAN_HAS_MODULES branch, or avoid referencing detail::join_env in this test.

Copilot uses AI. Check for mistakes.
test::use(r);

test_std::sync_wait(test_std::read_env(test_std::get_stop_token));
test_std::sync_wait(test_std::when_all(test_std::read_env(test_std::get_stop_token)));
test_std::sync_wait(test_std::when_all(test_std::read_env(test_std::get_scheduler)));
}
} // namespace

Expand Down
5 changes: 4 additions & 1 deletion tests/beman/execution/exec-when-all.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@ auto test_when_all() -> void {
await_cancel(),
add_value{test_std::just_stopped()},
test_std::just(true, 3.5));

test_std::sync_wait(test_std::read_env(test_std::get_stop_token));
test_std::sync_wait(
test_std::when_all(test_std::read_env(test_std::get_stop_token) | test_std::then([](auto&&) {})));
}

auto test_when_all_with_variant() -> void {
Expand Down Expand Up @@ -265,7 +269,6 @@ TEST(exec_when_all) {
static_assert(std::same_as<const test_std::when_all_with_variant_t, decltype(test_std::when_all_with_variant)>);

try {

test_when_all();
test_when_all_with_variant();
} catch (...) {
Expand Down
Loading