From 98b3fef657ce8d487e42c9cf322d57590547dfec Mon Sep 17 00:00:00 2001 From: Cra3z Date: Thu, 28 May 2026 13:53:21 +0800 Subject: [PATCH 1/4] Implement `P3941 - Scheduler Affinity` and `P4151 - Rename affine_on` --- docs/overview.md | 6 +- .../detail/{affine_on.hpp => affine.hpp} | 134 ++++++++++-------- .../beman/execution/detail/as_awaitable.hpp | 87 ++++++++---- .../beman/execution/detail/basic_sender.hpp | 6 + .../execution/detail/counting_scope_join.hpp | 13 +- .../execution/detail/get_start_scheduler.hpp | 35 +++++ .../execution/detail/infallible_scheduler.hpp | 69 +++++++++ include/beman/execution/detail/just.hpp | 3 +- ...ne_on.hpp => nested_sender_has_affine.hpp} | 18 +-- include/beman/execution/detail/on.hpp | 13 +- include/beman/execution/detail/read_env.hpp | 2 +- include/beman/execution/detail/sched_env.hpp | 11 +- .../detail/sender_adaptor_closure.hpp | 11 +- .../execution/detail/sender_has_affine.hpp | 31 ++++ .../execution/detail/sender_has_affine_on.hpp | 33 ----- include/beman/execution/detail/spawn.hpp | 8 +- include/beman/execution/detail/sync_wait.hpp | 3 + include/beman/execution/detail/then.hpp | 10 +- include/beman/execution/detail/write_env.hpp | 10 +- include/beman/execution/execution.hpp | 6 +- src/beman/execution/CMakeLists.txt | 16 ++- src/beman/execution/affine.cppm | 12 ++ src/beman/execution/affine_on.cppm | 12 -- src/beman/execution/execution.cppm | 9 +- src/beman/execution/get_start_scheduler.cppm | 12 ++ src/beman/execution/infallible_scheduler.cppm | 12 ++ .../execution/nested_sender_has_affine.cppm | 11 ++ .../nested_sender_has_affine_on.cppm | 11 -- src/beman/execution/sender_has_affine.cppm | 11 ++ src/beman/execution/sender_has_affine_on.cppm | 11 -- tests/beman/execution/CMakeLists.txt | 2 +- ...ffine-on.test.cpp => exec-affine.test.cpp} | 61 ++++---- .../execution/exec-scope-counting.test.cpp | 3 +- .../exec-scope-simple-counting.test.cpp | 3 +- tests/beman/execution/exec-snd-expos.test.cpp | 2 +- tests/beman/execution/execution-syn.test.cpp | 54 +++++++ 36 files changed, 504 insertions(+), 247 deletions(-) rename include/beman/execution/detail/{affine_on.hpp => affine.hpp} (55%) create mode 100644 include/beman/execution/detail/get_start_scheduler.hpp create mode 100644 include/beman/execution/detail/infallible_scheduler.hpp rename include/beman/execution/detail/{nested_sender_has_affine_on.hpp => nested_sender_has_affine.hpp} (64%) create mode 100644 include/beman/execution/detail/sender_has_affine.hpp delete mode 100644 include/beman/execution/detail/sender_has_affine_on.hpp create mode 100644 src/beman/execution/affine.cppm delete mode 100644 src/beman/execution/affine_on.cppm create mode 100644 src/beman/execution/get_start_scheduler.cppm create mode 100644 src/beman/execution/infallible_scheduler.cppm create mode 100644 src/beman/execution/nested_sender_has_affine.cppm delete mode 100644 src/beman/execution/nested_sender_has_affine_on.cppm create mode 100644 src/beman/execution/sender_has_affine.cppm delete mode 100644 src/beman/execution/sender_has_affine_on.cppm rename tests/beman/execution/{exec-affine-on.test.cpp => exec-affine.test.cpp} (75%) diff --git a/docs/overview.md b/docs/overview.md index 6b093f6b..b6a98020 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -640,11 +640,11 @@ The expression schedule(scheduler) creates a sender which up The sender adaptors take one or more senders and adapt their respective behavior to complete with a corresponding result. The description uses the informal function completions-of(sender) to represent the completion signatures which sender produces. Also, completion signatures are combined using +: the result is the deduplicated set of the combined completion signatures.
-affine_on(sender) -> sender-of<completions-of(sender)> -The expression affine_on(sender) creates +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 primary use of affine_on is implementing scheduler affinity for task. +The primary use of affine is implementing scheduler affinity for task.
`bulk` diff --git a/include/beman/execution/detail/affine_on.hpp b/include/beman/execution/detail/affine.hpp similarity index 55% rename from include/beman/execution/detail/affine_on.hpp rename to include/beman/execution/detail/affine.hpp index b154ab57..8179211f 100644 --- a/include/beman/execution/detail/affine_on.hpp +++ b/include/beman/execution/detail/affine.hpp @@ -1,8 +1,8 @@ -// include/beman/execution/detail/affine_on.hpp -*-C++-*- +// include/beman/execution/detail/affine.hpp -*-C++-*- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#ifndef INCLUDED_BEMAN_EXECUTION_DETAIL_AFFINE_ON -#define INCLUDED_BEMAN_EXECUTION_DETAIL_AFFINE_ON +#ifndef INCLUDED_BEMAN_EXECUTION_DETAIL_AFFINE +#define INCLUDED_BEMAN_EXECUTION_DETAIL_AFFINE #include #include @@ -22,11 +22,12 @@ import beman.execution.detail.env; import beman.execution.detail.forward_like; import beman.execution.detail.fwd_env; import beman.execution.detail.get_completion_signatures; -import beman.execution.detail.get_scheduler; +import beman.execution.detail.get_start_scheduler; import beman.execution.detail.get_stop_token; +import beman.execution.detail.infallible_scheduler; import beman.execution.detail.make_sender; import beman.execution.detail.never_stop_token; -import beman.execution.detail.nested_sender_has_affine_on; +import beman.execution.detail.nested_sender_has_affine; import beman.execution.detail.prop; import beman.execution.detail.schedule; import beman.execution.detail.schedule_from; @@ -34,7 +35,7 @@ import beman.execution.detail.scheduler; import beman.execution.detail.sender; import beman.execution.detail.sender_adaptor_closure; import beman.execution.detail.sender_for; -import beman.execution.detail.sender_has_affine_on; +import beman.execution.detail.sender_has_affine; import beman.execution.detail.set_value; import beman.execution.detail.store_receiver; import beman.execution.detail.tag_of_t; @@ -46,16 +47,18 @@ import beman.execution.detail.write_env; #include #include #include -#include +#include #include +#include #include #include +#include #include #include #include #include #include -#include +#include #include #include #include @@ -66,31 +69,36 @@ import beman.execution.detail.write_env; // ---------------------------------------------------------------------------- namespace beman::execution::detail { -template -struct affine_on_env { - Ev ev_; - auto query(const ::beman::execution::get_stop_token_t&) const noexcept -> ::beman::execution::never_stop_token { - return ::beman::execution::never_stop_token(); +template +struct unstoppable_scheduler { + using scheduler_concept = typename Sched::scheduler_concept; + + template + requires requires { ::std::declval().query(::std::declval(), ::std::declval()...); } + auto query(const Q& q, Args&&... args) const noexcept -> decltype(auto) { + return sched.query(q, ::std::forward(args)...); } - template - auto query(const Q& q) const noexcept -> decltype(q(this->ev_)) { - return q(this->ev_); + + auto schedule() const noexcept(std::is_nothrow_invocable_v<::beman::execution::schedule_t, Sched>) { + return ::beman::execution::unstoppable(::beman::execution::schedule(sched)); } + + friend auto operator==(const unstoppable_scheduler& lhs, const unstoppable_scheduler& rhs) -> bool = default; + + Sched sched; }; -template -affine_on_env(const Ev&) -> affine_on_env; /** - * @brief The affine_on_t struct is a sender adaptor closure that transforms a sender + * @brief The affine_t struct is a sender adaptor closure that transforms a sender * to complete on the scheduler obtained from the receiver's environment. * * This adaptor implements scheduler affinity to adapt a sender to complete on the * scheduler obtained the receiver's environment. The get_scheduler query is used * to obtain the scheduler on which the sender gets started. */ -struct affine_on_t : ::beman::execution::sender_adaptor_closure { +struct affine_t : ::beman::execution::sender_adaptor_closure { /** - * @brief Adapt a sender with affine_on. + * @brief Adapt a sender with affine. * * @tparam Sender The deduced type of the sender to be transformed. * @param sender The sender to be transformed. @@ -103,21 +111,21 @@ struct affine_on_t : ::beman::execution::sender_adaptor_closure { } /** - * @brief Overload for creating a sender adaptor from affine_on. + * @brief Overload for creating a sender adaptor from affine. * - * @return A sender adaptor for the affine_on_t. + * @return A sender adaptor for the affine_t. */ auto operator()() const { return ::beman::execution::detail::make_sender_adaptor(*this); } /** - * @brief affine_on is implemented by transforming it into a use of schedule_from. + * @brief affine is implemented by transforming it into a use of schedule_from. * * The constraints ensure that the environment provides a scheduler which is * infallible and, thus, can be used to guarantee completion on the correct * scheduler. * * The implementation first tries to see if the child sender's tag has a custom - * affine_on implementation. If it does, that is used. Otherwise, the default + * affine implementation. If it does, that is used. Otherwise, the default * implementation gets a scheduler from the environment and uses schedule_from * to adapt the sender to complete on that scheduler. * @@ -127,52 +135,52 @@ struct affine_on_t : ::beman::execution::sender_adaptor_closure { * @param env The environment providing the scheduler. * @return A transformed sender that is affined to the scheduler. */ - template <::beman::execution::sender Sender, typename Env> - requires ::beman::execution::detail::sender_for && requires(const Env& env) { - { ::beman::execution::get_scheduler(env) } -> ::beman::execution::scheduler; - { ::beman::execution::schedule(::beman::execution::get_scheduler(env)) } -> ::beman::execution::sender; - } - static auto transform_sender(::beman::execution::set_value_t, Sender&& sender, const Env& ev) { - static_assert(requires { - { - ::beman::execution::get_completion_signatures() - } //-dk:TODO -> - //::std::same_as<::beman::execution::completion_signatures<::beman::execution::set_value_t()>> - ; - }); - //[[maybe_unused]] auto& [tag, data, child] = sender; - auto& child = sender.template get<2>(); - using child_tag_t = ::beman::execution::tag_of_t<::std::remove_cvref_t>; - - if constexpr (::beman::execution::detail::nested_sender_has_affine_on) { - constexpr child_tag_t t{}; - return t.affine_on(::beman::execution::detail::forward_like(child), ev); + template <::beman::execution::detail::sender_for Sender, typename Env> + static auto transform_sender(::beman::execution::set_value_t, Sender&& sender, const Env& env) { + auto& child = sender.template get<2>(); + if constexpr (::beman::execution::detail::nested_sender_has_affine) { + return ::beman::execution::detail::forward_like(child).affine(); } else { - return ::beman::execution::detail::store_receiver( + static_assert( + requires { + { + ::beman::execution::get_start_scheduler(::std::declval()) + } -> ::beman::execution::detail::infallible_scheduler; + }, + "the result type of querying `get_start_scheduler` on an `Env` shall be a scheduler type whose " + "schedule asynchronous operation can only complete with set_value unless stop can be requested"); + return ::beman::execution::continues_on( ::beman::execution::detail::forward_like(child), - [](Child&& child, const auto& ev) { - return ::beman::execution::unstoppable(::beman::execution::continues_on( - ::beman::execution::write_env(::std::forward(child), ev), - ::beman::execution::get_scheduler(ev))); - }); + ::beman::execution::detail::unstoppable_scheduler{::beman::execution::get_start_scheduler(env)}); } } template struct get_signatures; - template + template + struct get_signatures<::beman::execution::detail::basic_sender<::beman::execution::detail::affine_t, Data, Child>, + Env> { + static consteval auto get() { + if constexpr (!requires { + { + ::beman::execution::get_start_scheduler(::std::declval()) + } -> ::beman::execution::detail::infallible_scheduler; + }) { + throw ::beman::execution::detail::infallible_scheduler_error{}; + } + return ::beman::execution::get_completion_signatures(); + } + }; + + template struct get_signatures< - ::beman::execution::detail::basic_sender<::beman::execution::detail::affine_on_t, Data, Child>, - Env...> { - using type = ::beman::execution::completion_signatures_of_t; + ::beman::execution::detail::basic_sender<::beman::execution::detail::affine_t, Data, Child>> { + static consteval auto get() { return ::beman::execution::get_completion_signatures(); } }; template static consteval auto get_completion_signatures() { - return typename get_signatures<::std::remove_cvref_t, Env...>::type{}; + return get_signatures<::std::remove_cvref_t, Env...>::get(); } }; @@ -180,15 +188,15 @@ struct affine_on_t : ::beman::execution::sender_adaptor_closure { namespace beman::execution { /** - * @brief affine_on is a CPO, used to adapt a sender to complete on the scheduler + * @brief affine is a CPO, used to adapt a sender to complete on the scheduler * it got started on which is derived from get_scheduler on the receiver's environment. */ -using affine_on_t = beman::execution::detail::affine_on_t; -inline constexpr affine_on_t affine_on{}; +using affine_t = beman::execution::detail::affine_t; +inline constexpr beman::execution::detail::affine_t affine{}; } // namespace beman::execution // ---------------------------------------------------------------------------- #include -#endif // INCLUDED_BEMAN_EXECUTION_DETAIL_AFFINE_ON +#endif // INCLUDED_BEMAN_EXECUTION_DETAIL_AFFINE diff --git a/include/beman/execution/detail/as_awaitable.hpp b/include/beman/execution/detail/as_awaitable.hpp index 40470efd..c55571aa 100644 --- a/include/beman/execution/detail/as_awaitable.hpp +++ b/include/beman/execution/detail/as_awaitable.hpp @@ -14,27 +14,68 @@ import std; #include #endif #ifdef BEMAN_HAS_MODULES -import beman.execution.detail.awaitable_sender; +import beman.execution.detail.env_of_t; import beman.execution.detail.get_await_completion_adaptor; +import beman.execution.detail.get_awaiter; import beman.execution.detail.get_env; import beman.execution.detail.query_with_default; import beman.execution.detail.is_awaitable; -import beman.execution.detail.sender; +import beman.execution.detail.is_awaiter; import beman.execution.detail.sender_awaitable; -import beman.execution.detail.unspecified_promise; +import beman.execution.detail.single_sender; +import beman.execution.detail.transform_sender; #else -#include +#include #include +#include #include #include #include -#include +#include #include -#include +#include +#include #endif // ---------------------------------------------------------------------------- +namespace beman::execution::detail { +template +auto adapt_for_await_completion(Sndr&& sndr) { + auto adaptor = ::beman::execution::detail::query_with_default( + ::beman::execution::get_await_completion_adaptor, ::beman::execution::get_env(sndr), ::std::identity{}); + return adaptor(::std::forward(sndr)); +} + +template +auto transform_and_adapt_for_await_completion(Expr&& expr, Promise& promise) { + auto sndr = ::beman::execution::transform_sender(::std::forward(expr), ::beman::execution::get_env(promise)); + return ::beman::execution::detail::adapt_for_await_completion(::std::move(sndr)); +} + +template +using await_completion_sender_t = decltype(::beman::execution::detail::transform_and_adapt_for_await_completion( + ::std::declval(), ::std::declval())); + +template +concept await_completion_sender = + ::beman::execution::detail::single_sender> && + requires { typename ::beman::execution::detail::await_completion_sender_t; }; + +template +concept has_await_completion_as_awaitable = + ::beman::execution::detail::await_completion_sender && requires(Promise& promise) { + ::std::declval<::beman::execution::detail::await_completion_sender_t>().as_awaitable(promise); + }; + +template +concept directly_awaitable = requires { + { + ::beman::execution::detail::get_awaiter(::std::declval()) + } -> ::beman::execution::detail::is_awaiter; +}; +} // namespace beman::execution::detail + namespace beman::execution { /*! * \brief Turn an entity, e.g., a sender, into an awaitable. @@ -49,25 +90,23 @@ struct as_awaitable_t { Promise>, "as_awaitable must return an awaitable"); return ::std::forward(expr).as_awaitable(promise); - } else if constexpr (::beman::execution::sender && - !::beman::execution::detail:: - is_awaitable) { - auto adaptor = - ::beman::execution::detail::query_with_default(::beman::execution::get_await_completion_adaptor, - ::beman::execution::get_env(expr), - ::std::identity{}); - using sender_tag = ::std::invoke_result_t; - if constexpr (::beman::execution::detail::awaitable_sender) { - return ::beman::execution::detail::sender_awaitable{ - adaptor(::std::forward(expr)), promise}; - } else if constexpr (::beman::execution::detail::awaitable_sender) { - return ::beman::execution::detail::sender_awaitable{::std::forward(expr), - promise}; - } else { - return ::std::forward(expr); - } + } else if constexpr (::beman::execution::detail::has_await_completion_as_awaitable) { + using result_t = + decltype(::std::declval<::beman::execution::detail::await_completion_sender_t>() + .as_awaitable(::std::declval())); + static_assert(::beman::execution::detail::is_awaitable, + "as_awaitable must return an awaitable"); + auto sndr = ::beman::execution::detail::transform_and_adapt_for_await_completion( + ::std::forward(expr), promise); + return ::std::move(sndr).as_awaitable(promise); + } else if constexpr (::beman::execution::detail::directly_awaitable) { + return (static_cast(promise), ::std::forward(expr)); + } else if constexpr (::beman::execution::detail::await_completion_sender) { + auto sndr = ::beman::execution::detail::transform_and_adapt_for_await_completion( + ::std::forward(expr), promise); + return ::beman::execution::detail::sender_awaitable{::std::move(sndr), promise}; } else { - return ::std::forward(expr); + return (static_cast(promise), ::std::forward(expr)); } } }; diff --git a/include/beman/execution/detail/basic_sender.hpp b/include/beman/execution/detail/basic_sender.hpp index 028c0b21..a013a89b 100644 --- a/include/beman/execution/detail/basic_sender.hpp +++ b/include/beman/execution/detail/basic_sender.hpp @@ -120,6 +120,12 @@ struct basic_sender : ::beman::execution::detail::product_type{}; } + + template <::beman::execution::detail::decays_to Self> + requires requires { Tag().affine(::std::declval()); } + auto affine(this Self&& self) noexcept(noexcept(Tag().affine(::std::declval()))) -> decltype(auto) { + return Tag().affine(::std::forward(self)); + } }; } // namespace beman::execution::detail diff --git a/include/beman/execution/detail/counting_scope_join.hpp b/include/beman/execution/detail/counting_scope_join.hpp index a7059da3..cd8f9f68 100644 --- a/include/beman/execution/detail/counting_scope_join.hpp +++ b/include/beman/execution/detail/counting_scope_join.hpp @@ -19,7 +19,7 @@ import beman.execution.detail.connect; import beman.execution.detail.counting_scope_base; import beman.execution.detail.default_impls; import beman.execution.detail.get_env; -import beman.execution.detail.get_scheduler; +import beman.execution.detail.get_start_scheduler; import beman.execution.detail.impls_for; import beman.execution.detail.make_sender; import beman.execution.detail.receiver; @@ -35,7 +35,7 @@ import beman.execution.detail.start; #include #include #include -#include +#include #include #include #include @@ -103,15 +103,16 @@ struct beman::execution::detail::counting_scope_join_t::state : ::beman::executi Receiver& rcvr; }; - using op_t = decltype(::beman::execution::connect(::beman::execution::schedule(::beman::execution::get_scheduler( - ::beman::execution::get_env(::std::declval()))), - ::std::declval())); + using op_t = + decltype(::beman::execution::connect(::beman::execution::schedule(::beman::execution::get_start_scheduler( + ::beman::execution::get_env(::std::declval()))), + ::std::declval())); ::beman::execution::detail::counting_scope_base* scope; explicit state(::beman::execution::detail::counting_scope_base* s, Receiver& r) : scope(s), receiver(r), - op(::beman::execution::connect(::beman::execution::schedule(::beman::execution::get_scheduler( + op(::beman::execution::connect(::beman::execution::schedule(::beman::execution::get_start_scheduler( ::beman::execution::get_env(this->receiver))), receiver_ref(this->receiver))) {} virtual ~state() = default; diff --git a/include/beman/execution/detail/get_start_scheduler.hpp b/include/beman/execution/detail/get_start_scheduler.hpp new file mode 100644 index 00000000..d6c71ae9 --- /dev/null +++ b/include/beman/execution/detail/get_start_scheduler.hpp @@ -0,0 +1,35 @@ +// include/beman/execution/detail/get_start_scheduler.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION_DETAIL_GET_START_SCHEDULER +#define INCLUDED_BEMAN_EXECUTION_DETAIL_GET_START_SCHEDULER + +#include +#ifdef BEMAN_HAS_IMPORT_STD +import std; +#else +#include +#endif +#ifdef BEMAN_HAS_MODULES +import beman.execution.detail.forwarding_query; +#else +#include +#endif + +// ---------------------------------------------------------------------------- + +namespace beman::execution { +struct get_start_scheduler_t : ::beman::execution::forwarding_query_t { + template + requires requires(const get_start_scheduler_t& self, const Env& env) { env.query(self); } + auto operator()(Env&& env) const noexcept { + return ::std::as_const(env).query(*this); + } +}; + +inline constexpr get_start_scheduler_t get_start_scheduler{}; +} // namespace beman::execution + +// ---------------------------------------------------------------------------- + +#endif // INCLUDED_BEMAN_EXECUTION_DETAIL_GET_START_SCHEDULER diff --git a/include/beman/execution/detail/infallible_scheduler.hpp b/include/beman/execution/detail/infallible_scheduler.hpp new file mode 100644 index 00000000..2f2a387e --- /dev/null +++ b/include/beman/execution/detail/infallible_scheduler.hpp @@ -0,0 +1,69 @@ +// include/beman/execution/detail/infallible_scheduler.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION_DETAIL_INFALLIBLE_SCHEDULER +#define INCLUDED_BEMAN_EXECUTION_DETAIL_INFALLIBLE_SCHEDULER + +#include + +#ifdef BEMAN_HAS_IMPORT_STD +import std; +#else +#include +#include +#endif +#ifdef BEMAN_HAS_MODULES +import beman.execution.detail.completion_signatures; +import beman.execution.detail.completion_signatures_of_t; +import beman.execution.detail.scheduler; +import beman.execution.detail.schedule_result_t; +import beman.execution.detail.set_stopped; +import beman.execution.detail.set_value; +import beman.execution.detail.stop_token_of_t; +import beman.execution.detail.unstoppable_token; +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +// ---------------------------------------------------------------------------- + +namespace beman::execution::detail { + +template +struct infallible_scheduler_error : ::std::exception { + auto what() const noexcept -> const char* override { + using _ [[maybe_unused]] = Env; + return "the result type of querying `get_start_scheduler` on an `Env` shall be a scheduler type whose " + "schedule " + "asynchronous operation can only complete with set_value unless stop can be requested"; + } +}; + +template +concept infallible_scheduler = + ::beman::execution::scheduler && + (::std::same_as< + ::beman::execution::completion_signatures<::beman::execution::set_value_t()>, + ::beman::execution::completion_signatures_of_t<::beman::execution::schedule_result_t, Env>> || + (!::beman::execution::unstoppable_token<::beman::execution::stop_token_of_t> && + (::std::same_as< + ::beman::execution::completion_signatures<::beman::execution::set_value_t(), + ::beman::execution::set_stopped_t()>, + ::beman::execution::completion_signatures_of_t<::beman::execution::schedule_result_t, Env>> || + ::std::same_as< + ::beman::execution::completion_signatures<::beman::execution::set_stopped_t(), + ::beman::execution::set_value_t()>, + ::beman::execution::completion_signatures_of_t<::beman::execution::schedule_result_t, Env>>))); + +} // namespace beman::execution::detail + +// ---------------------------------------------------------------------------- + +#endif // INCLUDED_BEMAN_EXECUTION_DETAIL_INFALLIBLE_SCHEDULER diff --git a/include/beman/execution/detail/just.hpp b/include/beman/execution/detail/just.hpp index 3a734e5a..b1fb576c 100644 --- a/include/beman/execution/detail/just.hpp +++ b/include/beman/execution/detail/just.hpp @@ -56,8 +56,9 @@ struct just_t { return ::beman::execution::detail::make_sender( *this, ::beman::execution::detail::product_type{::std::forward(arg)...}); } + template <::beman::execution::sender Sender> - static auto affine_on(Sender&& sndr, const auto&) noexcept { + static auto affine(Sender&& sndr) noexcept { return ::std::forward(sndr); } diff --git a/include/beman/execution/detail/nested_sender_has_affine_on.hpp b/include/beman/execution/detail/nested_sender_has_affine.hpp similarity index 64% rename from include/beman/execution/detail/nested_sender_has_affine_on.hpp rename to include/beman/execution/detail/nested_sender_has_affine.hpp index 6a9c123d..22abe955 100644 --- a/include/beman/execution/detail/nested_sender_has_affine_on.hpp +++ b/include/beman/execution/detail/nested_sender_has_affine.hpp @@ -1,25 +1,25 @@ -// include/beman/execution/detail/nested_sender_has_affine_on.hpp -*-C++-*- +// include/beman/execution/detail/nested_sender_has_affine.hpp -*-C++-*- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#ifndef INCLUDED_BEMAN_EXECUTION_DETAIL_NESTED_SENDER_HAS_AFFINE_ON -#define INCLUDED_BEMAN_EXECUTION_DETAIL_NESTED_SENDER_HAS_AFFINE_ON +#ifndef INCLUDED_BEMAN_EXECUTION_DETAIL_NESTED_SENDER_HAS_AFFINE +#define INCLUDED_BEMAN_EXECUTION_DETAIL_NESTED_SENDER_HAS_AFFINE #include #ifdef BEMAN_HAS_MODULES -import beman.execution.detail.sender_has_affine_on; +import beman.execution.detail.sender_has_affine; #else -#include +#include #endif // ---------------------------------------------------------------------------- namespace beman::execution::detail { -template -concept nested_sender_has_affine_on = requires(Sender&& sndr, const Env& env) { - { sndr.template get<2>() } -> ::beman::execution::detail::sender_has_affine_on; +template +concept nested_sender_has_affine = requires(Sender&& sndr) { + { sndr.template get<2>() } -> ::beman::execution::detail::sender_has_affine; }; } // namespace beman::execution::detail // ---------------------------------------------------------------------------- -#endif // INCLUDED_BEMAN_EXECUTION_DETAIL_NESTED_SENDER_HAS_AFFINE_ON +#endif // INCLUDED_BEMAN_EXECUTION_DETAIL_NESTED_SENDER_HAS_AFFINE diff --git a/include/beman/execution/detail/on.hpp b/include/beman/execution/detail/on.hpp index ee919772..d737eb75 100644 --- a/include/beman/execution/detail/on.hpp +++ b/include/beman/execution/detail/on.hpp @@ -20,7 +20,7 @@ import beman.execution.detail.fwd_env; import beman.execution.detail.get_completion_scheduler; import beman.execution.detail.get_domain; import beman.execution.detail.get_env; -import beman.execution.detail.get_scheduler; +import beman.execution.detail.get_start_scheduler; import beman.execution.detail.join_env; import beman.execution.detail.make_sender; import beman.execution.detail.product_type; @@ -39,6 +39,7 @@ import beman.execution.detail.transform_sender; #include #include #include +#include #include #include #include @@ -57,11 +58,11 @@ import beman.execution.detail.transform_sender; namespace beman::execution::detail { struct on_t : ::beman::execution::sender_adaptor_closure { template - struct env_needs_get_scheduler { + struct env_needs_get_start_scheduler { using sender_concept = ::beman::execution::sender_tag; template static constexpr auto get_completion_signatures() { - return env_needs_get_scheduler{}; + return env_needs_get_start_scheduler{}; } }; @@ -74,9 +75,9 @@ struct on_t : ::beman::execution::sender_adaptor_closure { if constexpr (::beman::execution::scheduler) { auto sch{::beman::execution::detail::query_with_default( - ::beman::execution::get_scheduler, env, not_a_scheduler_t{})}; + ::beman::execution::get_start_scheduler, env, not_a_scheduler_t{})}; if constexpr (::std::same_as) { - return env_needs_get_scheduler{}; + return env_needs_get_start_scheduler{}; } else { return ::beman::execution::continues_on( ::beman::execution::starts_on(::beman::execution::detail::forward_like(data), @@ -92,7 +93,7 @@ struct on_t : ::beman::execution::sender_adaptor_closure { env)}; if constexpr (::std::same_as) { - return env_needs_get_scheduler{}; + return env_needs_get_start_scheduler{}; } else { return ::beman::execution::continues_on( ::beman::execution::detail::forward_like(closure)(::beman::execution::continues_on( diff --git a/include/beman/execution/detail/read_env.hpp b/include/beman/execution/detail/read_env.hpp index 5ab59ed8..67fe95b1 100644 --- a/include/beman/execution/detail/read_env.hpp +++ b/include/beman/execution/detail/read_env.hpp @@ -42,7 +42,7 @@ namespace beman::execution::detail { struct read_env_t { auto operator()(auto&& query) const { return ::beman::execution::detail::make_sender(*this, query); } template <::beman::execution::sender Sender> - static auto affine_on(Sender&& sndr, const auto&) noexcept { + static auto affine(Sender&& sndr) noexcept { return ::std::forward(sndr); } diff --git a/include/beman/execution/detail/sched_env.hpp b/include/beman/execution/detail/sched_env.hpp index 1a3d698d..2631119d 100644 --- a/include/beman/execution/detail/sched_env.hpp +++ b/include/beman/execution/detail/sched_env.hpp @@ -14,11 +14,11 @@ import std; #ifdef BEMAN_HAS_MODULES import beman.execution.detail.default_domain; import beman.execution.detail.get_domain; -import beman.execution.detail.get_scheduler; +import beman.execution.detail.get_start_scheduler; #else #include #include -#include +#include #endif // ---------------------------------------------------------------------------- @@ -31,10 +31,11 @@ class sched_env { public: template - explicit sched_env(S sch) : sched(::std::move(sch)) {} + explicit sched_env(S sch) noexcept(std::is_nothrow_constructible_v) : sched(::std::move(sch)) {} - auto query(const ::beman::execution::get_scheduler_t&) const noexcept { return this->sched; } - auto query(const ::beman::execution::get_domain_t& q) const noexcept { + auto query(::beman::execution::get_start_scheduler_t) const noexcept { return this->sched; } + + auto query(::beman::execution::get_domain_t q) const noexcept { if constexpr (requires { this->sched.query(q); }) return this->sched.query(q); else diff --git a/include/beman/execution/detail/sender_adaptor_closure.hpp b/include/beman/execution/detail/sender_adaptor_closure.hpp index 457fea64..bc6755a6 100644 --- a/include/beman/execution/detail/sender_adaptor_closure.hpp +++ b/include/beman/execution/detail/sender_adaptor_closure.hpp @@ -17,6 +17,7 @@ import beman.execution.detail.sender; import beman.execution.detail.call_result_t; import beman.execution.detail.callable; import beman.execution.detail.class_type; +import beman.execution.detail.forward_like; import beman.execution.detail.nothrow_callable; import beman.execution.detail.movable_value; import beman.execution.detail.product_type; @@ -26,6 +27,7 @@ import beman.execution.detail.product_type; #include #include #include +#include #include #include #include @@ -100,7 +102,7 @@ concept sender_adaptor_closure_for = * \internal */ template -using apply_cvref_t = decltype(std::forward_like(std::declval())); +using apply_cvref_t = decltype(::beman::execution::detail::forward_like(std::declval())); /*! * \brief Perfect forwarding call wrapper produced by closure-closure composition via operator|. @@ -119,7 +121,8 @@ struct composed_sender_adaptor_closure : sender_adaptor_closure, Sender> and nothrow_callable, call_result_t, Sender>>) -> call_result_t, call_result_t, Sender>> { - return std::forward_like(self.outer)(std::forward_like(self.inner)(std::forward(sndr))); + return ::beman::execution::detail::forward_like(self.outer)( + ::beman::execution::detail::forward_like(self.inner)(std::forward(sndr))); } }; @@ -145,8 +148,8 @@ struct bound_sender_adaptor_closure : detail::product_type, Sender, apply_cvref_t...>) -> call_result_t, Sender, apply_cvref_t...> { return self.apply([&](auto&&... bound_args) { - return std::forward_like(self.adaptor)(std::forward(sndr), - std::forward_like(bound_args)...); + return ::beman::execution::detail::forward_like(self.adaptor)( + std::forward(sndr), ::beman::execution::detail::forward_like(bound_args)...); }); } }; diff --git a/include/beman/execution/detail/sender_has_affine.hpp b/include/beman/execution/detail/sender_has_affine.hpp new file mode 100644 index 00000000..f8968a49 --- /dev/null +++ b/include/beman/execution/detail/sender_has_affine.hpp @@ -0,0 +1,31 @@ +// include/beman/execution/detail/sender_has_affine.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION_DETAIL_SENDER_HAS_AFFINE +#define INCLUDED_BEMAN_EXECUTION_DETAIL_SENDER_HAS_AFFINE + +#include +#ifdef BEMAN_HAS_IMPORT_STD +import std; +#else +#include +#include +#endif +#ifdef BEMAN_HAS_MODULES +import beman.execution.detail.sender; +#else +#include +#endif + +// ---------------------------------------------------------------------------- + +namespace beman::execution::detail { +template +concept sender_has_affine = beman::execution::sender<::std::remove_cvref_t> && requires(Sender&& sndr) { + { ::std::forward(sndr).affine() } -> ::beman::execution::sender; +}; +} // namespace beman::execution::detail + +// ---------------------------------------------------------------------------- + +#endif // INCLUDED_BEMAN_EXECUTION_DETAIL_SENDER_HAS_AFFINE diff --git a/include/beman/execution/detail/sender_has_affine_on.hpp b/include/beman/execution/detail/sender_has_affine_on.hpp deleted file mode 100644 index 08d1d8df..00000000 --- a/include/beman/execution/detail/sender_has_affine_on.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// include/beman/execution/detail/sender_has_affine_on.hpp -*-C++-*- -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#ifndef INCLUDED_BEMAN_EXECUTION_DETAIL_SENDER_HAS_AFFINE_ON -#define INCLUDED_BEMAN_EXECUTION_DETAIL_SENDER_HAS_AFFINE_ON - -#include -#ifdef BEMAN_HAS_IMPORT_STD -import std; -#else -#include -#include -#endif -#ifdef BEMAN_HAS_MODULES -import beman.execution.detail.sender; -#else -#include -#endif - -// ---------------------------------------------------------------------------- - -namespace beman::execution::detail { -template -concept sender_has_affine_on = - beman::execution::sender<::std::remove_cvref_t> && requires(Sender&& sndr, const Env& env) { - sndr.template get<0>(); - { sndr.template get<0>().affine_on(std::forward(sndr), env) } -> ::beman::execution::sender; - }; -} // namespace beman::execution::detail - -// ---------------------------------------------------------------------------- - -#endif // INCLUDED_BEMAN_EXECUTION_DETAIL_SENDER_HAS_AFFINE_ON diff --git a/include/beman/execution/detail/spawn.hpp b/include/beman/execution/detail/spawn.hpp index 81be6a10..b6ee4913 100644 --- a/include/beman/execution/detail/spawn.hpp +++ b/include/beman/execution/detail/spawn.hpp @@ -87,10 +87,10 @@ struct spawn_t { auto new_sender{tok.wrap(::std::forward(sender))}; auto [all, senv] = ::beman::execution::detail::spawn_get_allocator(new_sender, env); - using sender_tag = decltype(::beman::execution::write_env(::std::move(new_sender), senv)); - using state_t = state; - using alloc_t = typename ::std::allocator_traits::template rebind_alloc; - using traits_t = ::std::allocator_traits; + using sender_t = decltype(::beman::execution::write_env(::std::move(new_sender), senv)); + using state_t = state; + using alloc_t = typename ::std::allocator_traits::template rebind_alloc; + using traits_t = ::std::allocator_traits; alloc_t alloc(all); state_t* op{traits_t::allocate(alloc, 1u)}; traits_t::construct(alloc, op, all, ::beman::execution::write_env(::std::move(new_sender), senv), tok); diff --git a/include/beman/execution/detail/sync_wait.hpp b/include/beman/execution/detail/sync_wait.hpp index 2ba75e2d..4643aadb 100644 --- a/include/beman/execution/detail/sync_wait.hpp +++ b/include/beman/execution/detail/sync_wait.hpp @@ -22,6 +22,7 @@ import beman.execution.detail.decayed_tuple; import beman.execution.detail.default_domain; import beman.execution.detail.get_delegation_scheduler; import beman.execution.detail.get_scheduler; +import beman.execution.detail.get_start_scheduler; import beman.execution.detail.receiver; import beman.execution.detail.run_loop; import beman.execution.detail.sender_in; @@ -37,6 +38,7 @@ import beman.execution.detail.value_types_of_t; #include #include #include +#include #include #include #include @@ -52,6 +54,7 @@ struct sync_wait_env { // dk:TODO detail export ::beman::execution::run_loop* loop{}; auto query(::beman::execution::get_scheduler_t) const noexcept { return this->loop->get_scheduler(); } + auto query(::beman::execution::get_start_scheduler_t) const noexcept { return loop->get_scheduler(); } auto query(::beman::execution::get_delegation_scheduler_t) const noexcept { return this->loop->get_scheduler(); } }; diff --git a/include/beman/execution/detail/then.hpp b/include/beman/execution/detail/then.hpp index 7c6b672b..c59594c4 100644 --- a/include/beman/execution/detail/then.hpp +++ b/include/beman/execution/detail/then.hpp @@ -30,7 +30,7 @@ import beman.execution.detail.meta.combine; import beman.execution.detail.meta.transform; import beman.execution.detail.meta.unique; import beman.execution.detail.movable_value; -import beman.execution.detail.nested_sender_has_affine_on; +import beman.execution.detail.nested_sender_has_affine; import beman.execution.detail.sender; import beman.execution.detail.sender_adaptor_closure; import beman.execution.detail.set_error; @@ -52,7 +52,7 @@ import beman.execution.detail.transform_sender; #include #include #include -#include +#include #include #include #include @@ -120,9 +120,9 @@ struct then_t : ::beman::execution::sender_adaptor_closure> { return ::beman::execution::detail::make_sender( *this, ::std::forward(fun), ::std::forward(sender)); } - template <::beman::execution::sender Sender, typename Env> - requires ::beman::execution::detail::nested_sender_has_affine_on - static auto affine_on(Sender&& sndr, const Env&) noexcept { + template <::beman::execution::sender Sender> + requires ::beman::execution::detail::nested_sender_has_affine + static auto affine(Sender&& sndr) noexcept { return ::std::forward(sndr); } diff --git a/include/beman/execution/detail/write_env.hpp b/include/beman/execution/detail/write_env.hpp index 70c3ebb5..2d62a385 100644 --- a/include/beman/execution/detail/write_env.hpp +++ b/include/beman/execution/detail/write_env.hpp @@ -21,7 +21,7 @@ import beman.execution.detail.get_completion_signatures; import beman.execution.detail.impls_for; import beman.execution.detail.join_env; import beman.execution.detail.make_sender; -import beman.execution.detail.nested_sender_has_affine_on; +import beman.execution.detail.nested_sender_has_affine; import beman.execution.detail.queryable; import beman.execution.detail.sender; #else @@ -30,7 +30,7 @@ import beman.execution.detail.sender; #include #include #include -#include +#include #include #include #endif @@ -53,9 +53,9 @@ struct write_env_t { return ::beman::execution::detail::make_sender( *this, ::std::forward(env), ::std::forward(sender)); } - template <::beman::execution::sender Sender, typename Env> - requires ::beman::execution::detail::nested_sender_has_affine_on - static auto affine_on(Sender&& sndr, const Env&) noexcept { + template <::beman::execution::sender Sender> + requires ::beman::execution::detail::nested_sender_has_affine + static auto affine(Sender&& sndr) noexcept { return ::std::forward(sndr); } diff --git a/include/beman/execution/execution.hpp b/include/beman/execution/execution.hpp index b0c6f02a..70a5f5c5 100644 --- a/include/beman/execution/execution.hpp +++ b/include/beman/execution/execution.hpp @@ -8,7 +8,7 @@ #include #ifdef BEMAN_HAS_MODULES -import beman.execution.detail.affine_on; +import beman.execution.detail.affine; import beman.execution.detail.as_except_ptr; import beman.execution.detail.associate; import beman.execution.detail.bulk; @@ -32,6 +32,7 @@ import beman.execution.detail.get_domain; import beman.execution.detail.get_forward_progress_guarantee; import beman.execution.detail.get_env; import beman.execution.detail.get_scheduler; +import beman.execution.detail.get_start_scheduler; import beman.execution.detail.get_stop_token; import beman.execution.detail.indeterminate_domain; import beman.execution.detail.inline_scheduler; @@ -73,7 +74,7 @@ import beman.execution.detail.when_all; import beman.execution.detail.with_awaitable_senders; import beman.execution.detail.write_env; #else -#include +#include #include #include #include @@ -96,6 +97,7 @@ import beman.execution.detail.write_env; #include #include #include +#include #include #include #include diff --git a/src/beman/execution/CMakeLists.txt b/src/beman/execution/CMakeLists.txt index e242b4d9..c63cfe87 100644 --- a/src/beman/execution/CMakeLists.txt +++ b/src/beman/execution/CMakeLists.txt @@ -23,7 +23,7 @@ target_sources( TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR}/include FILES - ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/affine_on.hpp + ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/affine.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/allocator_aware_move.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/allocator_of.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/almost_scheduler.hpp @@ -97,6 +97,7 @@ target_sources( ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_env.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_forward_progress_guarantee.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_scheduler.hpp + ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_start_scheduler.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_stop_token.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/handle.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/has_as_awaitable.hpp @@ -107,6 +108,7 @@ target_sources( ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/indeterminate_domain.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/indices_for.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/indirect_meta_apply.hpp + ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/infallible_scheduler.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/inline_attrs.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/inline_scheduler.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/inplace_stop_source.hpp @@ -132,7 +134,7 @@ target_sources( ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/meta_transform.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/meta_unique.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/movable_value.hpp - ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/nested_sender_has_affine_on.hpp + ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/nested_sender_has_affine.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/never_stop_token.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/non_assignable.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/nostopstate.hpp @@ -166,7 +168,7 @@ target_sources( ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sender_awaitable.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sender_decompose.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sender_for.hpp - ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sender_has_affine_on.hpp + ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sender_has_affine.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sender_in.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sender_to.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sends_stopped.hpp @@ -231,7 +233,7 @@ if(BEMAN_USE_MODULES) FILES execution.cppm execution-detail.cppm - affine_on.cppm + affine.cppm allocator_aware_move.cppm almost_scheduler.cppm apply_sender.cppm @@ -301,6 +303,7 @@ if(BEMAN_USE_MODULES) get_env.cppm get_forward_progress_guarantee.cppm get_scheduler.cppm + get_start_scheduler.cppm get_stop_token.cppm has_as_awaitable.cppm has_completions.cppm @@ -310,6 +313,7 @@ if(BEMAN_USE_MODULES) indeterminate_domain.cppm indices_for.cppm indirect_meta_apply.cppm + infallible_scheduler.cppm inline_attrs.cppm inline_scheduler.cppm inplace_stop_source.cppm @@ -335,7 +339,7 @@ if(BEMAN_USE_MODULES) meta_transform.cppm meta_unique.cppm movable_value.cppm - nested_sender_has_affine_on.cppm + nested_sender_has_affine.cppm never_stop_token.cppm notify.cppm non_assignable.cppm @@ -366,7 +370,7 @@ if(BEMAN_USE_MODULES) sender_awaitable.cppm sender_decompose.cppm sender_for.cppm - sender_has_affine_on.cppm + sender_has_affine.cppm sender_in.cppm sender.cppm sender_to.cppm diff --git a/src/beman/execution/affine.cppm b/src/beman/execution/affine.cppm new file mode 100644 index 00000000..cf2046de --- /dev/null +++ b/src/beman/execution/affine.cppm @@ -0,0 +1,12 @@ +module; +// src/beman/execution/affine.cppm -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +export module beman.execution.detail.affine; + +namespace beman::execution { +export using beman::execution::affine_t; +export using beman::execution::affine; +} // namespace beman::execution diff --git a/src/beman/execution/affine_on.cppm b/src/beman/execution/affine_on.cppm deleted file mode 100644 index 113bcbbb..00000000 --- a/src/beman/execution/affine_on.cppm +++ /dev/null @@ -1,12 +0,0 @@ -module; -// src/beman/execution/affine_on.cppm -*-C++-*- -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#include - -export module beman.execution.detail.affine_on; - -namespace beman::execution { -export using beman::execution::affine_on_t; -export using beman::execution::affine_on; -} // namespace beman::execution diff --git a/src/beman/execution/execution.cppm b/src/beman/execution/execution.cppm index 7504a205..9d0c91d7 100644 --- a/src/beman/execution/execution.cppm +++ b/src/beman/execution/execution.cppm @@ -7,7 +7,7 @@ module; export module beman.execution; -import beman.execution.detail.affine_on; +import beman.execution.detail.affine; import beman.execution.detail.apply_sender; import beman.execution.detail.as_awaitable; export import beman.execution.detail.associate; // [exec.associate] @@ -36,6 +36,7 @@ import beman.execution.detail.get_domain; import beman.execution.detail.get_env; import beman.execution.detail.get_forward_progress_guarantee; import beman.execution.detail.get_scheduler; +import beman.execution.detail.get_start_scheduler; import beman.execution.detail.get_stop_token; export import beman.execution.detail.inplace_stop_source; // [stopsource.inplace], class inplace_stop_source import beman.execution.detail.into_variant; @@ -137,12 +138,14 @@ export using ::beman::execution::stop_token_of_t; export using ::beman::execution::get_domain_t; export using ::beman::execution::get_scheduler_t; +export using ::beman::execution::get_start_scheduler_t; export using ::beman::execution::get_delegation_scheduler_t; export using ::beman::execution::get_await_completion_adaptor_t; export using ::beman::execution::get_forward_progress_guarantee_t; export using ::beman::execution::get_domain; export using ::beman::execution::get_scheduler; +export using ::beman::execution::get_start_scheduler; export using ::beman::execution::get_delegation_scheduler; export using ::beman::execution::get_await_completion_adaptor; export using ::beman::execution::forward_progress_guarantee; @@ -254,8 +257,8 @@ export using ::beman::execution::as_awaitable; export using ::beman::execution::prop; export using ::beman::execution::write_env_t; export using ::beman::execution::write_env; -export using ::beman::execution::affine_on_t; -export using ::beman::execution::affine_on; +export using ::beman::execution::affine_t; +export using ::beman::execution::affine; export using ::beman::execution::read_env_t; export using ::beman::execution::read_env; export using ::beman::execution::simple_counting_scope; diff --git a/src/beman/execution/get_start_scheduler.cppm b/src/beman/execution/get_start_scheduler.cppm new file mode 100644 index 00000000..9d9af148 --- /dev/null +++ b/src/beman/execution/get_start_scheduler.cppm @@ -0,0 +1,12 @@ +module; +// src/beman/execution/get_start_scheduler.cppm -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +export module beman.execution.detail.get_start_scheduler; + +namespace beman::execution { +export using beman::execution::get_start_scheduler_t; +export using beman::execution::get_start_scheduler; +} // namespace beman::execution diff --git a/src/beman/execution/infallible_scheduler.cppm b/src/beman/execution/infallible_scheduler.cppm new file mode 100644 index 00000000..b5f0f93e --- /dev/null +++ b/src/beman/execution/infallible_scheduler.cppm @@ -0,0 +1,12 @@ +module; +// src/beman/execution/infallible_scheduler.cppm -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +export module beman.execution.detail.infallible_scheduler; + +namespace beman::execution::detail { +export using beman::execution::detail::infallible_scheduler; +export using beman::execution::detail::infallible_scheduler_error; +} // namespace beman::execution::detail diff --git a/src/beman/execution/nested_sender_has_affine.cppm b/src/beman/execution/nested_sender_has_affine.cppm new file mode 100644 index 00000000..8eecfb26 --- /dev/null +++ b/src/beman/execution/nested_sender_has_affine.cppm @@ -0,0 +1,11 @@ +module; +// src/beman/execution/nested_sender_has_affine.cppm -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +export module beman.execution.detail.nested_sender_has_affine; + +namespace beman::execution::detail { +export using beman::execution::detail::nested_sender_has_affine; +} // namespace beman::execution::detail diff --git a/src/beman/execution/nested_sender_has_affine_on.cppm b/src/beman/execution/nested_sender_has_affine_on.cppm deleted file mode 100644 index 5a71bf2f..00000000 --- a/src/beman/execution/nested_sender_has_affine_on.cppm +++ /dev/null @@ -1,11 +0,0 @@ -module; -// src/beman/execution/nested_sender_has_affine_on.cppm -*-C++-*- -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#include - -export module beman.execution.detail.nested_sender_has_affine_on; - -namespace beman::execution::detail { -export using beman::execution::detail::nested_sender_has_affine_on; -} // namespace beman::execution::detail diff --git a/src/beman/execution/sender_has_affine.cppm b/src/beman/execution/sender_has_affine.cppm new file mode 100644 index 00000000..38b427d6 --- /dev/null +++ b/src/beman/execution/sender_has_affine.cppm @@ -0,0 +1,11 @@ +module; +// src/beman/execution/sender_has_affine.cppm -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +export module beman.execution.detail.sender_has_affine; + +namespace beman::execution::detail { +export using beman::execution::detail::sender_has_affine; +} // namespace beman::execution::detail diff --git a/src/beman/execution/sender_has_affine_on.cppm b/src/beman/execution/sender_has_affine_on.cppm deleted file mode 100644 index 8d8b68b1..00000000 --- a/src/beman/execution/sender_has_affine_on.cppm +++ /dev/null @@ -1,11 +0,0 @@ -module; -// src/beman/execution/sender_has_affine_on.cppm -*-C++-*- -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#include - -export module beman.execution.detail.sender_has_affine_on; - -namespace beman::execution::detail { -export using beman::execution::detail::sender_has_affine_on; -} // namespace beman::execution::detail diff --git a/tests/beman/execution/CMakeLists.txt b/tests/beman/execution/CMakeLists.txt index 0dd5cb4f..9df9a708 100644 --- a/tests/beman/execution/CMakeLists.txt +++ b/tests/beman/execution/CMakeLists.txt @@ -10,7 +10,7 @@ list(APPEND unsupported_execution_tests exec-split.test) list( APPEND execution_tests allocator-requirements-general.test - exec-affine-on.test + exec-affine.test exec-associate.test exec-awaitable.test exec-bulk.test diff --git a/tests/beman/execution/exec-affine-on.test.cpp b/tests/beman/execution/exec-affine.test.cpp similarity index 75% rename from tests/beman/execution/exec-affine-on.test.cpp rename to tests/beman/execution/exec-affine.test.cpp index 46cde579..419e4ede 100644 --- a/tests/beman/execution/exec-affine-on.test.cpp +++ b/tests/beman/execution/exec-affine.test.cpp @@ -1,4 +1,4 @@ -// tests/beman/execution/exec-affine-on.test.cpp -*-C++-*- +// tests/beman/execution/exec-affine.test.cpp -*-C++-*- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include @@ -9,11 +9,12 @@ #ifdef BEMAN_HAS_MODULES import beman.execution; #else -#include +#include #include #include #include #include +#include #include #include #include @@ -56,7 +57,9 @@ struct receiver { auto set_error(auto&&) && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); } auto set_stopped() && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); } - auto get_env() const noexcept { return test_std::env{test_std::prop(test_std::get_scheduler, this->scheduler_)}; } + auto get_env() const noexcept { + return test_std::env{test_std::prop(test_std::get_start_scheduler, this->scheduler_)}; + } }; template receiver(Sched, awaiter* = nullptr) -> receiver; @@ -113,7 +116,7 @@ auto test_order_of_connect() -> void { test_scheduler::data data{}; test_scheduler sched{&data}; - auto sndr{test_std::affine_on(test_std::starts_on(inner_sched, test_std::just(42)))}; + auto sndr{test_std::affine(test_std::starts_on(inner_sched, test_std::just(42)))}; assert(data.connected_ == 0); assert(data.started_ == 0); @@ -132,10 +135,10 @@ auto test_order_of_connect() -> void { } template -auto test_affine_on_specializations(Sender&& sender, std::size_t count = 0u) -> void { +auto test_affine_specializations(Sender&& sender, std::size_t count = 0u) -> void { test_scheduler::data data{}; test_scheduler sched{&data}; - auto sndr{test_std::affine_on(std::forward(sender))}; + auto sndr{test_std::affine(std::forward(sender))}; awaiter aw{}; assert(data.connected_ == 0); @@ -151,53 +154,53 @@ auto test_affine_on_specializations(Sender&& sender, std::size_t count = 0u) -> } } // namespace -TEST(affine_on) { - static_assert(test_std::sender); - static_assert(test_std::sender); +TEST(affine) { + static_assert(test_std::sender); + static_assert(test_std::sender); - static_assert(test_std::sender_in>); + static_assert(test_std::sender_in>); test_std::run_loop loop; auto r{receiver(loop.get_scheduler())}; static_assert(test_std::receiver); - auto s{test_std::get_scheduler(test_std::get_env(r))}; + auto s{test_std::get_start_scheduler(test_std::get_env(r))}; assert(s == loop.get_scheduler()); - auto st{test_std::transform_sender(test_std::affine_on(test_std::just(42)), test_std::get_env(r))}; + auto st{test_std::transform_sender(test_std::affine(test_std::just(42)), test_std::get_env(r))}; test_std::connect(std::move(st), std::move(r)); - auto s0{test_std::connect(test_std::affine_on(test_std::just(42)), receiver(loop.get_scheduler()))}; + auto s0{test_std::connect(test_std::affine(test_std::just(42)), receiver(loop.get_scheduler()))}; std::thread t{[&]() noexcept { loop.run(); }}; - auto r0 = test_std::sync_wait(test_std::affine_on(test_std::just(42))); + auto r0 = test_std::sync_wait(test_std::affine(test_std::just(42))); assert(r0); auto [v0] = *r0; assert(v0 == 42); - auto r1 = test_std::sync_wait(test_std::starts_on(loop.get_scheduler(), test_std::affine_on(test_std::just(42)))); + auto r1 = test_std::sync_wait(test_std::starts_on(loop.get_scheduler(), test_std::affine(test_std::just(42)))); assert(r1); auto [v1] = *r1; assert(v1 == 42); test_order_of_connect(); - test_affine_on_specializations(test_std::just(42)); - test_affine_on_specializations(test_std::just(42, true, 3.14)); - test_affine_on_specializations(test_std::just_error(42)); - test_affine_on_specializations(test_std::just_stopped()); - test_affine_on_specializations(test_std::just_stopped()); - test_affine_on_specializations(test_std::read_env(test_std::get_stop_token)); - test_affine_on_specializations(test_std::write_env( + test_affine_specializations(test_std::just(42)); + test_affine_specializations(test_std::just(42, true, 3.14)); + test_affine_specializations(test_std::just_error(42)); + test_affine_specializations(test_std::just_stopped()); + test_affine_specializations(test_std::just_stopped()); + test_affine_specializations(test_std::read_env(test_std::get_stop_token)); + test_affine_specializations(test_std::write_env( test_std::just(42), test_std::env{test_std::prop{test_std::get_stop_token, test_std::never_stop_token{}}})); - test_affine_on_specializations( + test_affine_specializations( test_std::write_env(test_std::starts_on(loop.get_scheduler(), test_std::just(42)), test_std::env{test_std::prop{test_std::get_stop_token, test_std::never_stop_token{}}}), 1u); - test_affine_on_specializations(test_std::then(test_std::just(42), [](int) {})); - test_affine_on_specializations( + test_affine_specializations(test_std::then(test_std::just(42), [](int) {})); + test_affine_specializations( test_std::then(test_std::starts_on(loop.get_scheduler(), test_std::just(42)), [](auto&&...) {}), 1u); - test_affine_on_specializations(test_std::upon_error(test_std::just_error(42), [](int) {})); - test_affine_on_specializations( + test_affine_specializations(test_std::upon_error(test_std::just_error(42), [](int) {})); + test_affine_specializations( test_std::upon_error(test_std::starts_on(loop.get_scheduler(), test_std::just_error(42)), [](auto&&...) {}), 1u); - test_affine_on_specializations(test_std::upon_stopped(test_std::just_stopped(), [] {})); - test_affine_on_specializations( + test_affine_specializations(test_std::upon_stopped(test_std::just_stopped(), [] {})); + test_affine_specializations( test_std::upon_stopped(test_std::starts_on(loop.get_scheduler(), test_std::just_stopped()), [] {}), 1u); loop.finish(); diff --git a/tests/beman/execution/exec-scope-counting.test.cpp b/tests/beman/execution/exec-scope-counting.test.cpp index fdaf152f..3bf32ddc 100644 --- a/tests/beman/execution/exec-scope-counting.test.cpp +++ b/tests/beman/execution/exec-scope-counting.test.cpp @@ -10,6 +10,7 @@ import beman.execution; #else #include #include +#include #include #include #include @@ -47,7 +48,7 @@ struct join_receiver { using receiver_concept = test_std::receiver_tag; struct env { - auto query(const test_std::get_scheduler_t&) const noexcept -> test_std::inline_scheduler { return {}; } + auto query(const test_std::get_start_scheduler_t&) const noexcept -> test_std::inline_scheduler { return {}; } }; bool& called; diff --git a/tests/beman/execution/exec-scope-simple-counting.test.cpp b/tests/beman/execution/exec-scope-simple-counting.test.cpp index 202a6154..8393f6b3 100644 --- a/tests/beman/execution/exec-scope-simple-counting.test.cpp +++ b/tests/beman/execution/exec-scope-simple-counting.test.cpp @@ -10,6 +10,7 @@ import beman.execution; #else #include #include +#include #include #include #include @@ -44,7 +45,7 @@ struct join_receiver { using receiver_concept = test_std::receiver_tag; struct env { - auto query(const test_std::get_scheduler_t&) const noexcept -> test_std::inline_scheduler { return {}; } + auto query(const test_std::get_start_scheduler_t&) const noexcept -> test_std::inline_scheduler { return {}; } }; bool& called; diff --git a/tests/beman/execution/exec-snd-expos.test.cpp b/tests/beman/execution/exec-snd-expos.test.cpp index 84622af8..4bebfa6e 100644 --- a/tests/beman/execution/exec-snd-expos.test.cpp +++ b/tests/beman/execution/exec-snd-expos.test.cpp @@ -264,7 +264,7 @@ auto test_sched_env() -> void { auto env{test_detail::sched_env(sched)}; static_assert(test_detail::queryable); - auto qsched{env.query(test_std::get_scheduler)}; + auto qsched{env.query(test_std::get_start_scheduler)}; static_assert(::std::same_as); ASSERT(qsched == sched); diff --git a/tests/beman/execution/execution-syn.test.cpp b/tests/beman/execution/execution-syn.test.cpp index ad269fa8..c21897dc 100644 --- a/tests/beman/execution/execution-syn.test.cpp +++ b/tests/beman/execution/execution-syn.test.cpp @@ -411,8 +411,62 @@ auto test_sender_adaptor() -> void { static_assert(std::same_as, decltype(via_op)>); } +struct as_awaitable_awaiter { + auto await_ready() -> bool { return true; } + auto await_suspend(auto) -> void {} + auto await_resume() -> int { return 42; } +}; + +struct await_completion_adapted_sender { + auto as_awaitable(auto&) -> as_awaitable_awaiter { return {}; } +}; + +struct await_completion_adaptor { + auto operator()(auto&&) const -> await_completion_adapted_sender { return {}; } +}; + +struct await_completion_transformed_sender { + struct env { + auto query(const test_std::get_await_completion_adaptor_t&) const noexcept -> await_completion_adaptor { + return {}; + } + }; + + using sender_concept = test_std::sender_tag; + + auto get_env() const noexcept -> env { return {}; } + + template + static consteval auto get_completion_signatures() { + return test_std::completion_signatures{}; + } +}; + +struct await_completion_domain { + template + auto transform_sender(Tag, Sender&&, const Env&) const noexcept -> await_completion_transformed_sender { + return {}; + } +}; + +struct await_completion_env { + auto query(const test_std::get_domain_t&) const noexcept -> await_completion_domain { return {}; } +}; + +struct await_completion_source_sender { + using sender_concept = test_std::sender_tag; +}; + +struct await_completion_promise { + auto get_env() const noexcept -> await_completion_env { return {}; } +}; + auto test_as_awaitable() -> void { static_assert(std::same_as); + + await_completion_promise promise{}; + auto awaitable{test_std::as_awaitable(await_completion_source_sender{}, promise)}; + static_assert(std::same_as); } auto test_exec_env() -> void { From c644aee0f8123d4eb99c3b37ba710eb608bf483d Mon Sep 17 00:00:00 2001 From: Cra3z Date: Thu, 28 May 2026 13:57:49 +0800 Subject: [PATCH 2/4] Format code --- src/beman/execution/CMakeLists.txt | 20 ++++++++++---------- tests/beman/execution/CMakeLists.txt | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/beman/execution/CMakeLists.txt b/src/beman/execution/CMakeLists.txt index c63cfe87..5970aec7 100644 --- a/src/beman/execution/CMakeLists.txt +++ b/src/beman/execution/CMakeLists.txt @@ -23,7 +23,7 @@ target_sources( TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR}/include FILES - ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/affine.hpp + ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/affine.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/allocator_aware_move.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/allocator_of.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/almost_scheduler.hpp @@ -97,7 +97,7 @@ target_sources( ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_env.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_forward_progress_guarantee.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_scheduler.hpp - ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_start_scheduler.hpp + ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_start_scheduler.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_stop_token.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/handle.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/has_as_awaitable.hpp @@ -108,7 +108,7 @@ target_sources( ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/indeterminate_domain.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/indices_for.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/indirect_meta_apply.hpp - ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/infallible_scheduler.hpp + ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/infallible_scheduler.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/inline_attrs.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/inline_scheduler.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/inplace_stop_source.hpp @@ -134,7 +134,7 @@ target_sources( ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/meta_transform.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/meta_unique.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/movable_value.hpp - ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/nested_sender_has_affine.hpp + ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/nested_sender_has_affine.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/never_stop_token.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/non_assignable.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/nostopstate.hpp @@ -168,7 +168,7 @@ target_sources( ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sender_awaitable.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sender_decompose.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sender_for.hpp - ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sender_has_affine.hpp + ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sender_has_affine.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sender_in.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sender_to.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sends_stopped.hpp @@ -233,7 +233,7 @@ if(BEMAN_USE_MODULES) FILES execution.cppm execution-detail.cppm - affine.cppm + affine.cppm allocator_aware_move.cppm almost_scheduler.cppm apply_sender.cppm @@ -303,7 +303,7 @@ if(BEMAN_USE_MODULES) get_env.cppm get_forward_progress_guarantee.cppm get_scheduler.cppm - get_start_scheduler.cppm + get_start_scheduler.cppm get_stop_token.cppm has_as_awaitable.cppm has_completions.cppm @@ -313,7 +313,7 @@ if(BEMAN_USE_MODULES) indeterminate_domain.cppm indices_for.cppm indirect_meta_apply.cppm - infallible_scheduler.cppm + infallible_scheduler.cppm inline_attrs.cppm inline_scheduler.cppm inplace_stop_source.cppm @@ -339,7 +339,7 @@ if(BEMAN_USE_MODULES) meta_transform.cppm meta_unique.cppm movable_value.cppm - nested_sender_has_affine.cppm + nested_sender_has_affine.cppm never_stop_token.cppm notify.cppm non_assignable.cppm @@ -370,7 +370,7 @@ if(BEMAN_USE_MODULES) sender_awaitable.cppm sender_decompose.cppm sender_for.cppm - sender_has_affine.cppm + sender_has_affine.cppm sender_in.cppm sender.cppm sender_to.cppm diff --git a/tests/beman/execution/CMakeLists.txt b/tests/beman/execution/CMakeLists.txt index 9df9a708..29b11054 100644 --- a/tests/beman/execution/CMakeLists.txt +++ b/tests/beman/execution/CMakeLists.txt @@ -10,7 +10,7 @@ list(APPEND unsupported_execution_tests exec-split.test) list( APPEND execution_tests allocator-requirements-general.test - exec-affine.test + exec-affine.test exec-associate.test exec-awaitable.test exec-bulk.test From 74bce4249890fefa2854daf6dc65c1e8a2a55bfe Mon Sep 17 00:00:00 2001 From: Cra3z Date: Thu, 28 May 2026 16:41:31 +0800 Subject: [PATCH 3/4] Improve readability --- include/beman/execution/detail/get_start_scheduler.hpp | 4 ++-- .../beman/execution/detail/sender_adaptor_closure.hpp | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/include/beman/execution/detail/get_start_scheduler.hpp b/include/beman/execution/detail/get_start_scheduler.hpp index d6c71ae9..3fae8532 100644 --- a/include/beman/execution/detail/get_start_scheduler.hpp +++ b/include/beman/execution/detail/get_start_scheduler.hpp @@ -22,8 +22,8 @@ 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) { env.query(self); } - auto operator()(Env&& env) const noexcept { - return ::std::as_const(env).query(*this); + auto operator()(const Env& env) const noexcept { + return env.query(*this); } }; diff --git a/include/beman/execution/detail/sender_adaptor_closure.hpp b/include/beman/execution/detail/sender_adaptor_closure.hpp index bc6755a6..924e099a 100644 --- a/include/beman/execution/detail/sender_adaptor_closure.hpp +++ b/include/beman/execution/detail/sender_adaptor_closure.hpp @@ -121,8 +121,7 @@ struct composed_sender_adaptor_closure : sender_adaptor_closure, Sender> and nothrow_callable, call_result_t, Sender>>) -> call_result_t, call_result_t, Sender>> { - return ::beman::execution::detail::forward_like(self.outer)( - ::beman::execution::detail::forward_like(self.inner)(std::forward(sndr))); + return ::std::forward(self).outer(::std::forward(self).inner(std::forward(sndr))); } }; @@ -147,9 +146,9 @@ struct bound_sender_adaptor_closure : detail::product_type, Sender, apply_cvref_t...>) -> call_result_t, Sender, apply_cvref_t...> { - return self.apply([&](auto&&... bound_args) { - return ::beman::execution::detail::forward_like(self.adaptor)( - std::forward(sndr), ::beman::execution::detail::forward_like(bound_args)...); + return self.apply([&](CvBoundArgs&&... bound_args) { + return ::std::forward(self).adaptor(::std::forward(sndr), + ::std::forward(bound_args)...); }); } }; From 629440a2c810fb61ac500cb89551eb2d9366fcbd Mon Sep 17 00:00:00 2001 From: Cra3z Date: Thu, 28 May 2026 17:41:11 +0800 Subject: [PATCH 4/4] Refactor includes and update comments for clarity in affine.hpp --- include/beman/execution/detail/affine.hpp | 29 ++++++----------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/include/beman/execution/detail/affine.hpp b/include/beman/execution/detail/affine.hpp index 8179211f..7b3be2fe 100644 --- a/include/beman/execution/detail/affine.hpp +++ b/include/beman/execution/detail/affine.hpp @@ -15,55 +15,40 @@ import std; #endif #ifdef BEMAN_HAS_MODULES import beman.execution.detail.basic_sender; -import beman.execution.detail.completion_signatures; -import beman.execution.detail.completion_signatures_of_t; import beman.execution.detail.continues_on; import beman.execution.detail.env; import beman.execution.detail.forward_like; -import beman.execution.detail.fwd_env; import beman.execution.detail.get_completion_signatures; import beman.execution.detail.get_start_scheduler; -import beman.execution.detail.get_stop_token; import beman.execution.detail.infallible_scheduler; import beman.execution.detail.make_sender; -import beman.execution.detail.never_stop_token; import beman.execution.detail.nested_sender_has_affine; -import beman.execution.detail.prop; import beman.execution.detail.schedule; -import beman.execution.detail.schedule_from; import beman.execution.detail.scheduler; import beman.execution.detail.sender; import beman.execution.detail.sender_adaptor_closure; import beman.execution.detail.sender_for; -import beman.execution.detail.sender_has_affine; import beman.execution.detail.set_value; import beman.execution.detail.store_receiver; -import beman.execution.detail.tag_of_t; import beman.execution.detail.unstoppable; -import beman.execution.detail.write_env; #else -#include +#include #include #include #include -#include +#include #include -#include #include #include -#include #include -#include +#include #include #include #include #include -#include #include #include -#include #include -#include #endif // ---------------------------------------------------------------------------- @@ -93,7 +78,7 @@ struct unstoppable_scheduler { * to complete on the scheduler obtained from the receiver's environment. * * This adaptor implements scheduler affinity to adapt a sender to complete on the - * scheduler obtained the receiver's environment. The get_scheduler query is used + * scheduler obtained the receiver's environment. The get_start_scheduler query is used * to obtain the scheduler on which the sender gets started. */ struct affine_t : ::beman::execution::sender_adaptor_closure { @@ -118,7 +103,7 @@ struct affine_t : ::beman::execution::sender_adaptor_closure { auto operator()() const { return ::beman::execution::detail::make_sender_adaptor(*this); } /** - * @brief affine is implemented by transforming it into a use of schedule_from. + * @brief affine is implemented by transforming it into a use of continues_on. * * The constraints ensure that the environment provides a scheduler which is * infallible and, thus, can be used to guarantee completion on the correct @@ -126,7 +111,7 @@ struct affine_t : ::beman::execution::sender_adaptor_closure { * * The implementation first tries to see if the child sender's tag has a custom * affine implementation. If it does, that is used. Otherwise, the default - * implementation gets a scheduler from the environment and uses schedule_from + * implementation gets a scheduler from the environment and uses continues_on * to adapt the sender to complete on that scheduler. * * @tparam Sender The type of the sender to be transformed. @@ -189,7 +174,7 @@ struct affine_t : ::beman::execution::sender_adaptor_closure { namespace beman::execution { /** * @brief affine is a CPO, used to adapt a sender to complete on the scheduler - * it got started on which is derived from get_scheduler on the receiver's environment. + * it got started on which is derived from get_start_scheduler on the receiver's environment. */ using affine_t = beman::execution::detail::affine_t; inline constexpr beman::execution::detail::affine_t affine{};