|
16 | 16 | #pragma once |
17 | 17 |
|
18 | 18 | #include "../stdexec/execution.hpp" |
19 | | -#include "env.hpp" |
20 | | -#include "__detail/__sender_facade.hpp" |
21 | 19 |
|
22 | 20 | namespace exec { |
23 | 21 | ///////////////////////////////////////////////////////////////////////////// |
24 | 22 | // A scoped version of [execution.senders.adaptors.on] |
25 | 23 | namespace __on { |
26 | | - using namespace stdexec; |
27 | | - |
28 | | - enum class on_kind { |
29 | | - start_on, |
30 | | - continue_on |
31 | | - }; |
32 | | - |
33 | | - template <on_kind> |
34 | | - struct on_t; |
35 | | - |
36 | | - template <class _Env, class _Sender> |
37 | | - struct _ENVIRONMENT_HAS_NO_SCHEDULER_FOR_THE_ON_ADAPTOR_TO_TRANSITION_BACK_TO { }; |
38 | | - |
39 | | - template <class _Env, class _SchedulerId> |
40 | | - struct __with_sched_env |
41 | | - : __env::__env_join_t<__env::__with<get_scheduler_t, __t<_SchedulerId>>, _Env> { }; |
42 | | - |
43 | | - template <class _Env, class _Scheduler> |
44 | | - __with_sched_env<_Env, __id<_Scheduler>> __make_env(_Env&& __env, _Scheduler __sched) noexcept { |
45 | | - return {__join_env(__env::__with_(get_scheduler, __sched), (_Env&&) __env)}; |
46 | | - } |
47 | | - |
48 | | - template <class _Scheduler> |
49 | | - struct __with_sched_kernel : __default_kernel { |
50 | | - _Scheduler __sched_; |
51 | | - |
52 | | - __with_sched_kernel(_Scheduler __sched) |
53 | | - : __sched_((_Scheduler&&) __sched) { |
54 | | - } |
55 | | - |
56 | | - template <class _Env> |
57 | | - __with_sched_env<_Env, __id<_Scheduler>> get_env(_Env&& __env) noexcept { |
58 | | - return __on::__make_env((_Env&&) __env, __sched_); |
59 | | - } |
60 | | - |
61 | | - template <class _Env, class _OtherSchedulerId> |
62 | | - _Env get_env(__with_sched_env<_Env, _OtherSchedulerId> __env) noexcept { |
63 | | - return __env.base(); |
64 | | - } |
65 | | - }; |
66 | | - |
67 | | - template <class _SenderId, class _Scheduler> |
68 | | - struct __with_sched |
69 | | - : __sender_facade< |
70 | | - __with_sched<_SenderId, _Scheduler>, |
71 | | - __t<_SenderId>, |
72 | | - __with_sched_kernel<_Scheduler>> { }; |
73 | | - |
74 | | - struct __dependent_sender { |
75 | | - using is_sender = void; |
76 | | - using __id = __dependent_sender; |
77 | | - using __t = __dependent_sender; |
78 | | - using completion_signatures = dependent_completion_signatures<no_env>; |
79 | | - }; |
80 | | - |
81 | | - template <class _SenderId, class _Scheduler> |
82 | | - struct __start_on; |
83 | | - |
84 | | - template <class _Sender, class _Scheduler> |
85 | | - using __start_on_t = __t<__start_on<__id<__decay_t<_Sender>>, _Scheduler>>; |
86 | | - |
87 | | - template <class _Scheduler> |
88 | | - struct __start_on_kernel : __default_kernel { |
89 | | - _Scheduler __sched_; |
90 | | - |
91 | | - explicit __start_on_kernel(_Scheduler __sched) |
92 | | - : __sched_((_Scheduler&&) __sched) { |
93 | | - } |
94 | | - |
95 | | - template <class... _Ts> |
96 | | - using __self_t = __mfront<__start_on_kernel, _Ts...>; |
97 | | - |
98 | | - template <class _Sender, class _OldScheduler> |
99 | | - auto transform_sender_(_Sender&& __sndr, _OldScheduler __old_sched) { |
100 | | - return stdexec::on(__sched_, (_Sender&&) __sndr) | transfer(__old_sched); |
101 | | - } |
102 | | - |
103 | | - template <class _Sender, class _Receiver> |
104 | | - using __new_sender_t = // |
105 | | - decltype(__declval<__self_t<_Sender, _Receiver>&>().transform_sender_( |
106 | | - __declval<_Sender>(), |
107 | | - __declval<__current_scheduler_t<_Receiver>>())); |
108 | | - |
109 | | - template <class _Sender> |
110 | | - using __on_sender_t = __copy_cvref_t<_Sender, __start_on_t<_Sender, _Scheduler>>; |
111 | | - |
112 | | - template <class _Sender, class _Receiver> |
113 | | - using __diagnostic_t = // |
114 | | - __minvoke< // |
115 | | - _FAILURE_TO_CONNECT_, // |
116 | | - _ENVIRONMENT_HAS_NO_SCHEDULER_FOR_THE_ON_ADAPTOR_TO_TRANSITION_BACK_TO< |
117 | | - env_of_t<_Receiver>, |
118 | | - __on_sender_t<_Sender>>>; |
119 | | - |
120 | | - template <class _Sender, class _Receiver> |
121 | | - static auto __transform_sender_result() { |
122 | | - if constexpr (__mvalid<__new_sender_t, _Sender, _Receiver>) { |
123 | | - return (__new_sender_t<_Sender, _Receiver>(*)()) nullptr; |
124 | | - } else if constexpr (same_as<env_of_t<_Receiver>, no_env>) { |
125 | | - return (__dependent_sender(*)()) nullptr; |
126 | | - } else { |
127 | | - return (__diagnostic_t<_Sender, _Receiver>(*)()) nullptr; |
128 | | - } |
129 | | - } |
130 | | - |
131 | | - template <class _Sender, class _Receiver> |
132 | | - using __result_t = decltype(__transform_sender_result<_Sender, _Receiver>()()); |
133 | | - |
134 | | - template <class _Sender, class _Receiver> |
135 | | - auto transform_sender(_Sender&& __sndr, __ignore, _Receiver& __rcvr) |
136 | | - -> __result_t<_Sender, _Receiver> { |
137 | | - if constexpr (__mvalid<__new_sender_t, _Sender, _Receiver>) { |
138 | | - auto __sched = get_scheduler(stdexec::get_env(__rcvr)); |
139 | | - return transform_sender_((_Sender&&) __sndr, __sched); |
140 | | - } else { |
141 | | - return {}; |
142 | | - } |
143 | | - } |
| 24 | + struct on_t |
| 25 | + : stdexec::v2::on_t |
| 26 | + , stdexec::v2::continue_on_t { |
| 27 | + using stdexec::v2::on_t::operator(); |
| 28 | + using stdexec::v2::continue_on_t::operator(); |
144 | 29 | }; |
145 | 30 |
|
146 | | - template <class _SenderId, class _Scheduler> |
147 | | - struct __start_on { |
148 | | - using __base = // |
149 | | - stdexec::__t< __sender_facade< |
150 | | - __start_on<_SenderId, _Scheduler>, |
151 | | - stdexec::__t<_SenderId>, |
152 | | - __start_on_kernel<_Scheduler>>>; |
153 | | - |
154 | | - struct __t : __base { |
155 | | - using __base::__base; |
156 | | - }; |
157 | | - }; |
158 | | - |
159 | | - template <> |
160 | | - struct on_t<on_kind::start_on> { |
161 | | - template <scheduler _Scheduler, sender _Sender> |
162 | | - requires constructible_from<__decay_t<_Sender>, _Sender> |
163 | | - auto operator()(_Scheduler __sched, _Sender&& __sndr) const |
164 | | - -> __start_on_t<_Sender, _Scheduler> { |
165 | | - // connect-based customization will remove the need for this check |
166 | | - using __has_customizations = __call_result_t<__has_algorithm_customizations_t, _Scheduler>; |
167 | | - static_assert( |
168 | | - !__has_customizations{}, |
169 | | - "For now the default exec::on implementation doesn't support scheduling " |
170 | | - "onto schedulers that customize algorithms."); |
171 | | - return {(_Sender&&) __sndr, (_Scheduler&&) __sched}; |
172 | | - } |
173 | | - }; |
174 | | - |
175 | | - template <class _SenderId, class _Scheduler, class _Closure> |
176 | | - struct __continue_on; |
177 | | - |
178 | | - template <class _Sender, class _Scheduler, class _Closure> |
179 | | - using __continue_on_t = __t<__continue_on<__id<__decay_t<_Sender>>, _Scheduler, _Closure>>; |
180 | | - |
181 | | - template <class _Scheduler, class _Closure> |
182 | | - struct __continue_on_kernel : __default_kernel { |
183 | | - _Scheduler __sched_; |
184 | | - _Closure __closure_; |
185 | | - |
186 | | - __continue_on_kernel(_Scheduler __sched, _Closure __closure) |
187 | | - : __sched_((_Scheduler&&) __sched) |
188 | | - , __closure_((_Closure&&) __closure) { |
189 | | - } |
190 | | - |
191 | | - template <class... _Ts> |
192 | | - using __self_t = __mfront<__continue_on_kernel, _Ts...>; |
193 | | - |
194 | | - template <class _Sender, class _OldScheduler> |
195 | | - auto transform_sender_(_Sender&& __sndr, _OldScheduler __old_sched) { |
196 | | - using __sender_t = __t<__with_sched<__id<__decay_t<_Sender>>, _OldScheduler>>; |
197 | | - return __sender_t{(_Sender&&) __sndr, __old_sched} | transfer(__sched_) |
198 | | - | (__copy_cvref_t<_Sender, _Closure>&&) __closure_ | transfer(__old_sched); |
199 | | - } |
200 | | - |
201 | | - template <class _Sender, class _Receiver> |
202 | | - using __new_sender_t = // |
203 | | - decltype(__declval<__self_t<_Sender, _Receiver>&>().transform_sender_( |
204 | | - __declval<_Sender>(), |
205 | | - __declval<__current_scheduler_t<_Receiver>>())); |
206 | | - |
207 | | - template <class _Sender> |
208 | | - using __on_sender_t = __copy_cvref_t<_Sender, __continue_on_t<_Sender, _Scheduler, _Closure>>; |
209 | | - |
210 | | - template <class _Sender, class _Receiver> |
211 | | - using __diagnostic_t = // |
212 | | - __minvoke< // |
213 | | - _FAILURE_TO_CONNECT_, // |
214 | | - _ENVIRONMENT_HAS_NO_SCHEDULER_FOR_THE_ON_ADAPTOR_TO_TRANSITION_BACK_TO< |
215 | | - env_of_t<_Receiver>, |
216 | | - __on_sender_t<_Sender>>>; |
217 | | - |
218 | | - template <class _Sender, class _Receiver> |
219 | | - static auto __transform_sender_result() { |
220 | | - if constexpr (__mvalid<__new_sender_t, _Sender, _Receiver>) { |
221 | | - return (__new_sender_t<_Sender, _Receiver>(*)()) nullptr; |
222 | | - } else if constexpr (same_as<env_of_t<_Receiver>, no_env>) { |
223 | | - return (__dependent_sender(*)()) nullptr; |
224 | | - } else { |
225 | | - return (__diagnostic_t<_Sender, _Receiver>(*)()) nullptr; |
226 | | - } |
227 | | - } |
228 | | - |
229 | | - template <class _Sender, class _Receiver> |
230 | | - using __result_t = decltype(__transform_sender_result<_Sender, _Receiver>()()); |
231 | | - |
232 | | - template <class _Sender, class _Receiver> |
233 | | - auto transform_sender(_Sender&& __sndr, __ignore, _Receiver& __rcvr) |
234 | | - -> __result_t<_Sender, _Receiver> { |
235 | | - if constexpr (__mvalid<__new_sender_t, _Sender, _Receiver>) { |
236 | | - auto __sched = get_scheduler(stdexec::get_env(__rcvr)); |
237 | | - return transform_sender_((_Sender&&) __sndr, __sched); |
238 | | - } else { |
239 | | - return {}; |
240 | | - } |
241 | | - } |
242 | | - |
243 | | - template <class _Env> |
244 | | - __with_sched_env<_Env, __id<_Scheduler>> get_env(_Env&& __env) noexcept { |
245 | | - return __on::__make_env((_Env&&) __env, __sched_); |
246 | | - } |
247 | | - }; |
248 | | - |
249 | | - template <class _SenderId, class _Scheduler, class _Closure> |
250 | | - struct __continue_on { |
251 | | - using __base = // |
252 | | - stdexec::__t<__sender_facade< |
253 | | - __continue_on<_SenderId, _Scheduler, _Closure>, |
254 | | - stdexec::__t<_SenderId>, |
255 | | - __continue_on_kernel<_Scheduler, _Closure>>>; |
256 | | - |
257 | | - struct __t : __base { |
258 | | - using __base::__base; |
259 | | - }; |
260 | | - }; |
261 | | - |
262 | | - template <> |
263 | | - struct on_t<on_kind::continue_on> { |
264 | | - template <sender _Sender, scheduler _Scheduler, __sender_adaptor_closure_for<_Sender> _Closure> |
265 | | - requires constructible_from<__decay_t<_Sender>, _Sender> |
266 | | - auto operator()(_Sender&& __sndr, _Scheduler __sched, _Closure __closure) const |
267 | | - -> __continue_on_t<_Sender, _Scheduler, _Closure> { |
268 | | - return {(_Sender&&) __sndr, (_Scheduler&&) __sched, (_Closure&&) __closure}; |
269 | | - } |
270 | | - |
271 | | - template <scheduler _Scheduler, __sender_adaptor_closure _Closure> |
272 | | - auto operator()(_Scheduler __sched, _Closure __closure) const |
273 | | - -> __binder_back<on_t, _Scheduler, _Closure> { |
274 | | - return { |
275 | | - {}, |
276 | | - {}, |
277 | | - {(_Scheduler&&) __sched, (_Closure&&) __closure} |
278 | | - }; |
279 | | - } |
280 | | - }; |
281 | | - |
282 | | - struct __on_t |
283 | | - : on_t<on_kind::start_on> |
284 | | - , on_t<on_kind::continue_on> { |
285 | | - using on_t<on_kind::start_on>::operator(); |
286 | | - using on_t<on_kind::continue_on>::operator(); |
287 | | - }; |
288 | 31 | } // namespace __on |
289 | 32 |
|
290 | | - using __on::on_kind; |
291 | 33 | using __on::on_t; |
292 | | - inline constexpr __on::__on_t on{}; |
| 34 | + inline constexpr on_t on{}; |
293 | 35 | } // namespace exec |
0 commit comments