From 6146e2d5ae00d765dcff5f8535ed01ce25977012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Thu, 31 Jul 2025 20:28:14 +0100 Subject: [PATCH 1/5] added a missing completion signal for scheduler_from --- .../beman/execution/detail/schedule_from.hpp | 3 +- tests/beman/execution/CMakeLists.txt | 1 + tests/beman/execution/issue-174.test.cpp | 51 +++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 tests/beman/execution/issue-174.test.cpp diff --git a/include/beman/execution/detail/schedule_from.hpp b/include/beman/execution/detail/schedule_from.hpp index 8dc26d91..8176c7e6 100644 --- a/include/beman/execution/detail/schedule_from.hpp +++ b/include/beman/execution/detail/schedule_from.hpp @@ -138,7 +138,8 @@ struct impls_for<::beman::execution::detail::schedule_from_t> : ::beman::executi ::beman::execution::env_of_t>, //-dk:TODO get proper error completion signatures ::beman::execution::completion_signatures<::beman::execution::set_error_t( - ::std::exception_ptr)>>>>>>; + ::std::exception_ptr), + ::beman::execution::set_stopped_t()>>>>>>; return state_type(sch, receiver); }}; diff --git a/tests/beman/execution/CMakeLists.txt b/tests/beman/execution/CMakeLists.txt index 899c28d9..696ec350 100644 --- a/tests/beman/execution/CMakeLists.txt +++ b/tests/beman/execution/CMakeLists.txt @@ -12,6 +12,7 @@ list(APPEND todo exec-associate.test) list( APPEND execution_tests + issue-174.test exec-scope-counting.test exec-spawn.test exec-stop-when.test diff --git a/tests/beman/execution/issue-174.test.cpp b/tests/beman/execution/issue-174.test.cpp new file mode 100644 index 00000000..a04fab5b --- /dev/null +++ b/tests/beman/execution/issue-174.test.cpp @@ -0,0 +1,51 @@ +#include +#include +#include +#include + +namespace ex = beman::execution; + +namespace { + std::thread::id main_thread_id = std::this_thread::get_id(); + + template + void debug(std::format_string fmt, Args&&... args) { + auto thread_id = std::this_thread::get_id(); + auto thread_name = thread_id == main_thread_id ? "main" : (std::stringstream{} << thread_id).str(); + std::clog << std::format("[thread-{}] {}\n", thread_name, std::format(fmt, std::forward(args)...)); + } +} + +int main() { + ex::run_loop ex_context1; + std::thread thread1{ + [&ex_context1] { + debug("ex_context1 run..."); + ex_context1.run(); + } + }; + + ex::run_loop ex_context2; + std::thread thread2{ + [&ex_context2] { + debug("ex_context2 run..."); + ex_context2.run(); + } + }; + + ex::sender auto snd = ex::just() | ex::then([] { + debug("#1"); + }) | ex::continues_on(ex_context1.get_scheduler()) | ex::then([] { + debug("#2"); + }) | ex::continues_on(ex_context2.get_scheduler()) | ex::then([] { + debug("#3"); + }); + + ex::sync_wait(snd); + + ex_context1.finish(); + ex_context2.finish(); + + thread2.join(); + thread1.join(); +} From de0579e486f85b77e097b57087c18fc5ef362652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Thu, 31 Jul 2025 20:31:17 +0100 Subject: [PATCH 2/5] added missing identifier --- tests/beman/execution/issue-174.test.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/beman/execution/issue-174.test.cpp b/tests/beman/execution/issue-174.test.cpp index a04fab5b..35853a2f 100644 --- a/tests/beman/execution/issue-174.test.cpp +++ b/tests/beman/execution/issue-174.test.cpp @@ -1,3 +1,6 @@ +// tests/beman/execution/issue-174.test.cpp *-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + #include #include #include From b497050a29b1a4193f4452883748cf7ffc8efebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Thu, 31 Jul 2025 20:36:44 +0100 Subject: [PATCH 3/5] clean-up the test --- tests/beman/execution/issue-174.test.cpp | 59 ++++++++---------------- 1 file changed, 18 insertions(+), 41 deletions(-) diff --git a/tests/beman/execution/issue-174.test.cpp b/tests/beman/execution/issue-174.test.cpp index 35853a2f..d9a29705 100644 --- a/tests/beman/execution/issue-174.test.cpp +++ b/tests/beman/execution/issue-174.test.cpp @@ -2,53 +2,30 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include -#include -#include #include +#include namespace ex = beman::execution; namespace { - std::thread::id main_thread_id = std::this_thread::get_id(); - - template - void debug(std::format_string fmt, Args&&... args) { - auto thread_id = std::this_thread::get_id(); - auto thread_name = thread_id == main_thread_id ? "main" : (std::stringstream{} << thread_id).str(); - std::clog << std::format("[thread-{}] {}\n", thread_name, std::format(fmt, std::forward(args)...)); - } -} - -int main() { - ex::run_loop ex_context1; - std::thread thread1{ - [&ex_context1] { - debug("ex_context1 run..."); - ex_context1.run(); - } - }; - - ex::run_loop ex_context2; - std::thread thread2{ - [&ex_context2] { - debug("ex_context2 run..."); - ex_context2.run(); + struct thread_loop: ex::run_loop { + std::thread thread{[this] { this->run(); }}; + ~thread_loop() { + this->finish(); + this->thread.join(); } }; +} - ex::sender auto snd = ex::just() | ex::then([] { - debug("#1"); - }) | ex::continues_on(ex_context1.get_scheduler()) | ex::then([] { - debug("#2"); - }) | ex::continues_on(ex_context2.get_scheduler()) | ex::then([] { - debug("#3"); - }); - - ex::sync_wait(snd); - - ex_context1.finish(); - ex_context2.finish(); - - thread2.join(); - thread1.join(); +int main() { + thread_loop ex_context1; + thread_loop ex_context2; + + ex::sync_wait( + ex::just() + | ex::then([] { }) + | ex::continues_on(ex_context1.get_scheduler()) + | ex::then([] { }) + | ex::continues_on(ex_context2.get_scheduler()) | ex::then([] {}) + ); } From a1378689244da0402a93594e69b909663ca5e638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Thu, 31 Jul 2025 20:39:29 +0100 Subject: [PATCH 4/5] clang-format --- .../beman/execution/detail/schedule_from.hpp | 19 +++++++------- tests/beman/execution/issue-174.test.cpp | 25 ++++++++----------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/include/beman/execution/detail/schedule_from.hpp b/include/beman/execution/detail/schedule_from.hpp index 8176c7e6..47a5b763 100644 --- a/include/beman/execution/detail/schedule_from.hpp +++ b/include/beman/execution/detail/schedule_from.hpp @@ -130,16 +130,15 @@ struct impls_for<::beman::execution::detail::schedule_from_t> : ::beman::executi ::std::monostate, ::beman::execution::detail::meta::transform< ::beman::execution::detail::as_tuple_t, - ::beman::execution::detail::meta::to< - ::std::variant, - ::beman::execution::detail::meta::combine< - ::beman::execution::completion_signatures_of_t< - ::beman::execution::detail::child_type, - ::beman::execution::env_of_t>, - //-dk:TODO get proper error completion signatures - ::beman::execution::completion_signatures<::beman::execution::set_error_t( - ::std::exception_ptr), - ::beman::execution::set_stopped_t()>>>>>>; + ::beman::execution::detail::meta::to<::std::variant, + ::beman::execution::detail::meta::combine< + ::beman::execution::completion_signatures_of_t< + ::beman::execution::detail::child_type, + ::beman::execution::env_of_t>, + //-dk:TODO get proper error completion signatures + ::beman::execution::completion_signatures< + ::beman::execution::set_error_t(::std::exception_ptr), + ::beman::execution::set_stopped_t()>>>>>>; return state_type(sch, receiver); }}; diff --git a/tests/beman/execution/issue-174.test.cpp b/tests/beman/execution/issue-174.test.cpp index d9a29705..b88ba527 100644 --- a/tests/beman/execution/issue-174.test.cpp +++ b/tests/beman/execution/issue-174.test.cpp @@ -8,24 +8,19 @@ namespace ex = beman::execution; namespace { - struct thread_loop: ex::run_loop { - std::thread thread{[this] { this->run(); }}; - ~thread_loop() { - this->finish(); - this->thread.join(); - } - }; -} +struct thread_loop : ex::run_loop { + std::thread thread{[this] { this->run(); }}; + ~thread_loop() { + this->finish(); + this->thread.join(); + } +}; +} // namespace int main() { thread_loop ex_context1; thread_loop ex_context2; - ex::sync_wait( - ex::just() - | ex::then([] { }) - | ex::continues_on(ex_context1.get_scheduler()) - | ex::then([] { }) - | ex::continues_on(ex_context2.get_scheduler()) | ex::then([] {}) - ); + ex::sync_wait(ex::just() | ex::then([] {}) | ex::continues_on(ex_context1.get_scheduler()) | ex::then([] {}) | + ex::continues_on(ex_context2.get_scheduler()) | ex::then([] {})); } From 4d1bb754822d740514b36d43651357af89956bef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Thu, 31 Jul 2025 21:43:36 +0100 Subject: [PATCH 5/5] fixed compilation issues with Xcode-15.4 --- examples/sender-demo.cpp | 2 +- include/beman/execution/detail/counting_scope.hpp | 2 ++ include/beman/execution/detail/spawn_future.hpp | 4 ++-- include/beman/execution/detail/stop_when.hpp | 9 ++++----- tests/beman/execution/exec-opstate-start.test.cpp | 2 +- tests/beman/execution/exec-scope-counting.test.cpp | 4 ++-- tests/beman/execution/exec-spawn-future.test.cpp | 2 +- 7 files changed, 13 insertions(+), 12 deletions(-) diff --git a/examples/sender-demo.cpp b/examples/sender-demo.cpp index e998d294..d9ac194e 100644 --- a/examples/sender-demo.cpp +++ b/examples/sender-demo.cpp @@ -47,7 +47,7 @@ static_assert(ex::sender_in>); int main() { try { - auto j = just_sender{std::pmr::string("value")}; + auto j = just_sender{std::pmr::string("value")}; auto t = std::move(j) | ex::then([](const std::pmr::string& v) { return v + " then"; }); auto w = ex::when_all(std::move(t)); auto e = ex::detail::write_env(std::move(w), diff --git a/include/beman/execution/detail/counting_scope.hpp b/include/beman/execution/detail/counting_scope.hpp index 46370e7f..30def4a7 100644 --- a/include/beman/execution/detail/counting_scope.hpp +++ b/include/beman/execution/detail/counting_scope.hpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -50,6 +51,7 @@ class beman::execution::counting_scope::token : public ::beman::execution::detai explicit token(::beman::execution::counting_scope* s) : ::beman::execution::detail::counting_scope_base::token(s) {} }; +static_assert(::beman::execution::scope_token<::beman::execution::counting_scope::token>); // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/spawn_future.hpp b/include/beman/execution/detail/spawn_future.hpp index e282aa57..bafbce0e 100644 --- a/include/beman/execution/detail/spawn_future.hpp +++ b/include/beman/execution/detail/spawn_future.hpp @@ -128,13 +128,13 @@ struct spawn_future_state : alloc(::std::move(a)), op(::beman::execution::write_env( ::beman::execution::detail::stop_when(::std::forward(s), source.get_token()), env), - receiver_t(this)), + receiver_t{this}), token(::std::move(tok)), associated(token.try_associate()) { if (this->associated) { ::beman::execution::start(this->op); } else { - ::beman::execution::set_stopped(receiver_t(this)); + ::beman::execution::set_stopped(receiver_t{this}); } } auto complete() noexcept -> void override { diff --git a/include/beman/execution/detail/stop_when.hpp b/include/beman/execution/detail/stop_when.hpp index 371b7ec5..f989ec32 100644 --- a/include/beman/execution/detail/stop_when.hpp +++ b/include/beman/execution/detail/stop_when.hpp @@ -27,7 +27,6 @@ namespace beman::execution::detail { inline constexpr struct stop_when_t { - template <::beman::execution::sender Sndr, ::beman::execution::stoppable_token Tok> struct sender; @@ -102,12 +101,12 @@ struct beman::execution::detail::stop_when_t::sender { 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))) {} + inner_state(::beman::execution::connect(::std::forward(s), receiver{&this->base})) {} auto start() & noexcept { - this->cb1.emplace(this->tok, cb_t(this->base.source)); + 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)); + cb_t{this->base.source}); ::beman::execution::start(this->inner_state); } }; @@ -127,7 +126,7 @@ inline auto beman::execution::detail::stop_when_t::operator()(Sndr&& sndr, Tok&& if constexpr (::beman::execution::unstoppable_token) { return ::std::forward(sndr); } else { - return sender(*this, ::std::forward(tok), ::std::forward(sndr)); + return sender{*this, ::std::forward(tok), ::std::forward(sndr)}; } } diff --git a/tests/beman/execution/exec-opstate-start.test.cpp b/tests/beman/execution/exec-opstate-start.test.cpp index 45cd1bdc..c1ff95b7 100644 --- a/tests/beman/execution/exec-opstate-start.test.cpp +++ b/tests/beman/execution/exec-opstate-start.test.cpp @@ -21,7 +21,7 @@ struct non_opstate { template struct opstate { receiver rcvr; - auto start() const noexcept(Noexcept) -> void { test_std::set_value(receiver(this->rcvr.value), 42); } + auto start() const noexcept(Noexcept) -> void { test_std::set_value(receiver{this->rcvr.value}, 42); } }; template diff --git a/tests/beman/execution/exec-scope-counting.test.cpp b/tests/beman/execution/exec-scope-counting.test.cpp index 6e685134..32e183c5 100644 --- a/tests/beman/execution/exec-scope-counting.test.cpp +++ b/tests/beman/execution/exec-scope-counting.test.cpp @@ -109,7 +109,7 @@ auto mem() -> void { ASSERT(true == scope.get_token().try_associate()); bool called{false}; ASSERT(called == false); - auto state(test_std::connect(scope.join(), join_receiver(called))); + auto state(test_std::connect(scope.join(), join_receiver{called})); ASSERT(called == false); test_std::start(state); ASSERT(called == false); @@ -125,7 +125,7 @@ auto token() -> void { ASSERT(true == tok.try_associate()); bool called{false}; - auto state(test_std::connect(scope.join(), join_receiver(called))); + auto state(test_std::connect(scope.join(), join_receiver{called})); test_std::start(state); ASSERT(false == called); scope.close(); diff --git a/tests/beman/execution/exec-spawn-future.test.cpp b/tests/beman/execution/exec-spawn-future.test.cpp index de6a80a4..17077fc3 100644 --- a/tests/beman/execution/exec-spawn-future.test.cpp +++ b/tests/beman/execution/exec-spawn-future.test.cpp @@ -274,7 +274,7 @@ auto test_get_allocator() { test_std::inplace_stop_source source; auto [alloc, ev] = test_detail::spawn_get_allocator( alloc_sender{53}, - test_detail::join_env(test_std::prop(test_std::get_allocator, allocator(101)), + test_detail::join_env(test_std::prop(test_std::get_allocator, allocator{101}), test_std::prop(test_std::get_stop_token, source.get_token()))); static_assert(std::same_as); ASSERT(alloc == allocator{101});