diff --git a/include/stdexec/__detail/__affine_on.hpp b/include/stdexec/__detail/__affine_on.hpp index d40308883..67e5ee658 100644 --- a/include/stdexec/__detail/__affine_on.hpp +++ b/include/stdexec/__detail/__affine_on.hpp @@ -24,10 +24,8 @@ namespace STDEXEC { - struct _CANNOT_MAKE_SENDER_AFFINE_TO_THE_CURRENT_SCHEDULER_ - {}; - struct _THE_SCHEDULER_IN_THE_CURRENT_EXECUTION_ENVIRONMENT_IS_NOT_INFALLIBLE_ - {}; + struct _CANNOT_MAKE_SENDER_AFFINE_TO_THE_STARTING_SCHEDULER_; + struct _THE_SCHEDULER_IN_THE_CURRENT_EXECUTION_ENVIRONMENT_IS_NOT_INFALLIBLE_; namespace __affine_on { @@ -87,18 +85,22 @@ namespace STDEXEC { // The environment doesn't have a scheduler, so we can't adapt the sender to be // affine. Instead, return a type describing the problem. - return __not_a_sender<_WHAT_(_CANNOT_MAKE_SENDER_AFFINE_TO_THE_CURRENT_SCHEDULER_), - _WHY_(_THE_CURRENT_EXECUTION_ENVIRONMENT_DOESNT_HAVE_A_SCHEDULER_), - _WHERE_(_IN_ALGORITHM_, affine_on_t)>{}; + return __not_a_sender< // + _WHAT_(_CANNOT_MAKE_SENDER_AFFINE_TO_THE_STARTING_SCHEDULER_), + _WHY_(_THE_CURRENT_EXECUTION_ENVIRONMENT_DOESNT_HAVE_A_SCHEDULER_), + _WHERE_(_IN_ALGORITHM_, affine_on_t), + _WITH_PRETTY_SENDER_<__cv_child_t>, + _WITH_ENVIRONMENT_(_Env)>{}; } else if constexpr (!__infallible_scheduler<__sched_t, __unstoppable_env_t<_Env>>) { // The scheduler in the environment isn't infallible, so we can't adapt the sender to be // affine. Instead, return a type describing the problem. return __not_a_sender< - _WHAT_(_CANNOT_MAKE_SENDER_AFFINE_TO_THE_CURRENT_SCHEDULER_), + _WHAT_(_CANNOT_MAKE_SENDER_AFFINE_TO_THE_STARTING_SCHEDULER_), _WHY_(_THE_SCHEDULER_IN_THE_CURRENT_EXECUTION_ENVIRONMENT_IS_NOT_INFALLIBLE_), _WHERE_(_IN_ALGORITHM_, affine_on_t), + _WITH_PRETTY_SENDER_<__cv_child_t>, _WITH_SCHEDULER_(__sched_t)>{}; } else diff --git a/include/stdexec/__detail/__on.hpp b/include/stdexec/__detail/__on.hpp index b37288eac..c822648ac 100644 --- a/include/stdexec/__detail/__on.hpp +++ b/include/stdexec/__detail/__on.hpp @@ -34,29 +34,7 @@ namespace STDEXEC { ///////////////////////////////////////////////////////////////////////////// // [execution.senders.adaptors.on] - namespace __on - { - struct on_t; - struct _CANNOT_RESTORE_EXECUTION_CONTEXT_AFTER_ON_ - {}; - - template - struct __no_scheduler_in_environment - { - using sender_concept = sender_t; - - template - static consteval auto get_completion_signatures() - { - return STDEXEC::__throw_compile_time_error< - _WHAT_(_CANNOT_RESTORE_EXECUTION_CONTEXT_AFTER_ON_), - _WHY_(_THE_CURRENT_EXECUTION_ENVIRONMENT_DOESNT_HAVE_A_SCHEDULER_), - _WHERE_(_IN_ALGORITHM_, on_t), - _WITH_PRETTY_SENDER_<_Sender>, - _WITH_ENVIRONMENT_(_Env)>(); - } - }; - } // namespace __on + struct _CANNOT_RESTORE_EXECUTION_CONTEXT_AFTER_ON_; //////////////////////////////////////////////////////////////////////////////////////////////// struct on_t @@ -84,70 +62,64 @@ namespace STDEXEC return __closure(*this, static_cast<_Scheduler&&>(__sched), static_cast<_Closure&&>(__clsur)); } - // This transform_sender overload handles the case where `on` was called like - // `on(sch, sndr)`. In this case, we find the old scheduler by looking in the - // receiver's environment. + // This transform_sender overload handles the case where `on` was called like `on(sch, + // sndr)`. In this case, we find the old scheduler by looking in the receiver's + // environment. template <__decay_copyable _Sender, class _Env> requires scheduler<__data_of<_Sender>> STDEXEC_ATTRIBUTE(always_inline) static auto transform_sender(set_value_t, _Sender&& __sndr, _Env const & __env) { - auto& [__tag, __sched, __child] = __sndr; - auto __old = __with_default(get_scheduler, __end_sched_t<_Sender, _Env>())(__env); + static_assert(__sender_for<_Sender, on_t>); + auto& [__tag, __new_sched, __child] = __sndr; + auto __old_sched = __with_default(get_scheduler, __end_sched_t<_Sender, _Env>())(__env); - return continues_on(starts_on(STDEXEC::__forward_like<_Sender>(__sched), + return continues_on(starts_on(STDEXEC::__forward_like<_Sender>(__new_sched), STDEXEC::__forward_like<_Sender>(__child)), - std::move(__old)); + std::move(__old_sched)); } - // This transform_sender overload handles the case where `on` was called like - // `sndr | on(sch, clsur)` or `on(sndr, sch, clsur)`. In this case, __child is a - // predecessor sender, so the scheduler we want to restore is the completion - // scheduler of __child. + // This transform_sender overload handles the case where `on` was called like `sndr | + // on(sch, clsur)` or `on(sndr, sch, clsur)`. In this case, __child is a predecessor + // sender, so the scheduler we want to restore is the completion scheduler of __child. template <__decay_copyable _Sender, class _Env> requires(!scheduler<__data_of<_Sender>>) STDEXEC_ATTRIBUTE(always_inline) static auto transform_sender(set_value_t, _Sender&& __sndr, _Env const & __env) { + static_assert(__sender_for<_Sender, on_t>); auto& [__tag, __data, __child] = __sndr; - auto& [__sched, __clsur] = __data; + auto& [__new_sched, __clsur] = __data; - auto __old = __with_default(get_completion_scheduler, - __end_sched_t<_Sender, _Env>())(get_env(__child), __env); + auto __old_sched = __with_default(get_completion_scheduler, + __end_sched_t<_Sender, _Env>())(get_env(__child), __env); - auto __pred = __reschedule(STDEXEC::__forward_like<_Sender>(__child), __old, __sched); - return __reschedule(STDEXEC::__forward_like<_Sender>(__clsur)(std::move(__pred)), - std::move(__sched), - std::move(__old)); + return continues_on(STDEXEC::__forward_like<_Sender>(__clsur)( + continues_on(STDEXEC::__forward_like<_Sender>(__child), + STDEXEC::__forward_like<_Sender>(__new_sched))), + std::move(__old_sched)); } template static auto transform_sender(set_value_t, _Sender&&, _Env const &) { - return __not_a_sender<_SENDER_TYPE_IS_NOT_DECAY_COPYABLE_, _WITH_PRETTY_SENDER_<_Sender>>{}; + return __not_a_sender<_WHAT_(_SENDER_TYPE_IS_NOT_DECAY_COPYABLE_), + _WITH_PRETTY_SENDER_<_Sender>>{}; } private: - // If __is_root_env<_Env> is true, then this sender has no parent, so there is - // no need to restore the execution context. We can use the inline scheduler - // as the scheduler if __env does not have one. + // If __is_root_env<_Env> is true, then this sender has no parent, so there is no need + // to restore the execution context. We can use the inline scheduler as the scheduler + // if __env does not have one. template using __end_sched_t = __if_c<__is_root_env<_Env>, inline_scheduler, - __not_a_scheduler<__on::__no_scheduler_in_environment<_Sender, _Env>>>; - - template - static constexpr auto __reschedule(_Sender&& __sndr, - [[maybe_unused]] _OldSched&& __old_sched, - _NewSched&& __new_sched) - { - // BUGBUG TODO(ericniebler): FIXME - // return continues_on( - // write_env(static_cast<_Sender&&>(__sndr), __sched_env{__old_sched}), - // static_cast<_NewSched&&>(__new_sched)); - return continues_on(static_cast<_Sender&&>(__sndr), static_cast<_NewSched&&>(__new_sched)); - } + __not_a_scheduler<_WHAT_(_CANNOT_RESTORE_EXECUTION_CONTEXT_AFTER_ON_), + _WHY_(_THE_CURRENT_EXECUTION_ENVIRONMENT_DOESNT_HAVE_A_SCHEDULER_), + _WHERE_(_IN_ALGORITHM_, on_t), + _WITH_PRETTY_SENDER_<__child_of<_Sender>>, + _WITH_ENVIRONMENT_(_Env)>>; }; inline constexpr on_t on{};