From 22884dc750407e662e4743e171f4e402ca27517e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Tue, 11 Aug 2026 22:11:39 +0100 Subject: [PATCH 1/6] reviewed MANDATE-NOTHROW and AS-CONST use --- docs/implementation-status.md | 6 +++--- .../beman/execution/detail/forwarding_query.hpp | 3 ++- .../detail/get_await_completion_adaptor.hpp | 5 ++--- .../execution/detail/get_completion_scheduler.hpp | 2 ++ .../execution/detail/get_delegation_scheduler.hpp | 3 ++- include/beman/execution/detail/get_domain.hpp | 14 +++++++++++++- include/beman/execution/detail/get_env.hpp | 11 ++++++----- .../detail/get_forward_progress_guarantee.hpp | 1 + include/beman/execution/detail/get_scheduler.hpp | 2 ++ .../beman/execution/detail/get_start_scheduler.hpp | 5 +++-- include/beman/execution/detail/get_stop_token.hpp | 3 ++- include/beman/execution/detail/set_error.hpp | 6 ++---- include/beman/execution/detail/set_stopped.hpp | 6 ++---- include/beman/execution/detail/set_value.hpp | 3 +++ include/beman/execution/detail/start.hpp | 13 ++----------- tests/beman/execution/exec-fwd-env.test.cpp | 2 +- .../exec-get-delegation-scheduler.test.cpp | 2 +- tests/beman/execution/exec-get-domain.test.cpp | 2 +- tests/beman/execution/exec-get-stop-token.test.cpp | 3 ++- tests/beman/execution/exec-opstate.test.cpp | 3 ++- tests/beman/execution/exec-recv.test.cpp | 3 ++- tests/beman/execution/exec-set-error.test.cpp | 5 +++-- tests/beman/execution/exec-set-stopped.test.cpp | 2 +- 23 files changed, 60 insertions(+), 45 deletions(-) diff --git a/docs/implementation-status.md b/docs/implementation-status.md index cc64333e..3dce58c0 100644 --- a/docs/implementation-status.md +++ b/docs/implementation-status.md @@ -15,13 +15,13 @@ The indicators come in groups of threes: Each section containing subelements reflects the state of the "worst" element. # 🔴🔴🔴 [exec](https://wg21.link/exec) Execution control library -## 🚧✅✅ [exec.general](https://wg21.link/exec.general) General +## ✅✅✅ [exec.general](https://wg21.link/exec.general) General -- 🚧❎❎ [MANDATE-NOTHROW(expr)](https://wg21.link/exec.general#5) ⇒ noexcept(expr) is `true` +- ❎❎❎ [MANDATE-NOTHROW(expr)](https://wg21.link/exec.general#5) ⇒ noexcept(expr) is `true` - ✅✅✅ [movable-value<T>](https://wg21.link/exec.general#6): [`movable_value.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/movable_value.hpp) - ✅✅✅ [MATCHING-SIG<F1, F2>](https://wg21.link/exec.general#7): [`matching_sig.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/matching_sig.hpp) - ✅✅✅ [AS-EXCEPT-PTR(error)](https://wg21.link/exec.general#8): [`as_except_ptr.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/as_except_ptr.hpp) -- 🚧❎❎ [as-const(error)](https://wg21.link/exec.general#9): [std::as_const](https://wg21.link/utility.as.const)(error) +- ❎❎❎ [as-const(error)](https://wg21.link/exec.general#9): [std::as_const](https://wg21.link/utility.as.const)(error) ## 🚧✅✅ [exec.queryable](https://wg21.link/exec.queryable) Query and queryables ### 🚧❎❎ [exec.queryable.general](https://wg21.link/exec.queryable.general) General diff --git a/include/beman/execution/detail/forwarding_query.hpp b/include/beman/execution/detail/forwarding_query.hpp index bf22ea34..634c9dde 100644 --- a/include/beman/execution/detail/forwarding_query.hpp +++ b/include/beman/execution/detail/forwarding_query.hpp @@ -24,9 +24,10 @@ namespace beman::execution::detail { struct forwarding_query_t { template requires requires(Object&& object, const forwarding_query_t& query) { - { ::std::forward(object).query(query) } noexcept -> ::std::same_as; + { ::std::forward(object).query(query) } -> ::std::same_as; } constexpr auto operator()(Object&& object) const noexcept -> bool { + static_assert(noexcept(::std::forward(object).query(*this))); return ::std::forward(object).query(*this); } template diff --git a/include/beman/execution/detail/get_await_completion_adaptor.hpp b/include/beman/execution/detail/get_await_completion_adaptor.hpp index d0a7cf5e..d8e79ac0 100644 --- a/include/beman/execution/detail/get_await_completion_adaptor.hpp +++ b/include/beman/execution/detail/get_await_completion_adaptor.hpp @@ -21,10 +21,9 @@ import beman.execution.detail.forwarding_query; namespace beman::execution { struct get_await_completion_adaptor_t { template - requires requires(Env&& env, const get_await_completion_adaptor_t& g) { - { ::std::as_const(env).query(g) } noexcept; - } + requires requires(Env&& env, const get_await_completion_adaptor_t& g) { ::std::as_const(env).query(g); } auto operator()(Env&& env) const noexcept { + static_assert(noexcept(::std::as_const(env).query(*this))); return ::std::as_const(env).query(*this); } static constexpr auto query(const ::beman::execution::forwarding_query_t&) noexcept -> bool { return true; } diff --git a/include/beman/execution/detail/get_completion_scheduler.hpp b/include/beman/execution/detail/get_completion_scheduler.hpp index cb7cba53..62bf5394 100644 --- a/include/beman/execution/detail/get_completion_scheduler.hpp +++ b/include/beman/execution/detail/get_completion_scheduler.hpp @@ -80,6 +80,8 @@ template ::beman::execution::scheduler auto get_completion_scheduler_t::operator()(const Q& q, const E&... e) const noexcept { if constexpr (::beman::execution::detail::compl_sched_recurse_queryable) { + static_assert(noexcept( + ::beman::execution::detail::recurse_query(::beman::execution::detail::try_query(q, *this, e...), e...))); return ::beman::execution::detail::recurse_query(::beman::execution::detail::try_query(q, *this, e...), e...); } else { static_assert(::beman::execution::scheduler); diff --git a/include/beman/execution/detail/get_delegation_scheduler.hpp b/include/beman/execution/detail/get_delegation_scheduler.hpp index 7c070e06..9364b9d3 100644 --- a/include/beman/execution/detail/get_delegation_scheduler.hpp +++ b/include/beman/execution/detail/get_delegation_scheduler.hpp @@ -24,9 +24,10 @@ namespace beman::execution { struct get_delegation_scheduler_t { template requires requires(Env&& env, const get_delegation_scheduler_t& g) { - { auto(::std::as_const(env).query(g)) } noexcept -> ::beman::execution::scheduler; + { auto(::std::as_const(env).query(g)) } -> ::beman::execution::scheduler; } auto operator()(Env&& env) const noexcept { + static_assert(noexcept(::std::as_const(env).query(*this))); return ::std::as_const(env).query(*this); } constexpr auto query(const ::beman::execution::forwarding_query_t&) const noexcept -> bool { return true; } diff --git a/include/beman/execution/detail/get_domain.hpp b/include/beman/execution/detail/get_domain.hpp index d774a526..e0ab08f8 100644 --- a/include/beman/execution/detail/get_domain.hpp +++ b/include/beman/execution/detail/get_domain.hpp @@ -35,12 +35,24 @@ struct get_domain_t : ::beman::execution::forwarding_query_t { template constexpr auto operator()(Env&& env) const noexcept { if constexpr (requires { ::std::as_const(env).query(*this); }) { - return ::std::as_const(env).query(*this); + static_assert(noexcept(::std::as_const(env).query(*this))); + return auto(::std::as_const(env).query(*this)); } else if constexpr (requires { ::beman::execution::get_completion_domain<::beman::execution::set_value_t>( ::beman::execution::get_scheduler(env), ::beman::execution::detail::hide_sched(env)); }) { + static_assert(noexcept(::beman::execution::get_completion_domain<::beman::execution::set_value_t>( + ::beman::execution::get_scheduler(env), ::beman::execution::detail::hide_sched(env)))); + return ::beman::execution::get_completion_domain<::beman::execution::set_value_t>( + ::beman::execution::get_scheduler(env), ::beman::execution::detail::hide_sched(env)); + } else if constexpr (requires { + ::beman::execution::get_completion_domain<::beman::execution::set_value_t>( + ::beman::execution::get_scheduler(env), + ::beman::execution::detail::hide_sched(env)); + }) { + static_assert(noexcept(::beman::execution::get_completion_domain<::beman::execution::set_value_t>( + ::beman::execution::get_scheduler(env), ::beman::execution::detail::hide_sched(env)))); return ::beman::execution::get_completion_domain<::beman::execution::set_value_t>( ::beman::execution::get_scheduler(env), ::beman::execution::detail::hide_sched(env)); } else { diff --git a/include/beman/execution/detail/get_env.hpp b/include/beman/execution/detail/get_env.hpp index cfb910c4..52fcb32a 100644 --- a/include/beman/execution/detail/get_env.hpp +++ b/include/beman/execution/detail/get_env.hpp @@ -29,11 +29,12 @@ struct get_env_t { std::remove_cvref_t&>().get_env())>>) auto operator()(Object&& object) const noexcept -> decltype(auto) { ::std::add_const_t<::std::remove_cvref_t>& obj{object}; - if constexpr (requires { obj.get_env(); }) { - static_assert(noexcept(obj.get_env()), "get_env requires the expression to be noexcept"); - static_assert(::beman::execution::detail::queryable>, - "get_env requires the result type to be destructible"); - return obj.get_env(); + if constexpr (requires { ::std::as_const(obj).get_env(); }) { + static_assert(noexcept(::std::as_const(obj).get_env()), "get_env requires the expression to be noexcept"); + static_assert( + ::beman::execution::detail::queryable>, + "get_env requires the result type to be destructible"); + return ::std::as_const(obj).get_env(); } else { return ::beman::execution::env<>{}; } diff --git a/include/beman/execution/detail/get_forward_progress_guarantee.hpp b/include/beman/execution/detail/get_forward_progress_guarantee.hpp index d11cc89e..eaba86b9 100644 --- a/include/beman/execution/detail/get_forward_progress_guarantee.hpp +++ b/include/beman/execution/detail/get_forward_progress_guarantee.hpp @@ -29,6 +29,7 @@ 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(noexcept(object.query(*this))); static_assert(::std::same_as); return object.query(*this); } diff --git a/include/beman/execution/detail/get_scheduler.hpp b/include/beman/execution/detail/get_scheduler.hpp index a0dc5c50..49d8bca3 100644 --- a/include/beman/execution/detail/get_scheduler.hpp +++ b/include/beman/execution/detail/get_scheduler.hpp @@ -33,6 +33,8 @@ struct get_scheduler_t : ::beman::execution::forwarding_query_t { ::std::as_const(env).query(self), ::beman::execution::detail::hide_sched(env)); } auto operator()(Env&& env) const noexcept { + static_assert(noexcept(::beman::execution::get_completion_scheduler<::beman::execution::set_value_t>( + ::std::as_const(env).query(*this), ::beman::execution::detail::hide_sched(env)))); return ::beman::execution::get_completion_scheduler<::beman::execution::set_value_t>( ::std::as_const(env).query(*this), ::beman::execution::detail::hide_sched(env)); } diff --git a/include/beman/execution/detail/get_start_scheduler.hpp b/include/beman/execution/detail/get_start_scheduler.hpp index 43a00bbf..5df9e5b8 100644 --- a/include/beman/execution/detail/get_start_scheduler.hpp +++ b/include/beman/execution/detail/get_start_scheduler.hpp @@ -24,10 +24,11 @@ namespace beman::execution { struct get_start_scheduler_t : ::beman::execution::forwarding_query_t { template requires requires(const get_start_scheduler_t& self, const Env& env) { - { auto(::std::as_const(env).query(self)) } noexcept -> beman::execution::scheduler; + { auto(::std::as_const(env).query(self)) } -> beman::execution::scheduler; } auto operator()(const Env& env) const noexcept { - return env.query(*this); + static_assert(noexcept(::std::as_const(env).query(*this))); + return ::std::as_const(env).query(*this); } }; diff --git a/include/beman/execution/detail/get_stop_token.hpp b/include/beman/execution/detail/get_stop_token.hpp index 010eb294..bed41dc9 100644 --- a/include/beman/execution/detail/get_stop_token.hpp +++ b/include/beman/execution/detail/get_stop_token.hpp @@ -31,9 +31,10 @@ namespace beman::execution { struct get_stop_token_t { template requires requires(Object&& object, const get_stop_token_t& tag) { - { ::std::as_const(object).query(tag) } noexcept -> ::beman::execution::detail::decayed_stoppable_token; + { ::std::as_const(object).query(tag) } -> ::beman::execution::detail::decayed_stoppable_token; } auto operator()(Object&& object) const noexcept { + static_assert(noexcept(::std::as_const(object).query(*this))); return ::std::as_const(object).query(*this); } diff --git a/include/beman/execution/detail/set_error.hpp b/include/beman/execution/detail/set_error.hpp index 83040252..b3764ed9 100644 --- a/include/beman/execution/detail/set_error.hpp +++ b/include/beman/execution/detail/set_error.hpp @@ -32,14 +32,12 @@ struct set_error_t { ::std::forward(receiver).set_error(::std::forward(error)); }) = BEMAN_EXECUTION_DELETE("set_error requires a suitable member overload on the receiver"); - template - requires(not noexcept(::std::declval().set_error(::std::declval()))) - auto operator()(Receiver&&, Error&&) const - -> void = BEMAN_EXECUTION_DELETE("the call to receiver.set_error(error) has to be noexcept"); // NOLINTBEGIN(misc-no-recursion) template auto operator()(Receiver&& receiver, Error&& error) const noexcept -> void { + static_assert(noexcept(::std::forward(receiver).set_error(::std::forward(error))), + "the call to receiver.set_error(error) has to be noexcept"); ::std::forward(receiver).set_error(::std::forward(error)); } // NOLINTEND(misc-no-recursion) diff --git a/include/beman/execution/detail/set_stopped.hpp b/include/beman/execution/detail/set_stopped.hpp index d0061cab..1f803937 100644 --- a/include/beman/execution/detail/set_stopped.hpp +++ b/include/beman/execution/detail/set_stopped.hpp @@ -30,13 +30,11 @@ struct set_stopped_t { auto operator()(Receiver&&) const -> void requires(not requires(Receiver&& receiver) { ::std::forward(receiver).set_stopped(); }) = BEMAN_EXECUTION_DELETE("set_stopped requires a suitable member overload on the receiver"); - template - requires(not noexcept(::std::declval().set_stopped())) - auto operator()(Receiver&&) const - -> void = BEMAN_EXECUTION_DELETE("the call to receiver.set_stopped() has to be noexcept"); template auto operator()(Receiver&& receiver) const noexcept -> void { + static_assert(noexcept(::std::forward(receiver).set_stopped()), + "the call to receiver.set_stopped() has to be noexcept"); ::std::forward(receiver).set_stopped(); } }; diff --git a/include/beman/execution/detail/set_value.hpp b/include/beman/execution/detail/set_value.hpp index c2e4bdc4..4cf48a97 100644 --- a/include/beman/execution/detail/set_value.hpp +++ b/include/beman/execution/detail/set_value.hpp @@ -50,6 +50,9 @@ struct set_value_t { template auto operator()(Receiver&& receiver, Args&&... args) const noexcept -> void { + static_assert(noexcept(::std::forward(receiver).set_value(::std::forward(args)...)), + "the call to receiver.set_value(args...) has to be noexcept"); + ::std::forward(receiver).set_value(::std::forward(args)...); } }; diff --git a/include/beman/execution/detail/start.hpp b/include/beman/execution/detail/start.hpp index 546a7314..0e074bb5 100644 --- a/include/beman/execution/detail/start.hpp +++ b/include/beman/execution/detail/start.hpp @@ -20,24 +20,15 @@ struct start_t { requires(not requires(const State& state) { state.start(); }) auto operator()(const State&) const -> void = BEMAN_EXECUTION_DELETE("state needs to have a start() member"); - template - requires(not requires(State& state) { - { state.start() } noexcept; - }) - auto operator()(State&) const -> void = BEMAN_EXECUTION_DELETE("state start() member has to be noexcept"); - template - requires(not requires(const State& state) { - { state.start() } noexcept; - }) - auto operator()(const State&) const -> void = BEMAN_EXECUTION_DELETE("state start() member has to be noexcept"); - template auto operator()(const State& state) const noexcept -> void { + static_assert(noexcept(state.start()), "state start() member has to be noexcept"); state.start(); } // NOLINTBEGIN(misc-no-recursion) template auto operator()(State& state) const noexcept -> void { + static_assert(noexcept(state.start()), "state start() member has to be noexcept"); state.start(); } // NOLINTEND(misc-no-recursion) diff --git a/tests/beman/execution/exec-fwd-env.test.cpp b/tests/beman/execution/exec-fwd-env.test.cpp index 6d3a5cfd..d0b3012f 100644 --- a/tests/beman/execution/exec-fwd-env.test.cpp +++ b/tests/beman/execution/exec-fwd-env.test.cpp @@ -48,7 +48,7 @@ TEST(exec_fwd_env) { static_assert(noexcept(test_std::forwarding_query(derived()))); static_assert(test_std::forwarding_query(static_query<>())); static_assert(noexcept(test_std::forwarding_query(static_query<>()))); - static_assert(not test_std::forwarding_query(static_query())); + //-dk:TODO verify this fails to compile: static_assert(not test_std::forwarding_query(static_query())); static_assert(noexcept(test_std::forwarding_query(static_query()))); static_assert(not test_std::forwarding_query(static_query())); static_assert(noexcept(test_std::forwarding_query(static_query()))); diff --git a/tests/beman/execution/exec-get-delegation-scheduler.test.cpp b/tests/beman/execution/exec-get-delegation-scheduler.test.cpp index 1be3b151..6cd80bd4 100644 --- a/tests/beman/execution/exec-get-delegation-scheduler.test.cpp +++ b/tests/beman/execution/exec-get-delegation-scheduler.test.cpp @@ -77,7 +77,7 @@ TEST(exec_get_delegation_scheduler) { static_assert(test_std::forwarding_query((test_std::get_delegation_scheduler))); test_get_delegation_scheduler(test_std::env<>{}); - test_get_delegation_scheduler(env{}); + //-dk:TODO verify that this fails to compile test_get_delegation_scheduler(env{}); test_get_delegation_scheduler(env{}); test_get_delegation_scheduler(env{17}); } diff --git a/tests/beman/execution/exec-get-domain.test.cpp b/tests/beman/execution/exec-get-domain.test.cpp index 154c6daa..e0e49051 100644 --- a/tests/beman/execution/exec-get-domain.test.cpp +++ b/tests/beman/execution/exec-get-domain.test.cpp @@ -102,7 +102,7 @@ TEST(exec_get_domain) { test_get_domain(non_const_get_domain{}); // falling back to `default_domain` test_get_domain(non_const_get_domain{}); // falling back to `default_domain` test_get_domain(has_get_domain{42}); - test_get_domain(has_get_domain{42}); + //-dk:TODO verify that this fails to compile test_get_domain(has_get_domain{42}); test_get_domain(has_get_domain{42}); test_get_domain(has_get_domain{42}); test_get_domain(overloaded_get_domain{}); diff --git a/tests/beman/execution/exec-get-stop-token.test.cpp b/tests/beman/execution/exec-get-stop-token.test.cpp index 661f40d9..93141e6a 100644 --- a/tests/beman/execution/exec-get-stop-token.test.cpp +++ b/tests/beman/execution/exec-get-stop-token.test.cpp @@ -56,7 +56,8 @@ TEST(exec_get_stop_token) { test_get_stop_token(no_get_stop_token()); test_get_stop_token(has_get_stop_token()); - test_get_stop_token(has_get_stop_token()); + //-dk:TODO test this fails to compile: + //test_get_stop_token(has_get_stop_token()); test_get_stop_token(non_const_get_stop_token()); test_get_stop_token(inconsistent_get_stop_token()); diff --git a/tests/beman/execution/exec-opstate.test.cpp b/tests/beman/execution/exec-opstate.test.cpp index 091d6db0..54f85ab4 100644 --- a/tests/beman/execution/exec-opstate.test.cpp +++ b/tests/beman/execution/exec-opstate.test.cpp @@ -45,7 +45,8 @@ TEST(exec_opstate) { test_operation_state(); test_operation_state>(); - test_operation_state>(); + //-dk:TODO verify that this fails to compile test_operation_state>(); test_operation_state>(); test_operation_state>(); test_operation_state&>(); diff --git a/tests/beman/execution/exec-recv.test.cpp b/tests/beman/execution/exec-recv.test.cpp index a5796087..eaf69021 100644 --- a/tests/beman/execution/exec-recv.test.cpp +++ b/tests/beman/execution/exec-recv.test.cpp @@ -104,7 +104,8 @@ auto test_valid_completions_for_concept() -> void { static_assert(not test_detail::valid_completion_for)->test_std::set_value_t, receiver1>); static_assert(test_detail::valid_completion_for)->test_std::set_error_t, receiver1>); - static_assert(not test_detail::valid_completion_fortest_std::set_error_t, receiver1>); + //-dk:TODO verify that this fails to compile static_assert(not + //test_detail::valid_completion_fortest_std::set_error_t, receiver1>); static_assert(test_detail::valid_completion_fortest_std::set_stopped_t, receiver1>); } diff --git a/tests/beman/execution/exec-set-error.test.cpp b/tests/beman/execution/exec-set-error.test.cpp index 20ae1a8f..7a3b18b9 100644 --- a/tests/beman/execution/exec-set-error.test.cpp +++ b/tests/beman/execution/exec-set-error.test.cpp @@ -52,8 +52,9 @@ template auto test_noexcept() { test::throws obj{}; static_assert(requires { test_std::set_error(std::declval(), arg()); }); - static_assert(not requires { test_std::set_error(std::declval(), obj); }); - static_assert(not requires { test_std::set_error(std::declval(), arg_throwing()); }); + //-dk:TODO verify this fails to compile static_assert(not requires { test_std::set_error(std::declval(), obj); + //}); -dk:TODO verify this fails to compile static_assert(not requires { test_std::set_error(std::declval(), + //arg_throwing()); }); } } // namespace diff --git a/tests/beman/execution/exec-set-stopped.test.cpp b/tests/beman/execution/exec-set-stopped.test.cpp index 9bbccd64..53671cb0 100644 --- a/tests/beman/execution/exec-set-stopped.test.cpp +++ b/tests/beman/execution/exec-set-stopped.test.cpp @@ -57,7 +57,7 @@ TEST(exec_set_stopped) { static_assert(std::same_as); test_callable(); - test_noexcept(); + //-dk:TODO verify that this fails to compile test_noexcept(); bool called{false}; ASSERT(not called); From 8660d7cd9168cb40247df38404923e14c1ef69a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sat, 15 Aug 2026 00:11:14 +0100 Subject: [PATCH 2/6] fix get_domain and stop_when - get_domain should return a default constructed domain - stop_when needs to unregister the stop_callbacks --- docs/implementation-status.md | 3 ++ docs/overview.md | 3 +- include/beman/execution/detail/get_domain.hpp | 17 ++++--- include/beman/execution/detail/stop_when.hpp | 49 +++++++++++++------ tests/beman/execution/CMakeLists.txt | 3 +- .../beman/execution/exec-get-domain.test.cpp | 2 +- .../execution/exec-get-stop-token.test.cpp | 2 +- tests/beman/execution/exec-opstate.test.cpp | 2 +- tests/beman/execution/exec-read-env.test.cpp | 28 ++++++++--- tests/beman/execution/exec-recv.test.cpp | 2 +- tests/beman/execution/exec-set-error.test.cpp | 2 +- tests/beman/execution/exec-snd-expos.test.cpp | 11 ++++- 12 files changed, 86 insertions(+), 38 deletions(-) diff --git a/docs/implementation-status.md b/docs/implementation-status.md index 3dce58c0..c7cbd2e1 100644 --- a/docs/implementation-status.md +++ b/docs/implementation-status.md @@ -1,3 +1,6 @@ + # Implementation Status Meaning of the status indicators (in order best to worst): diff --git a/docs/overview.md b/docs/overview.md index 955c8d86..7a4c9cc6 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -821,10 +821,11 @@ tries the following transformations:
  • sender-awaitable{adapt-for-await-completion(transform_sender(expr, get_env(promise))), promise} if this expression is well-formed; otherwise
  • expr
  • - + - `with_awaitable_sender` - `apply_sender` +
    completion_signatures<Sig...> The template specialization completion_signatures<Sig...> is a list diff --git a/include/beman/execution/detail/get_domain.hpp b/include/beman/execution/detail/get_domain.hpp index e0ab08f8..1572e7a9 100644 --- a/include/beman/execution/detail/get_domain.hpp +++ b/include/beman/execution/detail/get_domain.hpp @@ -35,26 +35,27 @@ struct get_domain_t : ::beman::execution::forwarding_query_t { template constexpr auto operator()(Env&& env) const noexcept { if constexpr (requires { ::std::as_const(env).query(*this); }) { - static_assert(noexcept(::std::as_const(env).query(*this))); - return auto(::std::as_const(env).query(*this)); + using type = decltype(auto(::std::as_const(env).query(*this))); + static_assert(noexcept(type{})); + return type{}; } else if constexpr (requires { ::beman::execution::get_completion_domain<::beman::execution::set_value_t>( ::beman::execution::get_scheduler(env), ::beman::execution::detail::hide_sched(env)); }) { - static_assert(noexcept(::beman::execution::get_completion_domain<::beman::execution::set_value_t>( + using type = decltype(auto(::beman::execution::get_completion_domain<::beman::execution::set_value_t>( ::beman::execution::get_scheduler(env), ::beman::execution::detail::hide_sched(env)))); - return ::beman::execution::get_completion_domain<::beman::execution::set_value_t>( - ::beman::execution::get_scheduler(env), ::beman::execution::detail::hide_sched(env)); + static_assert(noexcept(type{})); + return type{}; } else if constexpr (requires { ::beman::execution::get_completion_domain<::beman::execution::set_value_t>( ::beman::execution::get_scheduler(env), ::beman::execution::detail::hide_sched(env)); }) { - static_assert(noexcept(::beman::execution::get_completion_domain<::beman::execution::set_value_t>( + using type = decltype(auto(::beman::execution::get_completion_domain<::beman::execution::set_value_t>( ::beman::execution::get_scheduler(env), ::beman::execution::detail::hide_sched(env)))); - return ::beman::execution::get_completion_domain<::beman::execution::set_value_t>( - ::beman::execution::get_scheduler(env), ::beman::execution::detail::hide_sched(env)); + static_assert(noexcept(type{})); + return type{}; } else { return ::beman::execution::default_domain{}; } diff --git a/include/beman/execution/detail/stop_when.hpp b/include/beman/execution/detail/stop_when.hpp index 77cbe9e9..de6f24ce 100644 --- a/include/beman/execution/detail/stop_when.hpp +++ b/include/beman/execution/detail/stop_when.hpp @@ -8,6 +8,7 @@ #ifdef BEMAN_HAS_IMPORT_STD import std; #else +#include #include #include #include @@ -67,23 +68,31 @@ struct beman::execution::detail::stop_when_t::sender { std::remove_cvref_t sndr; template <::beman::execution::receiver Rcvr> - struct state { - using operation_state_concept = ::beman::execution::operation_state_tag; + struct base_state { using rcvr_t = ::std::remove_cvref_t; + rcvr_t rcvr; + ::beman::execution::inplace_stop_source source{}; + base_state(Rcvr&& r) : rcvr(::std::forward(r)) {} + virtual ~base_state() noexcept = default; + virtual auto reset() & noexcept -> void = 0; + }; + template <::beman::execution::receiver Rcvr> + struct state : base_state { + using operation_state_concept = ::beman::execution::operation_state_tag; + using rcvr_t = base_state::rcvr_t; using token1_t = ::std::remove_cvref_t; using token2_t = decltype(::beman::execution::get_stop_token(::beman::execution::get_env(::std::declval()))); struct cb_t { ::beman::execution::inplace_stop_source& source; - auto operator()() const noexcept { this->source.request_stop(); } - }; - struct base_state { - rcvr_t rcvr; - ::beman::execution::inplace_stop_source source{}; + auto operator()() const noexcept { + ::std::cout << "stop_when: stop requested\n" << ::std::flush; + this->source.request_stop(); + } }; struct env { - base_state* st; + base_state* st; auto query(const ::beman::execution::get_stop_token_t&) const noexcept { return this->st->source.get_token(); } @@ -98,24 +107,28 @@ struct beman::execution::detail::stop_when_t::sender { struct receiver { using receiver_concept = ::beman::execution::receiver_tag; - base_state* st; + base_state* st; auto get_env() const noexcept -> env { return env{this->st}; } template auto set_value(A&&... a) const noexcept -> void { + this->st->reset(); ::beman::execution::set_value(::std::move(this->st->rcvr), ::std::forward(a)...); } template auto set_error(E&& e) const noexcept -> void { + this->st->reset(); ::beman::execution::set_error(::std::move(this->st->rcvr), ::std::forward(e)); } - auto set_stopped() const noexcept -> void { ::beman::execution::set_stopped(::std::move(this->st->rcvr)); } + auto set_stopped() const noexcept -> void { + this->st->reset(); + ::beman::execution::set_stopped(::std::move(this->st->rcvr)); + } }; using inner_state_t = decltype(::beman::execution::connect(::std::declval(), ::std::declval())); token1_t tok; - base_state base; std::optional<::beman::execution::stop_callback_for_t> cb1; std::optional<::beman::execution::stop_callback_for_t> cb2; inner_state_t inner_state; @@ -123,15 +136,19 @@ struct beman::execution::detail::stop_when_t::sender { template <::beman::execution::sender S, ::beman::execution::stoppable_token T, ::beman::execution::receiver R> state(S&& s, T&& t, R&& r) : tok(::std::forward(t)), - base{::std::forward(r)}, - inner_state(::beman::execution::connect(::std::forward(s), receiver{&this->base})) {} + base_state{::std::forward(r)}, + inner_state(::beman::execution::connect(::std::forward(s), receiver{this})) {} auto start() & noexcept { - this->cb1.emplace(this->tok, cb_t{this->base.source}); - this->cb2.emplace(::beman::execution::get_stop_token(::beman::execution::get_env(this->base.rcvr)), - cb_t{this->base.source}); + this->cb1.emplace(this->tok, cb_t{this->source}); + this->cb2.emplace(::beman::execution::get_stop_token(::beman::execution::get_env(this->rcvr)), + cb_t{this->source}); ::beman::execution::start(this->inner_state); } + auto reset() & noexcept -> void override { + this->cb1.reset(); + this->cb2.reset(); + } }; template diff --git a/tests/beman/execution/CMakeLists.txt b/tests/beman/execution/CMakeLists.txt index ef8464ad..0ff48cfb 100644 --- a/tests/beman/execution/CMakeLists.txt +++ b/tests/beman/execution/CMakeLists.txt @@ -5,7 +5,7 @@ if(BEMAN_USE_MODULES) list(APPEND execution_tests execution-module.test stop-token-module.test) endif() -list(APPEND unsupported_execution_tests exec-split.test exec-spawn-future.test) +list(APPEND unsupported_execution_tests exec-split.test) list( APPEND execution_tests @@ -64,6 +64,7 @@ list( exec-snd-expos.test exec-snd-transform.test exec-spawn.test + exec-spawn-future.test exec-starts-on.test exec-stop-when.test exec-stopped-err.test diff --git a/tests/beman/execution/exec-get-domain.test.cpp b/tests/beman/execution/exec-get-domain.test.cpp index e0e49051..925bd56f 100644 --- a/tests/beman/execution/exec-get-domain.test.cpp +++ b/tests/beman/execution/exec-get-domain.test.cpp @@ -107,7 +107,7 @@ TEST(exec_get_domain) { test_get_domain(has_get_domain{42}); test_get_domain(overloaded_get_domain{}); - static_assert(42 == test_std::get_domain(has_get_domain{42}).value); + static_assert(0 == test_std::get_domain(has_get_domain{42}).value); test_get_domain(env_with_scheduler{}); } diff --git a/tests/beman/execution/exec-get-stop-token.test.cpp b/tests/beman/execution/exec-get-stop-token.test.cpp index 93141e6a..e17cab47 100644 --- a/tests/beman/execution/exec-get-stop-token.test.cpp +++ b/tests/beman/execution/exec-get-stop-token.test.cpp @@ -57,7 +57,7 @@ TEST(exec_get_stop_token) { test_get_stop_token(no_get_stop_token()); test_get_stop_token(has_get_stop_token()); //-dk:TODO test this fails to compile: - //test_get_stop_token(has_get_stop_token()); + // test_get_stop_token(has_get_stop_token()); test_get_stop_token(non_const_get_stop_token()); test_get_stop_token(inconsistent_get_stop_token()); diff --git a/tests/beman/execution/exec-opstate.test.cpp b/tests/beman/execution/exec-opstate.test.cpp index 54f85ab4..1dbc9138 100644 --- a/tests/beman/execution/exec-opstate.test.cpp +++ b/tests/beman/execution/exec-opstate.test.cpp @@ -46,7 +46,7 @@ TEST(exec_opstate) { test_operation_state>(); //-dk:TODO verify that this fails to compile test_operation_state>(); + // test_std::operation_state_tag>>(); test_operation_state>(); test_operation_state>(); test_operation_state&>(); diff --git a/tests/beman/execution/exec-read-env.test.cpp b/tests/beman/execution/exec-read-env.test.cpp index aa26681c..7bbbe02b 100644 --- a/tests/beman/execution/exec-read-env.test.cpp +++ b/tests/beman/execution/exec-read-env.test.cpp @@ -34,19 +34,29 @@ struct domain { auto operator==(const domain&) const -> bool = default; }; +struct get_test_domain_t { + template + auto operator()(const Env& ev) const noexcept -> domain { + return ev.query(*this); + } +}; +inline constexpr get_test_domain_t get_test_domain{}; + struct env { int value{}; auto query(test_std::get_domain_t) const noexcept -> domain { return {this->value}; } + auto query(get_test_domain_t) const noexcept -> domain { return {this->value}; } }; struct receiver { using receiver_concept = test_std::receiver_tag; int value{}; + int expect{}; bool* called{}; auto set_value(domain d) && noexcept -> void { - ASSERT(d == domain{this->value}); + ASSERT(d == domain{this->expect}); *this->called = true; } auto set_error(auto&&) && noexcept -> void { @@ -59,8 +69,10 @@ struct receiver { auto test_read_env() -> void { static_assert(test_std::receiver); - ASSERT(domain{17} == test_std::get_domain(env{17})); - ASSERT(domain{17} == test_std::get_domain(test_std::get_env(receiver{17}))); + ASSERT(domain{} == test_std::get_domain(env{17})); + ASSERT(domain{} == test_std::get_domain(test_std::get_env(receiver{17, 0}))); + ASSERT(domain{17} == get_test_domain(env{17})); + ASSERT(domain{17} == get_test_domain(test_std::get_env(receiver{17, 0}))); auto sender{test_std::read_env(test_std::get_domain)}; test::use(sender); static_assert(test_std::sender); @@ -72,10 +84,14 @@ auto test_read_env() -> void { decltype(test_std::get_completion_signatures())>); bool called{}; - auto op{test_std::connect(test_std::read_env(test_std::get_domain), receiver{17, &called})}; - test::use(op); + auto op1{test_std::connect(test_std::read_env(test_std::get_domain), receiver{17, 0, &called})}; ASSERT(not called); - test_std::start(op); + test_std::start(op1); + ASSERT(called); + + called = false; + auto op2{test_std::connect(test_std::read_env(get_test_domain), receiver{17, 17, &called})}; + test_std::start(op2); ASSERT(called); } diff --git a/tests/beman/execution/exec-recv.test.cpp b/tests/beman/execution/exec-recv.test.cpp index eaf69021..365fa0c7 100644 --- a/tests/beman/execution/exec-recv.test.cpp +++ b/tests/beman/execution/exec-recv.test.cpp @@ -105,7 +105,7 @@ auto test_valid_completions_for_concept() -> void { static_assert(test_detail::valid_completion_for)->test_std::set_error_t, receiver1>); //-dk:TODO verify that this fails to compile static_assert(not - //test_detail::valid_completion_fortest_std::set_error_t, receiver1>); + // test_detail::valid_completion_fortest_std::set_error_t, receiver1>); static_assert(test_detail::valid_completion_fortest_std::set_stopped_t, receiver1>); } diff --git a/tests/beman/execution/exec-set-error.test.cpp b/tests/beman/execution/exec-set-error.test.cpp index 7a3b18b9..cc0c58b2 100644 --- a/tests/beman/execution/exec-set-error.test.cpp +++ b/tests/beman/execution/exec-set-error.test.cpp @@ -54,7 +54,7 @@ auto test_noexcept() { static_assert(requires { test_std::set_error(std::declval(), arg()); }); //-dk:TODO verify this fails to compile static_assert(not requires { test_std::set_error(std::declval(), obj); //}); -dk:TODO verify this fails to compile static_assert(not requires { test_std::set_error(std::declval(), - //arg_throwing()); }); + // arg_throwing()); }); } } // namespace diff --git a/tests/beman/execution/exec-snd-expos.test.cpp b/tests/beman/execution/exec-snd-expos.test.cpp index dcdde83c..c7c878a6 100644 --- a/tests/beman/execution/exec-snd-expos.test.cpp +++ b/tests/beman/execution/exec-snd-expos.test.cpp @@ -71,9 +71,18 @@ struct custom_result { auto operator==(const custom_result&) const -> bool = default; }; +struct get_test_domain_t { + template + auto operator()(const Env& ev) const noexcept -> domain { + return ev.query(*this); + } +}; +inline constexpr get_test_domain_t get_test_domain{}; + struct env { int value{}; auto query(const test_std::get_domain_t&) const noexcept { return domain{value}; } + auto query(const get_test_domain_t&) const noexcept { return domain{value}; } auto query(const non_forwardable_t&) const noexcept { return true; } auto query(const forwardable_t&, int a, int b) const noexcept { return (value + a) * b; } }; @@ -444,7 +453,7 @@ auto test_completion_domain() -> void { } auto test_query_with_default() -> void { - auto result1{test_detail::query_with_default(test_std::get_domain, env{43}, default_domain{74})}; + auto result1{test_detail::query_with_default(get_test_domain, env{43}, default_domain{74})}; static_assert(std::same_as); ASSERT(result1.value == 43); From 204246601244e8da0777bcb0c1c10ffd0e5ad047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sat, 15 Aug 2026 00:24:35 +0100 Subject: [PATCH 3/6] fixed initializer list in stop_when (and formatting) --- include/beman/execution/detail/stop_when.hpp | 8 +- tests/beman/execution/exec-read-env.test.cpp | 8 +- tests/beman/execution/exec-snd-expos.test.cpp | 84 +++++++++---------- 3 files changed, 50 insertions(+), 50 deletions(-) diff --git a/include/beman/execution/detail/stop_when.hpp b/include/beman/execution/detail/stop_when.hpp index de6f24ce..0d1a99d6 100644 --- a/include/beman/execution/detail/stop_when.hpp +++ b/include/beman/execution/detail/stop_when.hpp @@ -69,7 +69,7 @@ struct beman::execution::detail::stop_when_t::sender { template <::beman::execution::receiver Rcvr> struct base_state { - using rcvr_t = ::std::remove_cvref_t; + using rcvr_t = ::std::remove_cvref_t; rcvr_t rcvr; ::beman::execution::inplace_stop_source source{}; base_state(Rcvr&& r) : rcvr(::std::forward(r)) {} @@ -93,7 +93,7 @@ struct beman::execution::detail::stop_when_t::sender { }; struct env { base_state* st; - auto query(const ::beman::execution::get_stop_token_t&) const noexcept { + auto query(const ::beman::execution::get_stop_token_t&) const noexcept { return this->st->source.get_token(); } template @@ -135,8 +135,8 @@ struct beman::execution::detail::stop_when_t::sender { template <::beman::execution::sender S, ::beman::execution::stoppable_token T, ::beman::execution::receiver R> state(S&& s, T&& t, R&& r) - : tok(::std::forward(t)), - base_state{::std::forward(r)}, + : base_state{::std::forward(r)}, + tok(::std::forward(t)), inner_state(::beman::execution::connect(::std::forward(s), receiver{this})) {} auto start() & noexcept { diff --git a/tests/beman/execution/exec-read-env.test.cpp b/tests/beman/execution/exec-read-env.test.cpp index 7bbbe02b..9c769f92 100644 --- a/tests/beman/execution/exec-read-env.test.cpp +++ b/tests/beman/execution/exec-read-env.test.cpp @@ -139,10 +139,10 @@ auto test_read_env_check_types() -> void { test_std::env<>>(); test_std::read_env_t::impls_for::check_types>(); #if 0 - test_std::read_env_t::impls_for::check_types>(); - test_std::read_env_t::impls_for::check_types>(); + test_std::read_env_t::impls_for::check_types>(); + test_std::read_env_t::impls_for::check_types>(); #endif } } // namespace diff --git a/tests/beman/execution/exec-snd-expos.test.cpp b/tests/beman/execution/exec-snd-expos.test.cpp index c7c878a6..8bfc3e2e 100644 --- a/tests/beman/execution/exec-snd-expos.test.cpp +++ b/tests/beman/execution/exec-snd-expos.test.cpp @@ -955,17 +955,17 @@ auto test_product_type() -> void { test::use(i, b, c); #if 0 //-dk:TODO it seems exporting constrained tuple_size/tuple_element doesn't work - struct derived : decltype(prod) {}; - static_assert(3u == std::tuple_size::value); - static_assert(std::same_as::type>); - static_assert(std::same_as::type>); - static_assert(std::same_as::type>); - derived d{1, true, 'c'}; - auto&& [di, db, dc] = d; - assert(di == d.get<0>()); - assert(db == d.get<1>()); - assert(dc == d.get<2>()); - test::use(di, db, dc); + struct derived : decltype(prod) {}; + static_assert(3u == std::tuple_size::value); + static_assert(std::same_as::type>); + static_assert(std::same_as::type>); + static_assert(std::same_as::type>); + derived d{1, true, 'c'}; + auto&& [di, db, dc] = d; + assert(di == d.get<0>()); + assert(db == d.get<1>()); + assert(dc == d.get<2>()); + test::use(di, db, dc); #endif } auto test_connect_all() -> void { @@ -1130,15 +1130,15 @@ auto test_completion_signatures_for() -> void { //-dk:TODO restore test static_assert(not test_std::sender_in); #if 0 - //-dk:TODO restore completion_signatures_for tests or remove completion_signatures for - static_assert(std::same_as< - test_detail::completion_signatures_for>, - completion_signatures_for_sender::empty_env_sigs - >); - static_assert(std::same_as< - test_detail::completion_signatures_for, - completion_signatures_for_sender::env_sigs - >); + //-dk:TODO restore completion_signatures_for tests or remove completion_signatures for + static_assert(std::same_as< + test_detail::completion_signatures_for>, + completion_signatures_for_sender::empty_env_sigs + >); + static_assert(std::same_as< + test_detail::completion_signatures_for, + completion_signatures_for_sender::env_sigs + >); #endif static_assert( not test_detail::valid_completion_signatures); @@ -1226,15 +1226,15 @@ auto test_basic_sender() -> void { static_assert(test_std::dependent_sender); static_assert(test_std::sender_in); #if 0 - //-dk:TODO restore completion_sigatures_for test - static_assert(std::same_as< - basic_sender_tag::sender::completion_signatures, - test_detail::completion_signatures_for - >); - static_assert(std::same_as< - basic_sender_tag::sender::completion_signatures, - test_detail::completion_signatures_for - >); + //-dk:TODO restore completion_sigatures_for test + static_assert(std::same_as< + basic_sender_tag::sender::completion_signatures, + test_detail::completion_signatures_for + >); + static_assert(std::same_as< + basic_sender_tag::sender::completion_signatures, + test_detail::completion_signatures_for + >); #endif auto ge{test_std::get_env(bs)}; @@ -1244,19 +1244,19 @@ auto test_basic_sender() -> void { auto op{test_std::connect(bs, receiver{})}; test::use(op); #if 0 - static_assert(std::same_as< - basic_sender_tag::sender::completion_signatures, - decltype(bs.get_completion_signatures(env{})) - >); - static_assert(std::same_as< - basic_sender_tag::sender::completion_signatures, - decltype(cbs.get_completion_signatures(env{})) - >); - static_assert(std::same_as< - basic_sender_tag::sender::completion_signatures, - decltype(basic_sender{ basic_sender_tag{}, data{}, sender0 {} } - .get_completion_signatures(env{})) - >); + static_assert(std::same_as< + basic_sender_tag::sender::completion_signatures, + decltype(bs.get_completion_signatures(env{})) + >); + static_assert(std::same_as< + basic_sender_tag::sender::completion_signatures, + decltype(cbs.get_completion_signatures(env{})) + >); + static_assert(std::same_as< + basic_sender_tag::sender::completion_signatures, + decltype(basic_sender{ basic_sender_tag{}, data{}, sender0 {} } + .get_completion_signatures(env{})) + >); #endif static_assert(std::same_as, basic_sender::indices_for>); } From c3ec6e78247c3a715038cc59ec0d2a44ea7ae163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sat, 15 Aug 2026 00:28:41 +0100 Subject: [PATCH 4/6] mark unused object in a test as such --- tests/beman/execution/exec-set-error.test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/beman/execution/exec-set-error.test.cpp b/tests/beman/execution/exec-set-error.test.cpp index cc0c58b2..5a694828 100644 --- a/tests/beman/execution/exec-set-error.test.cpp +++ b/tests/beman/execution/exec-set-error.test.cpp @@ -50,7 +50,7 @@ void test_callable() { template auto test_noexcept() { - test::throws obj{}; + [[maybe_unused]] test::throws obj{}; static_assert(requires { test_std::set_error(std::declval(), arg()); }); //-dk:TODO verify this fails to compile static_assert(not requires { test_std::set_error(std::declval(), obj); //}); -dk:TODO verify this fails to compile static_assert(not requires { test_std::set_error(std::declval(), From f5c1b909c16df33dee0dbc60a6396fc07c9d6482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sat, 15 Aug 2026 21:13:04 +0100 Subject: [PATCH 5/6] fixed outview.md in some p;laces and added missing documentation --- docs/TODO.json | 346 ------------------ docs/TODO.md | 112 ------ docs/implementation-status.md | 19 +- docs/overview.md | 123 ++++--- tests/beman/execution/CMakeLists.txt | 1 + .../execution/exec-get-await-adapt.test.cpp | 40 ++ 6 files changed, 117 insertions(+), 524 deletions(-) delete mode 100644 docs/TODO.json delete mode 100644 docs/TODO.md create mode 100644 tests/beman/execution/exec-get-await-adapt.test.cpp diff --git a/docs/TODO.json b/docs/TODO.json deleted file mode 100644 index a75b63a6..00000000 --- a/docs/TODO.json +++ /dev/null @@ -1,346 +0,0 @@ -{ - "allocator.requirements.general": { - "code": true, - "test": true, - "doc": false - }, - "execution": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "execution.queries": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "execution.queryable": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "execution.queryable.general]": { - "code": true, - "test": true, - "doc": false, - "comment": "nothing testable" - }, - "execution.forwarding_query": { - "code": true, - "test": true, - "doc": false - }, - "execution.get_allocator": { - "code": true, - "test": true, - "doc": false - }, - "execution.get_stop_token": { - "code": true, - "test": true, - "doc": false - }, - "execution.environment.get_env": { - "code": true, - "test": true, - "doc": false - }, - "execution.get_domain": { - "code": true, - "test": true, - "doc": false - }, - "execution.queryable.concepts": { - "code": true, - "test": true, - "doc": false - }, - "execution.receivers": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "execution.senders": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "execution.senders.factories": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "execution.senders.adapt": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "execution.senders.consumers": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "execution.snd_rec_utils": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "execution.contexts": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "execution.coro_utils": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "execution.receivers.set_value": { - "code": true, - "test": true, - "doc": false - }, - "execution.receivers.set_error": { - "code": true, - "test": true, - "doc": false - }, - "execution.receivers.set_stopped": { - "code": true, - "test": true, - "doc": false - }, - "execution.opstate.start": { - "code": true, - "test": true, - "doc": false - }, - "execution.opstate": { - "code": true, - "test": true, - "doc": false - }, - "execution.general": { - "code": true, - "test": true, - "doc": false - }, - "except": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "except.special": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "library": { - "code": true, - "test": true, - "doc": true, - "comment": "term definition only" - }, - "support": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "support.limits": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "utilities": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "function.objects": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "functional.syn": { - "code": true, - "test": true, - "doc": false - }, - "thread": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "thread.stoptoken": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "thread.stoptoken.intro": { - "code": true, - "test": true, - "doc": false - }, - "thread.stoptoken.syn": { - "code": true, - "test": true, - "doc": false - }, - "stoptoken.nonmembers": { - "code": true, - "test": true, - "doc": true, - "comment": "removed" - }, - "stoptoken.concepts": { - "code": true, - "test": true, - "doc": false - }, - "stoptoken": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "stoptoken.cons": { - "removed": true - }, - "stoptoken.general": { - "code": true, - "test": true, - "doc": false - }, - "stoptoken.mem": { - "code": true, - "test": true, - "doc": false - }, - "stopsource": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "stopsource.general": { - "code": true, - "test": true, - "doc": false - }, - "stopsource.cons": { - "code": true, - "test": true, - "doc": false - }, - "stopsource.mem": { - "code": true, - "test": true, - "doc": false - }, - "stopsource.nonmembers": { - "code": true, - "test": true, - "doc": true, - "comment": "removed" - }, - "stopcallback": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "stopcallback.general": { - "code": true, - "test": true, - "doc": false - }, - "stopcallback.cons": { - "code": true, - "test": true, - "doc": false - }, - "stoptoken.never": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "stoptoken.never.general": { - "code": true, - "test": true, - "doc": false - }, - "stoptoken.inplace": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "stoptoken.inplace.general": { - "code": true, - "test": true, - "doc": false - }, - "stoptoken.inplace.members": { - "code": true, - "test": true, - "doc": false - }, - "stopsource.inplace": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "stopsource.inplace.general": { - "code": true, - "test": true, - "doc": false - }, - "stopsource.inplace.cons": { - "code": true, - "test": true, - "doc": false - }, - "stopsource.inplace.mem": { - "code": true, - "test": true, - "doc": false - }, - "stopcallback.inplace": { - "code": true, - "test": true, - "doc": true, - "comment": "empty" - }, - "stopcallback.inplace.general": { - "code": true, - "test": true, - "doc": false - }, - "stopcallback.inplace.cons": { - "code": true, - "test": true, - "doc": false - }, - "": {} -} diff --git a/docs/TODO.md b/docs/TODO.md deleted file mode 100644 index a161b0d6..00000000 --- a/docs/TODO.md +++ /dev/null @@ -1,112 +0,0 @@ -# ToDo - -| Section | Code | Test | Doc | Comment | -| ------- |:----:|:----:|:---:| ------- | -| [[except](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#except)] | ✅ | ✅ | ✅ | empty | -| [[except.special](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#except.special)] | ✅ | ✅ | ✅ | empty | -| [[except.terminate](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#except.terminate)] | 🔴 | 🔴 | 🔴 | | -| [[library](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#library)] | ✅ | ✅ | ✅ | term definition only | -| [[support](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#support)] | ✅ | ✅ | ✅ | empty | -| [[support.limits](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#support.limits)] | ✅ | ✅ | ✅ | empty | -| [[version.syn](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#version.syn)] | 🔴 | 🔴 | 🔴 | | -| [[utilities](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#utilities)] | ✅ | ✅ | ✅ | empty | -| [[function.objects](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#function.objects)] | ✅ | ✅ | ✅ | empty | -| [[functional.syn](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#functional.syn)] | ✅ | ✅ | 🔴 | | -| [[thread](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#thread)] | ✅ | ✅ | ✅ | empty | -| [[thread.stoptoken](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#thread.stoptoken)] | ✅ | ✅ | ✅ | empty | -| [[thread.stoptoken.intro](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#thread.stoptoken.intro)] | ✅ | ✅ | 🔴 | | -| [[thread.stoptoken.syn](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#thread.stoptoken.syn)] | ✅ | ✅ | 🔴 | | -| [[stoptoken.concepts](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stoptoken.concepts)] | ✅ | ✅ | 🔴 | | -| [[stoptoken](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stoptoken)] | ✅ | ✅ | ✅ | empty | -| [[stoptoken.general](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stoptoken.general)] | ✅ | ✅ | 🔴 | | -| [[stoptoken.mem](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stoptoken.mem)] | ✅ | ✅ | 🔴 | | -| [[stoptoken.nonmembers](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stoptoken.nonmembers)] | ✅ | ✅ | ✅ | removed | -| [[stopsource](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stopsource)] | ✅ | ✅ | ✅ | empty | -| [[stopsource.general](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stopsource.general)] | ✅ | ✅ | 🔴 | | -| [[stopsource.cons](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stopsource.cons)] | ✅ | ✅ | 🔴 | | -| [[stopsource.mem](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stopsource.mem)] | ✅ | ✅ | 🔴 | | -| [[stopsource.nonmembers](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stopsource.nonmembers)] | ✅ | ✅ | ✅ | removed | -| [[stopcallback](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stopcallback)] | ✅ | ✅ | ✅ | empty | -| [[stopcallback.general](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stopcallback.general)] | ✅ | ✅ | 🔴 | | -| [[stopcallback.cons](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stopcallback.cons)] | ✅ | ✅ | 🔴 | | -| [[stoptoken.never](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stoptoken.never)] | ✅ | ✅ | ✅ | empty | -| [[stoptoken.never.general](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stoptoken.never.general)] | ✅ | ✅ | 🔴 | | -| [[stoptoken.inplace](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stoptoken.inplace)] | ✅ | ✅ | ✅ | empty | -| [[stoptoken.inplace.general](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stoptoken.inplace.general)] | ✅ | ✅ | 🔴 | | -| [[stoptoken.inplace.members](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stoptoken.inplace.members)] | ✅ | ✅ | 🔴 | | -| [[stopsource.inplace](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stopsource.inplace)] | ✅ | ✅ | ✅ | empty | -| [[stopsource.inplace.general](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stopsource.inplace.general)] | ✅ | ✅ | 🔴 | | -| [[stopsource.inplace.cons](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stopsource.inplace.cons)] | ✅ | ✅ | 🔴 | | -| [[stopsource.inplace.mem](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stopsource.inplace.mem)] | ✅ | ✅ | 🔴 | | -| [[stopcallback.inplace](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stopcallback.inplace)] | ✅ | ✅ | ✅ | empty | -| [[stopcallback.inplace.general](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stopcallback.inplace.general)] | ✅ | ✅ | 🔴 | | -| [[stopcallback.inplace.cons](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#stopcallback.inplace.cons)] | ✅ | ✅ | 🔴 | | -| [[execution](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution)] | ✅ | ✅ | ✅ | empty | -| [[execution.general](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.general)] | ✅ | ✅ | 🔴 | | -| [[execution.queryable](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.queryable)] | ✅ | ✅ | ✅ | empty | -| [[execution.queryable.general](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.queryable.general)] | 🔴 | 🔴 | 🔴 | | -| [[execution.queryable.concept](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.queryable.concept)] | 🔴 | 🔴 | 🔴 | | -| [[execution-async.ops](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution-async.ops)] | 🔴 | 🔴 | 🔴 | | -| [[execution.syn](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.syn)] | 🔴 | 🔴 | 🔴 | | -| [[execution.queries](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.queries)] | ✅ | ✅ | ✅ | empty | -| [[execution.forwarding_query](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.forwarding_query)] | ✅ | ✅ | 🔴 | | -| [[execution.get_allocator](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.get_allocator)] | ✅ | ✅ | 🔴 | | -| [[execution.get_stop_token](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.get_stop_token)] | ✅ | ✅ | 🔴 | | -| [[execution.environment.get_env](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.environment.get_env)] | ✅ | ✅ | 🔴 | | -| [[execution.get_domain](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.get_domain)] | ✅ | ✅ | 🔴 | | -| [[execution.get_scheduler](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.get_scheduler)] | 🔴 | 🔴 | 🔴 | | -| [[execution.get_delegation_scheduler](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.get_delegation_scheduler)] | 🔴 | 🔴 | 🔴 | | -| [[execution.get_forward_progress_guarantee](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.get_forward_progress_guarantee)] | 🔴 | 🔴 | 🔴 | | -| [[execution.get_completion_scheduler](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.get_completion_scheduler)] | 🔴 | 🔴 | 🔴 | | -| [[execution.schedulers](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.schedulers)] | 🔴 | 🔴 | 🔴 | | -| [[execution.receivers](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.receivers)] | ✅ | ✅ | ✅ | empty | -| [[execution.receiver_concepts](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.receiver_concepts)] | 🔴 | 🔴 | 🔴 | | -| [[execution.receivers.set_value](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.receivers.set_value)] | ✅ | ✅ | 🔴 | | -| [[execution.receivers.set_error](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.receivers.set_error)] | ✅ | ✅ | 🔴 | | -| [[execution.receivers.set_stopped](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.receivers.set_stopped)] | ✅ | ✅ | 🔴 | | -| [[execution.opstate](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.opstate)] | ✅ | ✅ | 🔴 | | -| [[execution.opstate.start](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.opstate.start)] | ✅ | ✅ | 🔴 | | -| [[execution.senders](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders)] | ✅ | ✅ | ✅ | empty | -| [[execution.senders.general](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.general)] | 🔴 | 🔴 | 🔴 | | -| [[execution.snd.concepts](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.snd.concepts)] | 🔴 | 🔴 | 🔴 | | -| [[execution.default_domain](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.default_domain)] | 🔴 | 🔴 | 🔴 | | -| [[execution.default_domain.statics](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.default_domain.statics)] | 🔴 | 🔴 | 🔴 | | -| [[execution.sender_transform](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.sender_transform)] | 🔴 | 🔴 | 🔴 | | -| [[execution.env_transform](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.env_transform)] | 🔴 | 🔴 | 🔴 | | -| [[execution.apply_sender](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.apply_sender)] | 🔴 | 🔴 | 🔴 | | -| [[execution.getcomplsigs](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.getcomplsigs)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.connect](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.connect)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.factories](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.factories)] | ✅ | ✅ | ✅ | empty | -| [[execution.senders.schedule](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.schedule)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.just](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.just)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.read.env](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.read.env)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.adapt](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.adapt)] | ✅ | ✅ | ✅ | empty | -| [[execution.senders.adapt.general](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.adapt.general)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.adaptor.objects](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.adaptor.objects)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.adapt.starts.on](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.adapt.starts.on)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.adapt.continues.on](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.adapt.continues.on)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.adaptors.schedule_from](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.adaptors.schedule_from)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.adaptors.on](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.adaptors.on)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.adaptor.then](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.adaptor.then)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.adapt.let](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.adapt.let)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.adapt.bulk](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.adapt.bulk)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.adapt.split](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.adapt.split)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.adaptor.when_all](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.adaptor.when_all)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.adapt.into_variant](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.adapt.into_variant)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.adapt.stopped_as_optional](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.adapt.stopped_as_optional)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.adapt.stopped_as_error](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.adapt.stopped_as_error)] | 🔴 | 🔴 | 🔴 | | -| [[execution.senders.consumers](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.consumers)] | ✅ | ✅ | ✅ | empty | -| [[execution.senders.consumers.sync_wait](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.senders.consumers.sync_wait)] | 🔴 | 🔴 | 🔴 | | -| [[execution.snd_rec_utils](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.snd_rec_utils)] | ✅ | ✅ | ✅ | empty | -| [[execution.snd_rec_utils.completion_sigs](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.snd_rec_utils.completion_sigs)] | 🔴 | 🔴 | 🔴 | | -| [[execution.snd_rec_utils.transform_completion_sigs](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.snd_rec_utils.transform_completion_sigs)] | 🔴 | 🔴 | 🔴 | | -| [[execution.contexts](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.contexts)] | ✅ | ✅ | ✅ | empty | -| [[execution.contexts.run_loop](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.contexts.run_loop)] | 🔴 | 🔴 | 🔴 | | -| [[execution.contexts.run_loop.types](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.contexts.run_loop.types)] | 🔴 | 🔴 | 🔴 | | -| [[execution.contexts.run_loop.ctor](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.contexts.run_loop.ctor)] | 🔴 | 🔴 | 🔴 | | -| [[execution.contexts.run_loop.members](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.contexts.run_loop.members)] | 🔴 | 🔴 | 🔴 | | -| [[execution.coro_utils](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.coro_utils)] | ✅ | ✅ | ✅ | empty | -| [[execution.coro_utils.as_awaitable](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.coro_utils.as_awaitable)] | 🔴 | 🔴 | 🔴 | | -| [[execution.coro_utils.with_awaitable_senders](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#execution.coro_utils.with_awaitable_senders)] | 🔴 | 🔴 | 🔴 | | -| [[allocator.requirements.general](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#allocator.requirements.general)] | ✅ | ✅ | 🔴 | | -| [[exec.awaitables](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#exec.awaitables)] | 🔴 | 🔴 | 🔴 | | diff --git a/docs/implementation-status.md b/docs/implementation-status.md index c7cbd2e1..dfcc95a0 100644 --- a/docs/implementation-status.md +++ b/docs/implementation-status.md @@ -26,11 +26,11 @@ Each section containing subelements reflects the state of the "worst" element. - ✅✅✅ [AS-EXCEPT-PTR(error)](https://wg21.link/exec.general#8): [`as_except_ptr.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/as_except_ptr.hpp) - ❎❎❎ [as-const(error)](https://wg21.link/exec.general#9): [std::as_const](https://wg21.link/utility.as.const)(error) -## 🚧✅✅ [exec.queryable](https://wg21.link/exec.queryable) Query and queryables -### 🚧❎❎ [exec.queryable.general](https://wg21.link/exec.queryable.general) General -### 🚧✅✅ [exec.queryable.concept](https://wg21.link/exec.queryable.concept) Queryable concept +## ✅✅✅ [exec.queryable](https://wg21.link/exec.queryable) Query and queryables +### ❎❎❎ [exec.queryable.general](https://wg21.link/exec.queryable.general) General +### ✅✅✅ [exec.queryable.concept](https://wg21.link/exec.queryable.concept) Queryable concept -- 🚧✅✅ [queryable<Q>](https://wg21.link/exec.queryable.concept#1): [`queryable.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/queryable.hpp) +- ✅✅✅ [queryable<Q>](https://wg21.link/exec.queryable.concept#1): [`queryable.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/queryable.hpp) ## ❎❎❎ [exec.async.ops](https://wg21.link/exec.async.ops) Asynchronous operations ## ✅✅🔴 [execution.syn](https://wg21.link/execution.syn) Header `` synopsis @@ -52,7 +52,7 @@ Each section containing subelements reflects the state of the "worst" element. - ✅✅✅ [single-sender-value_type<Sndr, Env...>](https://wg21.link/exec.queryable.concept#1): [`single_sender_value_type.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/single_sender_value_type.hpp) - ✅✅✅ [single-sender<Sndr, Env...>](https://wg21.link/exec.queryable.concept#1): [`single_sender.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/single_sender.hpp) -## 🔴🔴🔴 [exec.queries](https://wg21.link/exec.queries) Queries +## ✅✅✅ [exec.queries](https://wg21.link/exec.queries) Queries ### ✅✅✅ [exec.queries.expos](https://wg21.link/exec.queries.expos) Query utilities - ✅✅✅ [TRY-QUERY(q, tag, a...)](https://wg21.link/exec.queries.expos#2): [`try_query.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/try_query.hpp) @@ -72,14 +72,9 @@ Each section containing subelements reflects the state of the "worst" element. - ✅✅✅ [`get_forward_progress_guarantee`](https://wg21.link/exec.get.fwd.progress#2): [`get_forward_progress_guarantee.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_forward_progress_guarantee.hpp) ### ✅✅✅ [exec.get.compl.sched](https://wg21.link/exec.get.compl.sched) `execution::get_completion_scheduler`: [`get_completion_scheduler.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_completion_scheduler.hpp) +### ✅✅✅ [exec.get.compl.domain](https://wg21.link/exec.get.compl.domain) `execution::get_completion_domain`: [`get_completion_domain.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_completion_domain.hpp) -- ❎ check [exec.get.compl.sched p6](https://wg21.link/exec.get.compl.sched#6) - -### ✅✅🔴 [exec.get.compl.domain](https://wg21.link/exec.get.compl.domain) `execution::get_completion_domain`: [`get_completion_domain.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_completion_domain.hpp) - -- ❎ check [exec.get.compl.domain p3](https://wg21.link/exec.get.compl.domain#3 - -### ✅🔴🔴 [exec.get.await.adapt](https://wg21.link/exec.get.await.adapt) `execution::get_await_completion_adaptor`: [`get_await_completion_adaptor.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_await_completion_adaptor.hpp) +### ✅✅✅ [exec.get.await.adapt](https://wg21.link/exec.get.await.adapt) `execution::get_await_completion_adaptor`: [`get_await_completion_adaptor.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_await_completion_adaptor.hpp) ## ✅🔴✅ [exec.sched](https://wg21.link/exec.sched) Schedulers - ✅✅✅ [`scheduler`](https://wg21.link/exec.sched#1): [`scheduler.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/scheduler.hpp) diff --git a/docs/overview.md b/docs/overview.md index 7a4c9cc6..ba3408f2 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -35,6 +35,7 @@ Required members for _State_: - The type `operation_state_concept` is an alias for `operation_state_tag` or a type derived thereof. - state.start() & noexcept +
    Example @@ -55,6 +56,7 @@ struct example_state static_assert(std::execution::operation_state>); ```
    +
    receiver<Receiver> @@ -79,6 +81,7 @@ Typical members for _Receiver_: - set_error(error) && noexcept -> void - set_stopped() && noexcept -> void +
    Example @@ -113,12 +116,14 @@ struct example_receiver static_assert(std::execution::receiver>); ```
    +
    receiver_of<Receiver, Completions> The concept receiver_of<Receiver, Completions> tests whether std::execution::receiver<_Receiver_> is true and if an object of type _Receiver_ can be invoked with each of the completion signals in _Completions_. +
    Example @@ -155,6 +160,7 @@ static_assert(not std::execution::receiver_of +
    scheduler<Scheduler> @@ -164,9 +170,11 @@ Requirements for _Scheduler_: - The type _Scheduler_::scheduler_concept is an alias for `scheduler_tag` or a type derived thereof. - schedule(_scheduler_) -> sender - The value completion scheduler of the sender’s environment is the _scheduler_: - _scheduler_ == std::execution::get_completion_scheduler<std::execution::set_value_t>( - std::execution::get_env(std::execution::schedule(_scheduler_)) - ) + + scheduler == std::execution::get_completion_scheduler<std::execution::set_value_t>( + std::execution::get_env(std::execution::schedule(scheduler)) + ) + - std::equality_comparable<_Scheduler_> - std::copy_constructible<_Scheduler_>
    @@ -187,6 +195,7 @@ Typical members for _Sender_: - _Sender_::completion_signatures is a type alias for std::execution::completion_signatures<...> (if there is no get_completion_signatures member). - connect(_sender_, receiver) -> operation_state +
    Example The example shows a sender implementing an operation similar to just(_value). @@ -222,11 +231,12 @@ struct example_sender static_assert(std::execution::sender); ```
    +
    sender_in<Sender, Env = std::execution::env<>> -The concept sender_in<Sender, Env> tests whether _Sender_ is a sender, _Env_ is a destructible type, and std::execution::get_completion_signatures(_sender_, _env_) yields a specialization of std::execution::completion_signatures. +The concept sender_in<Sender, Env> tests whether _Sender_ is a sender, _Env_ is a destructible type, and std::execution::get_completion_signatures<_Sender_, _Env_>() yields a specialization of std::execution::completion_signatures.
    sender-to<Sender, Receiver> @@ -241,33 +251,30 @@ To determine if _Receiver_ can receive all sends_stopped<Sender, Env> determines if _Sender_ may send a stopped completion signal. To do so, the concepts determines if std::execution::get_completion_signals(_sender_, _env_) contains the signatures std::execution::set_stopped_t().
    -stoppable_token<_Token_> -A stoppable_token<_Token_>, e.g., obtained via std::execution::get_stop_token(_env_) is used to support cancellation of asynchronous operations. Using _token_.stop_requested() an active operation can poll whether it was requested to cancel. An inactive operation waiting for a notification can use an object of a specialization of the template _Token_::callback_type to get notified when cancellation is requested. +stoppable_token<Token> +A stoppable_token<Token>, e.g., obtained via std::execution::get_stop_token(env) is used to support cancellation of asynchronous operations. Using token.stop_requested() an active operation can poll whether it was requested to cancel. An inactive operation waiting for a notification can use an object of a specialization of the template Token::callback_type to get notified when cancellation is requested. Required members for _Token_: -- _Token_::callback_type<_Callback_> can be specialized with a std::callable<_Callback_> type. -- _token_.stop_requested() const noexcept -> bool -- _token_.stop_possible() const noexcept -> bool -- std::copyable<_Token_> -- std::equality_comparable<_Token_> -- std::swappable<_Token_> +- Token::callback_type<Callback> can be specialized with a std::callable<Callback> type. +- token.stop_requested() const noexcept -> bool +- token.stop_possible() const noexcept -> bool +- std::copyable<Token> +- std::equality_comparable<Token> +- std::swappable<Token>
    Example: concept use -
    ```c++ static_assert(std::execution::unstoppable_token); static_assert(std::execution::unstoppable_token); static_assert(std::execution::unstoppable_token); ``` -
    Example: polling -
    -This example shows a sketch of using a stoppable_token<_Token_> to cancel an active operation. The computation in this example is represented as `sleep_for`. +This example shows a sketch of using a stoppable_token<Token> to cancel an active operation. The computation in this example is represented as sleep_for. ```c++ void compute(std::stoppable_token auto token) @@ -278,12 +285,10 @@ void compute(std::stoppable_token auto token) } } ``` -
    Example: inactive -
    -This example shows how an operation_state can use the callback_type together with a _token_ to get notified when cancellation is requested. +This example shows how an operation_state can use the callback_type together with a token to get notified when cancellation is requested. ```c++ template @@ -330,17 +335,17 @@ struct example_state } }; ``` -
    +
    -unstoppable_token<_Token_> -The concept unstoppable_token<Token> is modeled by a _Token_ if stoppable_token<_Token_> is true and it can statically be determined that both _token_.stop_requested() and _token_.stop_possible() are `constexpr` epxressions yielding `false`. This concept is used to avoid extra work when using stop tokens which will never indicate that cancellations are requested. +unstoppable_token<Token> +The concept unstoppable_token<Token> is modeled by a Token if stoppable_token<Token> is true and it can statically be determined that both token.stop_requested() and token.stop_possible() are constexpr epxressions yielding false. This concept is used to avoid extra work when using stop tokens which will never indicate that cancellations are requested.
    Example -The concept yields `true` for the std::execution::never_stop_token: +The concept yields true for the std::execution::never_stop_token: ```c++ static_assert(std::execution::unstoppable_token); @@ -356,7 +361,7 @@ The queries are used to obtain properties associated with an object.
    Example defining a query on an environment -This example shows how to define an environment class which provides a get_allocator query. The objects stores a `std::pmr::memory_resource*` and returns a correspondingly initialized `std::pmr::polymorphic_allocator<>`. +This example shows how to define an environment class which provides a get_allocator query. The objects stores a std::pmr::memory_resource* and returns a correspondingly initialized std::pmr::polymorphic_allocator<>. ``` struct alloc_env { @@ -370,20 +375,20 @@ struct alloc_env {
    forwarding_query(query) -> bool -Default: `false` +Default: false
    -The expression forwarding_query(query) is a `constexpr` query used to determine if the query query should be forwarded when wrapping an environment. The expression is required to be a core constant expression if query is a core constant expression. +The expression forwarding_query(query) is a constexpr query used to determine if the query query should be forwarded when wrapping an environment. The expression is required to be a core constant expression if query is a core constant expression. The result of the expression is determined as follows:
      -
    1. The result is the value of the expression query.query(forwarding_query) if this expression is valid and `noexcept`.
    2. +
    3. The result is the value of the expression query.query(forwarding_query) if this expression is valid and noexcept.
    4. The result is true if the type of query is publicly derived from forwarding_query.
    5. Otherwise the result is false.
    Example -When defining a custom query custom it is desirable to allow the query getting forwarded. It is necessary to explicit define the result of forwarding_query(custom). The result can be defined by providing a corresponding `query` member function. When using this approach the function isn’t allowed to throw, needs to return `bool`, and needs to be a core constant expression: +When defining a custom query custom it is desirable to allow the query getting forwarded. It is necessary to explicit define the result of forwarding_query(custom). The result can be defined by providing a corresponding query member function. When using this approach the function isn’t allowed to throw, needs to return bool, and needs to be a core constant expression: ``` struct custom_t { @@ -395,7 +400,7 @@ struct custom_t { inline constexpr custom_t custom{}; ``` -Alternatively, the query can be defined as forwarding by deriving publicly from `forwarding_query_t`: +Alternatively, the query can be defined as forwarding by deriving publicly from forwarding_query_t: ``` struct custom_t: forwarding_query_t { @@ -405,16 +410,21 @@ struct custom_t: forwarding_query_t {
    +
    +get_await_completion_adaptor(queryable) -> awaiter +If the expression get_await_completion_adaptor(queryable) is valid it yields an awaiter depending on the queryable. This query is used while getting an awaiter from a sender. +
    +
    get_env(queryable) -> env -Default: `env<>` +Default: env<>
    -The expression get_env(queryable) is used to get the environment env associated with queryable. To provide a non-default environment for a queryable a `get_env` member needs to be defined. If queryable doesn’t provide the get_env query an object of type env<> is returned. +The expression get_env(queryable) is used to get the environment env associated with queryable. To provide a non-default environment for a queryable a get_env member needs to be defined. If queryable doesn’t provide the get_env query an object of type env<> is returned. The value of the expression is
    1. the result of as_const(queryable).get_env() if this expression is valid and noexcept.
    2. env<> otherwise.
    -
    +
    Example The example defines an environment class env which stores a pointer to the relevant data and is returned as the environment for the type `queryable`: @@ -425,7 +435,7 @@ struct data { /*...*/ }; struct env { data* d; /* ... */ }; struct queryable { - data* d;\ + data* d; // ... env get_env() const noexcept { return { this->d }; } }; @@ -433,8 +443,9 @@ struct queryable { Note that the `get_env` member is both `const` and `noexcept`.
    -
    +
    +
    get_allocator(env) -> allocator Default: none @@ -446,10 +457,10 @@ The expression get_allocator(env) returns an alloca
  • the result of the expression satisfies simple-allocator.
  • Otherwise the expression is ill-formed. -
    +
    Example -This example shows how to define an environment class which provides a get_allocator query. The objects stores a `std::pmr::memory_resource*` and returns a correspondingly initialized `std::pmr::polymorphic_allocator<>`. +This example shows how to define an environment class which provides a get_allocator query. The objects stores a std::pmr::memory_resource* and returns a correspondingly initialized std::pmr::polymorphic_allocator<>. ``` struct alloc_env { @@ -461,8 +472,9 @@ struct alloc_env { }; ```
    -
    +
    +
    get_completion_domain<Tag>(attrs) -> domain Default: none @@ -504,23 +516,27 @@ To determine the result the sender is first transformed usin
  • completion_signatures<set_value_t(T), set_error_t(exception_ptr), set_stopped_t()> if New-Sender-Type is an awaitable type which would yield an object of type T when it is co_awaited;
  • invalid otherwise.
  • -
    +
    Example -When a sender doesn’t need to compute the completion signatures based on an environment it is easiest to use a the type alias, e.g.: +Even when a sender doesn’t need to compute the completion signatures based on an environment it is necessary to provide get_completion_signatures member function, e.g.: + ```c++ struct sender { using sender_concept = std::execution::sender_tag; - using completion_signatures = std::completion_signatures< - std::execution::set_value_t(int), - std::execution::set_error_t(std::error_code), - std::execution::set_stopped() - >; + template + static consteval void get_completion_signatures() { + return std::completion_signatures< + std::execution::set_value_t(int), + std::execution::set_error_t(std::error_code), + std::execution::set_stopped() + >{}; + } // ... }; ```
    -
    +
    get_delegation_scheduler(env) -> scheduler @@ -534,7 +550,7 @@ Otherwise the expression is invalid.
    get_domain(env) -> domain -The expression get_domain(env) yields the domain associated with env. The value of the expression is equivalent to +The expression get_domain(env) yields the domain associated with env. The value of the expression is equivalent to return D() where D is the type of the expression
    1. auto(as_const(env).query(get_domain)) if this expression is valid;
    2. otherwise, get_completion_domain<set_value_t>(get_scheduler(env), HIDE-SCHED(env)) if this expression is valid;
    3. @@ -574,7 +590,7 @@ Otherwise the expression is invalid. If the expression get_start_scheduler(get_env(rcvr)) is well-formed it should yield the scheduler the operation state resulting -from connect(sndr>, rcvr) gets started on. +from connect(sndr, rcvr) gets started on.
    get_stop_token(env) -> stoppable_token @@ -618,7 +634,7 @@ Sender factories create a sender which forms the start of a graph of lazy work i
    just(value...) -> sender-of<set_value_t(Value...)> -The expression just(value...) creates a sender which sends value... on the `set_value` (success) channel when started (note that value... can be empty). +The expression just(value...) creates a sender which sends value... on the set_value (success) channel when started (note that value... can be empty). Completions
      @@ -627,7 +643,7 @@ The expression just(value...) creates a sender which sends <
    just_error(error) -> sender-of<set_error_t(Error)> -The expression just_error(error) creates a sender which sends error on the `set_error` (failure) channel when started. +The expression just_error(error) creates a sender which sends error on the set_error (failure) channel when started. Completions
      @@ -636,7 +652,7 @@ The expression just_error(error) creates a sender which send
    just_stopped() -> sender-of<set_stopped_t()> -The expression just_stopped() creates a sender which sends a completion on the `set_stopped` (cancellation) channel when started. +The expression just_stopped() creates a sender which sends a completion on the set_stopped (cancellation) channel when started. Completions
      @@ -645,7 +661,7 @@ The expression just_stopped() creates a sender which sends a comple
    read_env(query) -> sender-of<set_value_t(query-result)> -The expression read_env(query) creates a sender which sends the result of querying query the environment of the receiver it gets connected to on the `set_value` channel when started. Put differently, it calls set_value(move(receiver), query(get_env(receiver))). For example, in a coroutine it may be useful to extra the stop token associated with the coroutine which can be done using read_env: +The expression read_env(query) creates a sender which sends the result of querying query the environment of the receiver it gets connected to on the set_value channel when started. Put differently, it calls set_value(move(receiver), query(get_env(receiver))). For example, in a coroutine it may be useful to extra the stop token associated with the coroutine which can be done using read_env: ```c++ auto token = co_await read_env(get_stop_token); @@ -658,7 +674,7 @@ auto token = co_await read_env(get_stop_token);
    schedule(scheduler) -> sender-of<set_value_t()> -The expression schedule(scheduler) creates a sender which upon success completes on the set_value channel without any arguments running on the execution context associated with scheduler. Depending on the scheduler it is possible that the sender can complete with an error if the scheduling fails or using `set_stopped()` if the operation gets cancelled before it is successful. +The expression schedule(scheduler) creates a sender which upon success completes on the set_value channel without any arguments running on the execution context associated with scheduler. Depending on the scheduler it is possible that the sender can complete with an error if the scheduling fails or using set_stopped() if the operation gets cancelled before it is successful. Completions
      @@ -673,8 +689,7 @@ The sender adaptors take one or more senders and adapt their respective behavior
      affine(sender) -> sender-of<completions-of(sender)> -The expression affine(sender) creates -a sender which completes on the same scheduler it was started on, even if sender changes the scheduler. The scheduler to resume on is determined using get_scheduler(get_env(rcvr)) where rcvr is the receiver the sender is connected to. +The expression affine(sender) creates a sender which completes on the same scheduler it was started on, even if sender changes the scheduler. The scheduler to resume on is determined using get_start_scheduler(get_env(rcvr)) where rcvr is the receiver the sender is connected to. The scheduler sched returned from get_start_scheduler(get_env(rcvr)) has to be infallible, i.e., the completion signtures of scheduler(sched) only contain set_value_t(). The primary use of affine is implementing scheduler affinity for task.
      diff --git a/tests/beman/execution/CMakeLists.txt b/tests/beman/execution/CMakeLists.txt index 0ff48cfb..bc27cbb2 100644 --- a/tests/beman/execution/CMakeLists.txt +++ b/tests/beman/execution/CMakeLists.txt @@ -24,6 +24,7 @@ list( exec-general.test exec-getcomplsigs.test exec-get-allocator.test + exec-get-await-adapt.test exec-get-compl-domain.test exec-get-compl-sched.test exec-get-delegation-scheduler.test diff --git a/tests/beman/execution/exec-get-await-adapt.test.cpp b/tests/beman/execution/exec-get-await-adapt.test.cpp new file mode 100644 index 00000000..7f2913d4 --- /dev/null +++ b/tests/beman/execution/exec-get-await-adapt.test.cpp @@ -0,0 +1,40 @@ +// tests/beman/execution/exec-get-await-adapt.test.cpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#ifdef BEMAN_HAS_IMPORT_STD +import std; +#else +#include +#include +#endif +#ifdef BEMAN_HAS_MODULES +import beman.execution; +#else +#include +#endif + +// ---------------------------------------------------------------------------- + +namespace { +struct awaiter { + int value{}; + auto operator==(const awaiter&) const noexcept -> bool = default; + auto await_ready() const noexcept -> bool { return true; } + auto await_suspend(std::coroutine_handle<>) const noexcept -> void {} + auto await_resume() const noexcept -> void {} +}; + +struct env { + int value{}; + auto query(beman::execution::get_await_completion_adaptor_t) const noexcept -> awaiter { return {this->value}; } +}; +} // namespace + +TEST(exec_get_await_adapt) { + ASSERT(beman::execution::get_await_completion_adaptor(env{17}).value == 17); + [](const auto& env) { + ASSERT(!requires { beman::execution::get_await_completion_adaptor(env); }); + }(test_std::env<>{}); +} From a96fb21cd9e2b4ebb24e440d87d595e9ab2fa8ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sat, 15 Aug 2026 21:35:41 +0100 Subject: [PATCH 6/6] added the missing infallible-scheduler test --- docs/implementation-status.md | 4 ++-- docs/overview.md | 8 ++----- src/beman/execution/execution-detail.cppm | 1 + tests/beman/execution/exec-sched.test.cpp | 28 +++++++++++++++++++++++ 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/docs/implementation-status.md b/docs/implementation-status.md index dfcc95a0..87d67519 100644 --- a/docs/implementation-status.md +++ b/docs/implementation-status.md @@ -75,10 +75,10 @@ Each section containing subelements reflects the state of the "worst" element. ### ✅✅✅ [exec.get.compl.domain](https://wg21.link/exec.get.compl.domain) `execution::get_completion_domain`: [`get_completion_domain.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_completion_domain.hpp) ### ✅✅✅ [exec.get.await.adapt](https://wg21.link/exec.get.await.adapt) `execution::get_await_completion_adaptor`: [`get_await_completion_adaptor.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/get_await_completion_adaptor.hpp) -## ✅🔴✅ [exec.sched](https://wg21.link/exec.sched) Schedulers +## ✅✅✅ [exec.sched](https://wg21.link/exec.sched) Schedulers - ✅✅✅ [`scheduler`](https://wg21.link/exec.sched#1): [`scheduler.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/scheduler.hpp) -- ✅🔴✅ [infallible-scheduler](https://wg21.link/exec.sched#8): [`infallible_scheduler.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/infallible_scheduler.hpp) +- ✅✅✅ [infallible-scheduler](https://wg21.link/exec.sched#8): [`infallible_scheduler.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/infallible_scheduler.hpp) ## 🔴🔴🔴 [exec.recv](https://wg21.link/exec.recv) Receivers ### 🔴🔴🔴 [exec.recv.concepts](https://wg21.link/exec.recv.concepts) Receiver concepts diff --git a/docs/overview.md b/docs/overview.md index ba3408f2..9b3f1ad5 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -1019,13 +1019,9 @@ expressions HIDE-SCHED(q).query(tag, a...) is
    -infallible-scheduler<Sched> +infallible-scheduler<Sched, Env> -Determines if Sched is a scheduler (i.e., scheduler<Sched> is true) -and if Sched's sender has only a set_value_t() completion signature when used with -an environment with an unstoppable_token<Tok> stop token Tok. If the -stop token Tok is not unstoppable_token<Tok> the completion signatures -can include a set_stopped_t() completion signature in addition to the set_value_t() completion signature. +Determines if Sched is a scheduler (i.e., scheduler<Sched> is true) and if sched's sender has only a set_value_t() completion signature when used with an environment with an unstoppable_token<Tok> stop token Tok. If the stop token Tok is not unstoppable_token<Tok> the completion signatures can include a set_stopped_t() completion signature in addition to the set_value_t() completion signature.
    diff --git a/src/beman/execution/execution-detail.cppm b/src/beman/execution/execution-detail.cppm index 591f6275..f278af37 100644 --- a/src/beman/execution/execution-detail.cppm +++ b/src/beman/execution/execution-detail.cppm @@ -40,6 +40,7 @@ export import beman.execution.detail.immovable; export import beman.execution.detail.impls_for; export import beman.execution.detail.indices_for; export import beman.execution.detail.indirect_meta_apply; +export import beman.execution.detail.infallible_scheduler; export import beman.execution.detail.inline_attrs; export import beman.execution.detail.inline_scheduler; export import beman.execution.detail.is_awaitable; diff --git a/tests/beman/execution/exec-sched.test.cpp b/tests/beman/execution/exec-sched.test.cpp index e12b5cf1..d296bcdf 100644 --- a/tests/beman/execution/exec-sched.test.cpp +++ b/tests/beman/execution/exec-sched.test.cpp @@ -4,6 +4,7 @@ #include #ifdef BEMAN_HAS_MODULES import beman.execution; +import beman.execution.detail; #else #include #include @@ -24,9 +25,29 @@ struct env { } }; +struct infallible_env {}; +struct stoppable_env { + auto query(test_std::get_stop_token_t) const noexcept { return test_std::inplace_stop_token{}; } +}; +struct fallible_env { + auto query(test_std::get_stop_token_t) const noexcept { return test_std::inplace_stop_token{}; } +}; + template struct sender { using sender_concept = test_std::sender_tag; + template + static consteval auto get_completion_signatures() noexcept { + if constexpr (sizeof...(Ev) == 0 || + (false || ... || + test_std::unstoppable_token()))>)) { + return test_std::completion_signatures(); + } else if constexpr (sizeof...(Ev) == 1 && (false || ... || std::same_as)) { + return test_std::completion_signatures(); + } else { + return test_std::completion_signatures(); + } + } auto get_env() const noexcept { return Env{}; } }; @@ -112,6 +133,12 @@ template auto test_scheduler() -> void { static_assert(Expect == test_std::scheduler); } + +auto test_infallible_scheduler() -> void { + static_assert(test_detail::infallible_scheduler); + static_assert(test_detail::infallible_scheduler); + static_assert(not test_detail::infallible_scheduler); +} } // namespace TEST(exec_sched) { @@ -128,4 +155,5 @@ TEST(exec_sched) { test_scheduler(); test_scheduler(); test_scheduler(); + test_infallible_scheduler(); }