From 7ca8600b8cc921f9bbd8b54e540f585d71bab526 Mon Sep 17 00:00:00 2001 From: Cra3z Date: Mon, 13 Jul 2026 14:14:08 +0800 Subject: [PATCH 1/2] Fix when_all_with_variant sender attribute and completion-signatures --- .../detail/when_all_with_variant.hpp | 96 +++++++++++++++++++ .../exec-parallel-scheduler.test.cpp | 4 +- 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/include/beman/execution/detail/when_all_with_variant.hpp b/include/beman/execution/detail/when_all_with_variant.hpp index 22c4a7e9..ce6c3140 100644 --- a/include/beman/execution/detail/when_all_with_variant.hpp +++ b/include/beman/execution/detail/when_all_with_variant.hpp @@ -12,20 +12,38 @@ import std; #include #endif #ifdef BEMAN_HAS_MODULES +import beman.execution.detail.basic_sender; +import beman.execution.detail.common_domain; +import beman.execution.detail.compl_domain; +import beman.execution.detail.default_impls; +import beman.execution.detail.env; import beman.execution.detail.forward_like; +import beman.execution.detail.get_completion_domain; +import beman.execution.detail.get_completion_signatures; import beman.execution.detail.into_variant; import beman.execution.detail.make_sender; import beman.execution.detail.sender; import beman.execution.detail.sender_for; import beman.execution.detail.set_value; +import beman.execution.detail.set_error; +import beman.execution.detail.set_stopped; import beman.execution.detail.when_all; #else +#include +#include +#include +#include +#include #include +#include +#include #include #include #include #include #include +#include +#include #include #endif @@ -45,6 +63,84 @@ struct when_all_with_variant_t { auto operator()(Sender&&... sender) const { return ::beman::execution::detail::make_sender(*this, {}, ::std::forward(sender)...); } + + private: + template + struct get_signatures; + template + struct get_signatures : get_signatures> {}; + template + struct get_signatures<::beman::execution::detail:: + basic_sender<::beman::execution::detail::when_all_with_variant_t, Data, Children...>, + Env> { + + static consteval auto get() { + using sndr_t = decltype(::beman::execution::when_all( + ::beman::execution::into_variant(::std::declval())...)); + return ::beman::execution::get_completion_signatures(); + } + }; + + template + struct attrs { + template + using child_domain_t = + ::beman::execution::detail::common_domain_t<::beman::execution::detail::compl_domain_of_t< + Tag, + ::std::invoke_result_t<::beman::execution::into_variant_t, Children>, + Env...>...>; + + template + requires requires { typename child_domain_t<::beman::execution::set_value_t, Env...>; } + static auto query(::beman::execution::get_completion_domain_t<::beman::execution::set_value_t>, + const Env&...) noexcept -> child_domain_t<::beman::execution::set_value_t, Env...> { + return {}; + } + + template + requires requires { + typename ::beman::execution::detail::common_domain_t< + child_domain_t<::beman::execution::set_value_t, Env...>, + child_domain_t<::beman::execution::set_error_t, Env...>, + child_domain_t<::beman::execution::set_stopped_t, Env...>>; + } + static auto query(::beman::execution::get_completion_domain_t<::beman::execution::set_error_t>, + const Env&...) noexcept + -> ::beman::execution::detail::common_domain_t, + child_domain_t<::beman::execution::set_error_t, Env...>, + child_domain_t<::beman::execution::set_stopped_t, Env...>> { + return {}; + } + + template + requires requires { + typename ::beman::execution::detail::common_domain_t< + child_domain_t<::beman::execution::set_value_t, Env...>, + child_domain_t<::beman::execution::set_stopped_t, Env...>>; + } + static auto query(::beman::execution::get_completion_domain_t<::beman::execution::set_stopped_t>, + const Env&...) noexcept + -> ::beman::execution::detail::common_domain_t, + child_domain_t<::beman::execution::set_stopped_t, Env...>> { + return {}; + } + }; + + public: + template <::beman::execution::sender Sender, typename... Env> + static consteval auto get_completion_signatures() { + return get_signatures<::std::remove_cvref_t, Env...>::get(); + } + + struct impls_for : ::beman::execution::detail::default_impls { + struct get_attrs_impl { + template + auto operator()(const auto&, const Children&...) const noexcept { + return attrs{}; + } + }; + static constexpr auto get_attrs{get_attrs_impl{}}; + }; }; } // namespace beman::execution::detail diff --git a/tests/beman/execution/exec-parallel-scheduler.test.cpp b/tests/beman/execution/exec-parallel-scheduler.test.cpp index 4b17ae79..bdbdcc2b 100644 --- a/tests/beman/execution/exec-parallel-scheduler.test.cpp +++ b/tests/beman/execution/exec-parallel-scheduler.test.cpp @@ -160,9 +160,9 @@ struct thread_pool_backend : replaceability::parallel_scheduler_backend { const std::size_t n = chunk_count - i; // the count of `bulk_task` which are not enqueued successfully guard.unlock(); - if (n == 1uz) { + if (i == 1uz) { cv.notify_one(); - } else if (n > 1uz) { + } else if (i > 1uz) { cv.notify_all(); } From f08b3543f92e96936983f8a5900d0dae82773a10 Mon Sep 17 00:00:00 2001 From: Cra3z Date: Mon, 13 Jul 2026 16:15:02 +0800 Subject: [PATCH 2/2] Update test --- tests/beman/execution/exec-dependent-sender.test.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/beman/execution/exec-dependent-sender.test.cpp b/tests/beman/execution/exec-dependent-sender.test.cpp index d5ad7e7b..feb9634a 100644 --- a/tests/beman/execution/exec-dependent-sender.test.cpp +++ b/tests/beman/execution/exec-dependent-sender.test.cpp @@ -11,6 +11,8 @@ import beman.execution; #include #include #include +#include +#include #endif TEST(exec_dependent_sender) { @@ -26,4 +28,12 @@ TEST(exec_dependent_sender) { test_std::read_env(test_std::get_scheduler), [](auto sched) noexcept { return test_std::just(sched); }) | test_std::then([](auto sched) noexcept {}))>); + static_assert( + test_std::dependent_sender); + static_assert(test_std::dependent_sender); + static_assert(!test_std::dependent_sender); + static_assert(!test_std::dependent_sender); + static_assert(test_std::dependent_sender); }