From 76131871da949e82147b087a3675bf12aadc8df1 Mon Sep 17 00:00:00 2001 From: Cra3z Date: Fri, 27 Mar 2026 15:38:48 +0800 Subject: [PATCH 1/4] Implement `get_forward_progress_guarantee` --- .../detail/get_forward_progress_guarantee.hpp | 49 +++++++++++++++++++ include/beman/execution/detail/run_loop.hpp | 7 +++ src/beman/execution/CMakeLists.txt | 2 + src/beman/execution/execution.cppm | 7 +-- .../get_forward_progress_guarantee.cppm | 13 +++++ .../execution/exec-run-loop-general.test.cpp | 3 ++ 6 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 include/beman/execution/detail/get_forward_progress_guarantee.hpp create mode 100644 src/beman/execution/get_forward_progress_guarantee.cppm diff --git a/include/beman/execution/detail/get_forward_progress_guarantee.hpp b/include/beman/execution/detail/get_forward_progress_guarantee.hpp new file mode 100644 index 00000000..4dd7aa4c --- /dev/null +++ b/include/beman/execution/detail/get_forward_progress_guarantee.hpp @@ -0,0 +1,49 @@ +// include/beman/execution/detail/get_forward_progress_guarantee.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION_DETAIL_GET_FORWARD_PROGRESS_GUARANTEE +#define INCLUDED_BEMAN_EXECUTION_DETAIL_GET_FORWARD_PROGRESS_GUARANTEE + +#include +#include +#ifdef BEMAN_HAS_IMPORT_STD +import std; +#else +#include +#endif +#ifdef BEMAN_HAS_MODULES +import beman.execution.detail.forwarding_query; +#else +#include +#endif + +// ---------------------------------------------------------------------------- + +namespace beman::execution { + +enum class forward_progress_guarantee { concurrent, parallel, weakly_parallel }; + +struct get_forward_progress_guarantee_t { + template + requires requires(const Object& object, const get_forward_progress_guarantee_t& tag) { object.query(tag); } + auto operator()(const Object& object) const noexcept -> forward_progress_guarantee { + static_assert(::std::same_as); + return object.query(*this); + } + + template + auto operator()(const Object&) const noexcept -> forward_progress_guarantee { + return forward_progress_guarantee::weakly_parallel; + } + + static constexpr auto query(const ::beman::execution::forwarding_query_t&) noexcept -> bool { return true; } +}; + +inline constexpr get_forward_progress_guarantee_t get_forward_progress_guarantee{}; +} // namespace beman::execution + +// ---------------------------------------------------------------------------- + +#include + +#endif // INCLUDED_BEMAN_EXECUTION_DETAIL_GET_FORWARD_PROGRESS_GUARANTEE \ No newline at end of file diff --git a/include/beman/execution/detail/run_loop.hpp b/include/beman/execution/detail/run_loop.hpp index bb29d675..bdb9360d 100644 --- a/include/beman/execution/detail/run_loop.hpp +++ b/include/beman/execution/detail/run_loop.hpp @@ -19,6 +19,7 @@ import beman.execution.detail.completion_signatures; import beman.execution.detail.env; import beman.execution.detail.get_completion_scheduler; import beman.execution.detail.get_env; +import beman.execution.detail.get_forward_progress_guarantee; import beman.execution.detail.get_stop_token; import beman.execution.detail.immovable; import beman.execution.detail.operation_state; @@ -32,6 +33,7 @@ import beman.execution.detail.unstoppable_token; #include #include #include +#include #include #include #include @@ -113,6 +115,11 @@ class run_loop { auto schedule() noexcept -> sender { return {this->loop}; } auto operator==(const scheduler&) const -> bool = default; + + static constexpr auto query(::beman::execution::get_forward_progress_guarantee_t) noexcept + -> ::beman::execution::forward_progress_guarantee { + return ::beman::execution::forward_progress_guarantee::parallel; + } }; enum class state : unsigned char { starting, running, finishing }; diff --git a/src/beman/execution/CMakeLists.txt b/src/beman/execution/CMakeLists.txt index cfef78f5..36c68048 100644 --- a/src/beman/execution/CMakeLists.txt +++ b/src/beman/execution/CMakeLists.txt @@ -89,6 +89,7 @@ target_sources( ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_domain_early.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_domain_late.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_env.hpp + ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_forward_progress_guarantee.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_scheduler.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_stop_token.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/has_as_awaitable.hpp @@ -275,6 +276,7 @@ if(BEMAN_USE_MODULES) get_domain_late.cppm get_domain.cppm get_env.cppm + get_forward_progress_guarantee.cppm get_scheduler.cppm get_stop_token.cppm has_as_awaitable.cppm diff --git a/src/beman/execution/execution.cppm b/src/beman/execution/execution.cppm index cd2ab544..c4a72dd4 100644 --- a/src/beman/execution/execution.cppm +++ b/src/beman/execution/execution.cppm @@ -31,6 +31,7 @@ export import beman.execution.detail.get_completion_signatures; // [exec.getcomp import beman.execution.detail.get_delegation_scheduler; import beman.execution.detail.get_domain; import beman.execution.detail.get_env; +import beman.execution.detail.get_forward_progress_guarantee; import beman.execution.detail.get_scheduler; import beman.execution.detail.get_stop_token; export import beman.execution.detail.inplace_stop_source; // [stopsource.inplace], class inplace_stop_source @@ -133,14 +134,14 @@ export using ::beman::execution::get_domain_t; export using ::beman::execution::get_scheduler_t; export using ::beman::execution::get_delegation_scheduler_t; export using ::beman::execution::get_await_completion_adaptor_t; -//-dk:TODO export using ::beman::execution::get_forward_progress_guarantee_t; +export using ::beman::execution::get_forward_progress_guarantee_t; export using ::beman::execution::get_domain; export using ::beman::execution::get_scheduler; export using ::beman::execution::get_delegation_scheduler; export using ::beman::execution::get_await_completion_adaptor; -//-dk:TODO export using ::beman::execution::forward_progress_guarantee; -//-dk:TODO export using ::beman::execution::get_forward_progress_guarantee; +export using ::beman::execution::forward_progress_guarantee; +export using ::beman::execution::get_forward_progress_guarantee; export using ::beman::execution::get_env_t; export using ::beman::execution::get_env; diff --git a/src/beman/execution/get_forward_progress_guarantee.cppm b/src/beman/execution/get_forward_progress_guarantee.cppm new file mode 100644 index 00000000..37fbe820 --- /dev/null +++ b/src/beman/execution/get_forward_progress_guarantee.cppm @@ -0,0 +1,13 @@ +module; +// src/beman/execution/get_forward_progress_guarantee.cppm -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +export module beman.execution.detail.get_forward_progress_guarantee; + +namespace beman::execution { +export using beman::execution::forward_progress_guarantee; +export using beman::execution::get_forward_progress_guarantee_t; +export using beman::execution::get_forward_progress_guarantee; +} // namespace beman::execution diff --git a/tests/beman/execution/exec-run-loop-general.test.cpp b/tests/beman/execution/exec-run-loop-general.test.cpp index 7e26cb5f..b24bae9a 100644 --- a/tests/beman/execution/exec-run-loop-general.test.cpp +++ b/tests/beman/execution/exec-run-loop-general.test.cpp @@ -28,4 +28,7 @@ TEST(exec_run_loop_general) { }); static_assert(requires { rl.run(); }); static_assert(requires { rl.finish(); }); + + ASSERT(test_std::get_forward_progress_guarantee(rl.get_scheduler()) == + test_std::forward_progress_guarantee::parallel); } From 5103a00eded84474c79e555969a776efa7238a8a Mon Sep 17 00:00:00 2001 From: Cra3z Date: Fri, 27 Mar 2026 15:48:47 +0800 Subject: [PATCH 2/4] make pre-commit check happy --- .../beman/execution/detail/get_forward_progress_guarantee.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/beman/execution/detail/get_forward_progress_guarantee.hpp b/include/beman/execution/detail/get_forward_progress_guarantee.hpp index 4dd7aa4c..bdc0affa 100644 --- a/include/beman/execution/detail/get_forward_progress_guarantee.hpp +++ b/include/beman/execution/detail/get_forward_progress_guarantee.hpp @@ -46,4 +46,4 @@ inline constexpr get_forward_progress_guarantee_t get_forward_progress_guarantee #include -#endif // INCLUDED_BEMAN_EXECUTION_DETAIL_GET_FORWARD_PROGRESS_GUARANTEE \ No newline at end of file +#endif // INCLUDED_BEMAN_EXECUTION_DETAIL_GET_FORWARD_PROGRESS_GUARANTEE From a2d43a4dbce2d9d50e2b29e45a0477d30f060e2d Mon Sep 17 00:00:00 2001 From: Cra3z Date: Fri, 27 Mar 2026 17:34:37 +0800 Subject: [PATCH 3/4] Implement `sync_wait_with_variant` --- .../detail/sync_wait_with_variant.hpp | 74 ++++++++++++++++++ src/beman/execution/CMakeLists.txt | 2 + src/beman/execution/execution.cppm | 5 +- .../execution/sync_wait_with_variant.cppm | 12 +++ tests/beman/execution/CMakeLists.txt | 1 + .../exec-sync-wait-with-variant.test.cpp | 78 +++++++++++++++++++ 6 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 include/beman/execution/detail/sync_wait_with_variant.hpp create mode 100644 src/beman/execution/sync_wait_with_variant.cppm create mode 100644 tests/beman/execution/exec-sync-wait-with-variant.test.cpp diff --git a/include/beman/execution/detail/sync_wait_with_variant.hpp b/include/beman/execution/detail/sync_wait_with_variant.hpp new file mode 100644 index 00000000..cf2753fc --- /dev/null +++ b/include/beman/execution/detail/sync_wait_with_variant.hpp @@ -0,0 +1,74 @@ +// include/beman/execution/detail/sync_wait_with_variant.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION_DETAIL_SYNC_WAIT_WITH_VARIANT +#define INCLUDED_BEMAN_EXECUTION_DETAIL_SYNC_WAIT_WITH_VARIANT + +#include +#include +#ifdef BEMAN_HAS_IMPORT_STD +import std; +#else +#include +#include +#endif +#ifdef BEMAN_HAS_MODULES +import beman.execution.detail.apply_sender; +import beman.execution.detail.callable; +import beman.execution.detail.call_result_t; +import beman.execution.detail.get_domain_early; +import beman.execution.detail.into_variant; +import beman.execution.detail.sender_in; +import beman.execution.detail.sync_wait; +import beman.execution.detail.value_types_of_t; +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +// ---------------------------------------------------------------------------- + +namespace beman::execution::detail { +template <::beman::execution::sender_in<::beman::execution::detail::sync_wait_env> Sndr> +using sync_wait_with_variant_result_type = + ::std::optional<::beman::execution::value_types_of_t>; +} // namespace beman::execution::detail + +namespace beman::execution { + +struct sync_wait_with_variant_t { + template + requires ::beman::execution::detail::callable< + ::beman::execution::sync_wait_t, + ::beman::execution::detail::call_result_t<::beman::execution::into_variant_t, Sndr>> + auto apply_sender(Sndr&& sndr) const { + using result_type = ::beman::execution::detail::sync_wait_with_variant_result_type; + if (auto opt_value = + ::beman::execution::sync_wait(::beman::execution::into_variant(::std::forward(sndr)))) { + return result_type(::std::move(::std::get<0>(*opt_value))); + } + return result_type(::std::nullopt); + } + + template + requires requires { typename ::beman::execution::detail::sync_wait_with_variant_result_type; } + auto operator()(Sndr&& sndr) const { + return ::beman::execution::apply_sender( + ::beman::execution::detail::get_domain_early(sndr), *this, ::std::forward(sndr)); + } +}; + +inline constexpr sync_wait_with_variant_t sync_wait_with_variant{}; +} // namespace beman::execution + +// ---------------------------------------------------------------------------- + +#include + +#endif // INCLUDED_BEMAN_EXECUTION_DETAIL_SYNC_WAIT_WITH_VARIANT diff --git a/src/beman/execution/CMakeLists.txt b/src/beman/execution/CMakeLists.txt index 36c68048..ccbaa2b4 100644 --- a/src/beman/execution/CMakeLists.txt +++ b/src/beman/execution/CMakeLists.txt @@ -182,6 +182,7 @@ target_sources( ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/suppress_push.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/suspend_complete.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sync_wait.hpp + ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sync_wait_with_variant.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/tag_of_t.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/then.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/transform_sender.hpp @@ -369,6 +370,7 @@ if(BEMAN_USE_MODULES) stopped_as_optional.cppm suspend_complete.cppm sync_wait.cppm + sync_wait_with_variant.cppm tag_of_t.cppm then.cppm transform_sender.cppm diff --git a/src/beman/execution/execution.cppm b/src/beman/execution/execution.cppm index c4a72dd4..5d16e8e1 100644 --- a/src/beman/execution/execution.cppm +++ b/src/beman/execution/execution.cppm @@ -69,6 +69,7 @@ import beman.execution.detail.stoppable_source; import beman.execution.detail.stopped_as_error; import beman.execution.detail.stopped_as_optional; import beman.execution.detail.sync_wait; +import beman.execution.detail.sync_wait_with_variant; export import beman.execution.detail.tag_of_t; // [exec.getcomplsigs], completion signatures import beman.execution.detail.then; import beman.execution.detail.transform_sender; @@ -232,10 +233,10 @@ export using ::beman::execution::run_loop; // [exec.consumers], consumers export using ::beman::execution::sync_wait_t; -//-dk:TODO export using ::beman::execution::sync_wait_with_variant_t; +export using ::beman::execution::sync_wait_with_variant_t; export using ::beman::execution::sync_wait; -//-dk:TODO export using ::beman::execution::sync_wait_with_variant; +export using ::beman::execution::sync_wait_with_variant; // [exec.as.awaitable] export using ::beman::execution::as_awaitable_t; diff --git a/src/beman/execution/sync_wait_with_variant.cppm b/src/beman/execution/sync_wait_with_variant.cppm new file mode 100644 index 00000000..b1f14681 --- /dev/null +++ b/src/beman/execution/sync_wait_with_variant.cppm @@ -0,0 +1,12 @@ +module; +// src/beman/execution/sync_wait_with_variant.cppm -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +export module beman.execution.detail.sync_wait_with_variant; + +namespace beman::execution { +export using beman::execution::sync_wait_with_variant_t; +export using beman::execution::sync_wait_with_variant; +} // namespace beman::execution diff --git a/tests/beman/execution/CMakeLists.txt b/tests/beman/execution/CMakeLists.txt index ca30e35f..08530378 100644 --- a/tests/beman/execution/CMakeLists.txt +++ b/tests/beman/execution/CMakeLists.txt @@ -61,6 +61,7 @@ list( exec-stopped-as-error.test exec-stopped-as-optional.test exec-sync-wait.test + exec-sync-wait-with-variant.test exec-then.test exec-utils-cmplsigs.test exec-when-all.test diff --git a/tests/beman/execution/exec-sync-wait-with-variant.test.cpp b/tests/beman/execution/exec-sync-wait-with-variant.test.cpp new file mode 100644 index 00000000..ce07b911 --- /dev/null +++ b/tests/beman/execution/exec-sync-wait-with-variant.test.cpp @@ -0,0 +1,78 @@ +// src/beman/execution/tests/exec-sync-wait-with-variant.test.cpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include +#ifdef BEMAN_HAS_MODULES +import beman.execution; +import beman.execution.detail; +#else +#include +#endif + +// ---------------------------------------------------------------------------- + +namespace { + +template +struct just_variant { + using sender_concept = test_std::sender_t; + using completion_signatures = test_std::completion_signatures; + + template + static consteval auto get_completion_signatures() -> completion_signatures { + return {}; + } + + template + struct state { + using operation_state_concept = test_std::operation_state_t; + + auto start() & noexcept -> void { + std::visit([this](auto v) { test_std::set_value(std::move(receiver), std::move(v)); }, std::move(var)); + } + + std::variant var; + Receiver receiver; + }; + + template + auto connect(Receiver receiver) && noexcept -> state { + return {std::move(var), ::std::move(receiver)}; + } + + std::variant var; +}; + +auto test_sync_wait_with_variant_multi_value() -> void { + auto result1 = test_std::sync_wait_with_variant(just_variant{114}); + static_assert(std::same_as, std::tuple>>>); + ASSERT(result1.has_value()); + ASSERT(result1.value().index() == 0); + ASSERT(std::get<0>(*result1) == std::tuple{114}); + + auto result2 = test_std::sync_wait_with_variant(just_variant{"hello"}); + static_assert( + std::same_as, std::tuple>>>); + ASSERT(result2.has_value()); + ASSERT(result2.value().index() == 1); + ASSERT(std::get<1>(*result2) == std::tuple{"hello"}); +} + +auto test_sync_wait_with_variant_single_value() -> void { + auto value = test_std::sync_wait_with_variant(test_std::just(514)); + static_assert(std::same_as>>>); + ASSERT(value.has_value()); + ASSERT(std::get<0>(*value) == std::tuple{514}); +} + +} // namespace + +TEST(exec_sync_wait_with_variant) { + test_sync_wait_with_variant_multi_value(); + test_sync_wait_with_variant_single_value(); +} From dcf9a164e4d85627244dc3f400cd2058f12e36be Mon Sep 17 00:00:00 2001 From: Cra3z Date: Fri, 27 Mar 2026 17:56:21 +0800 Subject: [PATCH 4/4] Add missing header --- include/beman/execution/execution.hpp | 10 ++++++++++ .../execution/exec-sync-wait-with-variant.test.cpp | 1 + 2 files changed, 11 insertions(+) diff --git a/include/beman/execution/execution.hpp b/include/beman/execution/execution.hpp index b0225977..a615c5e7 100644 --- a/include/beman/execution/execution.hpp +++ b/include/beman/execution/execution.hpp @@ -20,10 +20,12 @@ import beman.execution.detail.counting_scope; import beman.execution.detail.env; import beman.execution.detail.forwarding_query; import beman.execution.detail.get_allocator; +import beman.execution.detail.get_await_completion_adaptor; import beman.execution.detail.get_completion_scheduler; import beman.execution.detail.get_completion_signatures; import beman.execution.detail.get_delegation_scheduler; import beman.execution.detail.get_domain; +import beman.execution.detail.get_forward_progress_guarantee; import beman.execution.detail.get_env; import beman.execution.detail.get_scheduler; import beman.execution.detail.get_stop_token; @@ -52,7 +54,10 @@ import beman.execution.detail.spawn; //-dk:TODO? import beman.execution.detail.split; import beman.execution.detail.start; import beman.execution.detail.starts_on; +import beman.execution.detail.stopped_as_error; +import beman.execution.detail.stopped_as_optional; import beman.execution.detail.sync_wait; +import beman.execution.detail.sync_wait_with_variant; import beman.execution.detail.then; import beman.execution.detail.valid_completion_for; import beman.execution.detail.valid_completion_signatures; @@ -73,10 +78,12 @@ import beman.execution.detail.write_env; #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -105,7 +112,10 @@ import beman.execution.detail.write_env; //-dk:TODO? #include #include #include +#include +#include #include +#include #include #include #include diff --git a/tests/beman/execution/exec-sync-wait-with-variant.test.cpp b/tests/beman/execution/exec-sync-wait-with-variant.test.cpp index ce07b911..0fee6c29 100644 --- a/tests/beman/execution/exec-sync-wait-with-variant.test.cpp +++ b/tests/beman/execution/exec-sync-wait-with-variant.test.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include