2828#include " __senders_core.hpp"
2929#include " __sender_adaptor_closure.hpp"
3030#include " __sender_introspection.hpp"
31- #include " __type_traits.hpp"
3231#include " __utility.hpp"
32+ #include " __write_env.hpp"
3333
3434namespace stdexec {
3535 // ///////////////////////////////////////////////////////////////////////////
3636 // [execution.senders.adaptors.on]
3737 namespace __on {
38- inline constexpr __mstring __on_context = " In stdexec::on(Scheduler, Sender)..." _mstr;
39- inline constexpr __mstring __no_scheduler_diag =
40- " stdexec::on() requires a scheduler to transition back to." _mstr;
41- inline constexpr __mstring __no_scheduler_details =
42- " The provided environment lacks a value for the get_scheduler() query." _mstr;
43-
44- template <
45- __mstring _Context = __on_context,
46- __mstring _Diagnostic = __no_scheduler_diag,
47- __mstring _Details = __no_scheduler_details
48- >
49- struct _CANNOT_RESTORE_EXECUTION_CONTEXT_AFTER_ON_ { };
50-
5138 struct on_t ;
5239
53- template <class _Sender , class _Env >
54- struct __no_scheduler_in_environment {
55- using sender_concept = sender_t ;
56-
57- STDEXEC_EXPLICIT_THIS_BEGIN (auto get_completion_signatures)(
58- this const __no_scheduler_in_environment&,
59- const auto &) noexcept {
60- return __mexception<
61- _CANNOT_RESTORE_EXECUTION_CONTEXT_AFTER_ON_<>,
62- _WITH_SENDER_<_Sender>,
63- _WITH_ENVIRONMENT_<_Env>
64- >{};
65- }
66- STDEXEC_EXPLICIT_THIS_END (get_completion_signatures)
67- };
40+ struct _CANNOT_RESTORE_THE_EXECUTION_CONTEXT_AFTER_ON ;
41+ struct _THE_ENVIRONMENT_OF_THE_RECEIVER_DOES_NOT_HAVE_A_SCHEDULER_FOR_ON_TO_RETURN_TO ;
42+ struct _THE_PREDECESSOR_SENDER_DOES_NOT_KNOW_THE_SCHEDULER_ON_WHICH_IT_COMPLETES ;
6843
6944 template <class _Scheduler , class _Closure >
7045 struct __on_data {
@@ -73,7 +48,8 @@ namespace stdexec {
7348 };
7449
7550 template <class _Scheduler , class _Closure >
76- __on_data (_Scheduler, _Closure) -> __on_data<_Scheduler, _Closure>;
51+ STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE __on_data (_Scheduler, _Closure) //
52+ ->__on_data<_Scheduler, _Closure>;
7753
7854 // //////////////////////////////////////////////////////////////////////////////////////////////
7955 struct on_t {
@@ -99,30 +75,31 @@ namespace stdexec {
9975 }
10076
10177 template <class _Sender , class _OldSched , class _NewSched >
102- static auto __reschedule (
103- _Sender&& __sndr,
104- [[maybe_unused]] _OldSched&& __old_sched,
105- _NewSched&& __new_sched) {
106- // return continues_on(
107- // write_env(static_cast<_Sender&&>(__sndr), __sched_env{__old_sched}),
108- // static_cast<_NewSched&&>(__new_sched));
109- return continues_on (static_cast <_Sender&&>(__sndr), static_cast <_NewSched&&>(__new_sched));
78+ static auto __reschedule (_Sender&& __sndr, _OldSched&& __old_sched, _NewSched&& __new_sched) {
79+ return continues_on (
80+ write_env (static_cast <_Sender&&>(__sndr), __sched_env{__old_sched}),
81+ static_cast <_NewSched&&>(__new_sched));
11082 }
11183
11284 template <class _Sender , class _Env >
11385 STDEXEC_ATTRIBUTE (always_inline)
11486 static auto __transform_sender_fn (const _Env& __env) noexcept {
11587 return [&]<class _Data , class _Child >(__ignore, _Data&& __data, _Child&& __child) {
116- // If __is_root_env<_Env> is true, then this sender has no parent, so there is
117- // no need to restore the execution context. We can use the inline scheduler
118- // as the scheduler if __env does not have one.
119- using __end_sched_t = __if_c<
120- __is_root_env<_Env>,
121- inline_scheduler,
122- __not_a_scheduler<__no_scheduler_in_environment<_Sender, _Env>>
123- >;
12488
12589 if constexpr (scheduler<_Data>) {
90+ using __not_a_scheduler = stdexec::__not_a_scheduler<
91+ _WHAT_<>(_CANNOT_RESTORE_THE_EXECUTION_CONTEXT_AFTER_ON),
92+ _WHY_ (_THE_ENVIRONMENT_OF_THE_RECEIVER_DOES_NOT_HAVE_A_SCHEDULER_FOR_ON_TO_RETURN_TO),
93+ _WHERE_ (_IN_ALGORITHM_, on_t ),
94+ _WITH_ENVIRONMENT_<_Env>,
95+ _WITH_SENDER_<_Child>
96+ >;
97+
98+ // If __is_root_env<_Env> is true, then this sender has no parent, so there is
99+ // no need to restore the execution context. We can use the inline scheduler
100+ // as the scheduler if __env does not have one.
101+ using __end_sched_t = __if_c<__is_root_env<_Env>, inline_scheduler, __not_a_scheduler>;
102+
126103 // This branch handles the case where `on` was called like `on(sch, sndr)`. In
127104 // this case, we find the old scheduler by looking in the receiver's
128105 // environment.
@@ -132,6 +109,19 @@ namespace stdexec {
132109 starts_on (static_cast <_Data&&>(__data), static_cast <_Child&&>(__child)),
133110 static_cast <decltype (__old)&&>(__old));
134111 } else {
112+ using __not_a_scheduler = stdexec::__not_a_scheduler<
113+ _WHAT_<>(_CANNOT_RESTORE_THE_EXECUTION_CONTEXT_AFTER_ON),
114+ _WHY_ (_THE_PREDECESSOR_SENDER_DOES_NOT_KNOW_THE_SCHEDULER_ON_WHICH_IT_COMPLETES),
115+ _WHERE_ (_IN_ALGORITHM_, on_t ),
116+ _WITH_SENDER_<_Child>,
117+ _WITH_ENVIRONMENT_<_Env>
118+ >;
119+
120+ // If __is_root_env<_Env> is true, then this sender has no parent, so there is
121+ // no need to restore the execution context. We can use the inline scheduler
122+ // as the scheduler if __env does not have one.
123+ using __end_sched_t = __if_c<__is_root_env<_Env>, inline_scheduler, __not_a_scheduler>;
124+
135125 // This branch handles the case where `on` was called like `sndr | on(sch,
136126 // clsur)`. In this case, __child is a predecessor sender, so the scheduler we
137127 // want to restore is the completion scheduler of __child.
0 commit comments