1 /*
2  * Copyright (c) 2021-2024 NVIDIA Corporation
3  *
4  * Licensed under the Apache License Version 2.0 with LLVM Exceptions
5  * (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  *
8  *   https://llvm.org/LICENSE.txt
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include "__execution_fwd.hpp"
19 
20 // include these after __execution_fwd.hpp
21 #include "__completion_signatures.hpp"
22 #include "__concepts.hpp"
23 #include "__debug.hpp"
24 #include "__diagnostics.hpp"
25 #include "__meta.hpp"
26 #include "__senders_core.hpp"
27 
28 #include <tuple>
29 #include <variant>
30 
31 namespace stdexec
32 {
33 #if STDEXEC_ENABLE_EXTRA_TYPE_CHECKING()
34 // __checked_completion_signatures is for catching logic bugs in a sender's
35 // metadata. If sender<S> and sender_in<S, Ctx> are both true, then they had
36 // better report the same metadata. This completion signatures wrapper enforces
37 // that at compile time.
38 template <class _Sender, class... _Env>
__checked_completion_signatures(_Sender && __sndr,_Env &&...__env)39 auto __checked_completion_signatures(_Sender&& __sndr, _Env&&... __env) noexcept
40 {
41     using __completions_t = __completion_signatures_of_t<_Sender, _Env...>;
42     stdexec::__debug_sender(static_cast<_Sender&&>(__sndr), __env...);
43     return __completions_t{};
44 }
45 
46 template <class _Sender, class... _Env>
47     requires sender_in<_Sender, _Env...>
48 using completion_signatures_of_t =
49     decltype(stdexec::__checked_completion_signatures(__declval<_Sender>(),
50                                                       __declval<_Env>()...));
51 #else
52 template <class _Sender, class... _Env>
53     requires sender_in<_Sender, _Env...>
54 using completion_signatures_of_t =
55     __completion_signatures_of_t<_Sender, _Env...>;
56 #endif
57 
58 struct __not_a_variant
59 {
60     __not_a_variant() = delete;
61 };
62 
63 template <class... _Ts>
64 using __std_variant = //
65     __minvoke_if_c<sizeof...(_Ts) != 0,
66                    __mtransform<__q1<__decay_t>, __munique<__qq<std::variant>>>,
67                    __mconst<__not_a_variant>, _Ts...>;
68 
69 template <class... _Ts>
70 using __nullable_std_variant =
71     __mcall<__munique<__mbind_front<__qq<std::variant>, std::monostate>>,
72             __decay_t<_Ts>...>;
73 
74 template <class... _Ts>
75 using __decayed_std_tuple = __meval<std::tuple, __decay_t<_Ts>...>;
76 
77 namespace __sigs
78 {
79 // The following code is used to normalize completion signatures.
80 // "Normalization" means that that rvalue-references are stripped from the types
81 // in the completion signatures. For example, the completion signature
82 // `set_value_t(int &&)` would be normalized to `set_value_t(int)`, but
83 // `set_value_t(int)` and `set_value_t(int &)` would remain unchanged.
84 template <class _Tag, class... _Args>
85 auto __normalize_sig_impl(_Args&&...) -> _Tag (*)(_Args...);
86 
87 template <class _Tag, class... _Args>
88 auto __normalize_sig(_Tag (*)(_Args...))
89     -> decltype(__sigs::__normalize_sig_impl<_Tag>(__declval<_Args>()...));
90 
91 template <class... _Sigs>
92 auto __repack_completions(_Sigs*...) -> completion_signatures<_Sigs...>;
93 
94 template <class... _Sigs>
95 auto __normalize_completions(completion_signatures<_Sigs...>*)
96     -> decltype(__sigs::__repack_completions(
97         __sigs::__normalize_sig(static_cast<_Sigs*>(nullptr))...));
98 
99 template <class _Completions>
100 using __normalize_completions_t = decltype(__sigs::__normalize_completions(
101     static_cast<_Completions*>(nullptr)));
102 } // namespace __sigs
103 
104 template <class... _SigPtrs>
105 using __completion_signature_ptrs = //
106     decltype(__sigs::__repack_completions(static_cast<_SigPtrs>(nullptr)...));
107 
108 template <class... _Sigs>
109 using __concat_completion_signatures = //
110     __mconcat<__qq<completion_signatures>>::__f<
111         __mconcat<__qq<__mmake_set>>::__f<_Sigs...>>;
112 
113 namespace __sigs
114 {
115 //////////////////////////////////////////////////////////////////////////////////////////////////
116 template <template <class...> class _Tuple, class _Tag, class... _Args>
117 auto __for_each_sig(_Tag (*)(_Args...)) -> _Tuple<_Tag, _Args...>;
118 
119 template <class _Sig, template <class...> class _Tuple>
120 using __for_each_sig_t =
121     decltype(__sigs::__for_each_sig<_Tuple>(static_cast<_Sig*>(nullptr)));
122 
123 template <template <class...> class _Tuple, template <class...> class _Variant,
124           class... _More, class _What, class... _With>
125 auto __for_each_completion_signature_fn(_ERROR_<_What, _With...>**)
126     -> _ERROR_<_What, _With...>;
127 
128 template <template <class...> class _Tuple, template <class...> class _Variant,
129           class... _More, class... _Sigs>
130 auto __for_each_completion_signature_fn(completion_signatures<_Sigs...>**)
131     -> _Variant<__for_each_sig_t<_Sigs, _Tuple>..., _More...>;
132 } // namespace __sigs
133 
134 template <class _Sigs, template <class...> class _Tuple,
135           template <class...> class _Variant, class... _More>
136 using __for_each_completion_signature =
137     decltype(__sigs::__for_each_completion_signature_fn<
138              _Tuple, _Variant, _More...>(static_cast<_Sigs**>(nullptr)));
139 
140 namespace __sigs
141 {
142 ////////////////////////////////////////////////////////////////////////////////////////////////
143 template <template <class...> class _SetVal, template <class...> class _SetErr,
144           class _SetStp, class... _Values>
145 auto __transform_sig(set_value_t (*)(_Values...)) -> _SetVal<_Values...>;
146 
147 template <template <class...> class _SetVal, template <class...> class _SetErr,
148           class _SetStp, class _Error>
149 auto __transform_sig(set_error_t (*)(_Error)) -> _SetErr<_Error>;
150 
151 template <template <class...> class _SetVal, template <class...> class _SetErr,
152           class _SetStp>
153 auto __transform_sig(set_stopped_t (*)()) -> _SetStp;
154 
155 template <class _Sig, template <class...> class _SetVal,
156           template <class...> class _SetErr, class _SetStp>
157 using __transform_sig_t =
158     decltype(__sigs::__transform_sig<_SetVal, _SetErr, _SetStp>(
159         static_cast<_Sig*>(nullptr)));
160 
161 template <template <class...> class _SetVal, template <class...> class _SetErr,
162           class _SetStp, template <class...> class _Variant, class... _More,
163           class _What, class... _With>
164 auto __transform_sigs_fn(_ERROR_<_What, _With...>**)
165     -> _ERROR_<_What, _With...>;
166 
167 template <template <class...> class _SetVal, template <class...> class _SetErr,
168           class _SetStp, template <class...> class _Variant, class... _More,
169           class... _Sigs>
170 auto __transform_sigs_fn(completion_signatures<_Sigs...>**) //
171     -> _Variant<__transform_sig_t<_Sigs, _SetVal, _SetErr, _SetStp>...,
172                 _More...>;
173 } // namespace __sigs
174 
175 template <class _Sigs, template <class...> class _SetVal,
176           template <class...> class _SetErr, class _SetStp,
177           template <class...> class _Variant,
178           class... _More>
179 using __transform_completion_signatures = //
180     decltype(__sigs::__transform_sigs_fn<_SetVal, _SetErr, _SetStp, _Variant,
181                                          _More...>(
182         static_cast<_Sigs**>(nullptr)));
183 
184 namespace __sigs
185 {
186 ////////////////////////////////////////////////////////////////////////////////////////////////
187 template <class _WantedTag>
188 struct __gather_sigs_fn;
189 
190 template <>
191 struct __gather_sigs_fn<set_value_t>
192 {
193     template <class _Sigs, template <class...> class _Then,
194               template <class...> class _Else,
195               template <class...> class _Variant, class... _More>
196     using __f = __transform_completion_signatures<
197         _Sigs, _Then, __mbind_front_q<_Else, set_error_t>::template __f,
198         _Else<set_stopped_t>, _Variant, _More...>;
199 };
200 
201 template <>
202 struct __gather_sigs_fn<set_error_t>
203 {
204     template <class _Sigs, template <class...> class _Then,
205               template <class...> class _Else,
206               template <class...> class _Variant, class... _More>
207     using __f = __transform_completion_signatures<
208         _Sigs, __mbind_front_q<_Else, set_value_t>::template __f, _Then,
209         _Else<set_stopped_t>, _Variant, _More...>;
210 };
211 
212 template <>
213 struct __gather_sigs_fn<set_stopped_t>
214 {
215     template <class _Sigs, template <class...> class _Then,
216               template <class...> class _Else,
217               template <class...> class _Variant, class... _More>
218     using __f = __transform_completion_signatures<
219         _Sigs, __mbind_front_q<_Else, set_value_t>::template __f,
220         __mbind_front_q<_Else, set_error_t>::template __f, _Then<>, _Variant,
221         _More...>;
222 };
223 
224 template <class... _Values>
225 using __default_set_value = completion_signatures<set_value_t(_Values...)>;
226 
227 template <class... _Error>
228 using __default_set_error = completion_signatures<set_error_t(_Error...)>;
229 
230 template <class _Tag, class... _Args>
231 using __default_completion = completion_signatures<_Tag(_Args...)>;
232 } // namespace __sigs
233 
234 template <class _Sigs, class _WantedTag, template <class...> class _Then,
235           template <class...> class _Else, template <class...> class _Variant,
236           class... _More>
237 using __gather_completion_signatures = typename __sigs::__gather_sigs_fn<
238     _WantedTag>::template __f<_Sigs, _Then, _Else, _Variant, _More...>;
239 
240 /////////////////////////////////////////////////////////////////////////////
241 // transform_completion_signatures
242 // ==========================
243 //
244 // `transform_completion_signatures` takes a sender, and environment, and a
245 // bunch of other template arguments for munging the completion signatures of a
246 // sender in interesting ways.
247 //
248 //  ```c++
249 //  template <class... Args>
250 //    using __default_set_value = completion_signatures<set_value_t(Args...)>;
251 //
252 //  template <class Err>
253 //    using __default_set_error = completion_signatures<set_error_t(Err)>;
254 //
255 //  template <
256 //    class Completions,
257 //    class AdditionalSigs = completion_signatures<>,
258 //    template <class...> class SetValue = __default_set_value,
259 //    template <class> class SetError = __default_set_error,
260 //    class SetStopped = completion_signatures<set_stopped_t()>>
261 //  using transform_completion_signatures =
262 //    completion_signatures< ... >;
263 //  ```
264 //
265 //  * `SetValue` : an alias template that accepts a set of value types and
266 //  returns an instance of
267 //    `completion_signatures`.
268 //
269 //  * `SetError` : an alias template that accepts an error types and returns a
270 //  an instance of
271 //    `completion_signatures`.
272 //
273 //  * `SetStopped` : an instantiation of `completion_signatures` with a list of
274 //  completion
275 //    signatures `Sigs...` to the added to the list if the sender can complete
276 //    with a stopped signal.
277 //
278 //  * `AdditionalSigs` : an instantiation of `completion_signatures` with a list
279 //  of completion
280 //    signatures `Sigs...` to the added to the list unconditionally.
281 //
282 //  `transform_completion_signatures` does the following:
283 //
284 //  * Let `VCs...` be a pack of the `completion_signatures` types in the
285 //  `__typelist` named by
286 //    `value_types_of_t<Sndr, Env, SetValue, __typelist>`, and let `Vs...` be
287 //    the concatenation of the packs that are template arguments to each
288 //    `completion_signature` in `VCs...`.
289 //
290 //  * Let `ECs...` be a pack of the `completion_signatures` types in the
291 //  `__typelist` named by
292 //    `error_types_of_t<Sndr, Env, __errorlist>`, where `__errorlist` is an
293 //    alias template such that `__errorlist<Ts...>` names
294 //    `__typelist<SetError<Ts>...>`, and let `Es...` be the concatenation of the
295 //    packs that are the template arguments to each `completion_signature` in
296 //    `ECs...`.
297 //
298 //  * Let `Ss...` be an empty pack if `sends_stopped<Sndr, Env>` is `false`;
299 //  otherwise, a pack
300 //    containing the template arguments of the `completion_signatures`
301 //    instantiation named by `SetStopped`.
302 //
303 //  * Let `MoreSigs...` be a pack of the template arguments of the
304 //  `completion_signatures`
305 //    instantiation named by `AdditionalSigs`.
306 //
307 //  Then `transform_completion_signatures<Completions, AdditionalSigs, SetValue,
308 //  SetError, SendsStopped>` names the type `completion_signatures< Sigs... >`
309 //  where `Sigs...` is the unique set of types in `[Vs..., Es..., Ss...,
310 //  MoreSigs...]`.
311 //
312 //  If any of the above type computations are ill-formed,
313 //  `transform_completion_signatures<Sndr, Env, AdditionalSigs, SetValue,
314 //  SetError, SendsStopped>` is ill-formed.
315 template <
316     class _Sigs, class _MoreSigs = completion_signatures<>,
317     template <class...> class _ValueTransform = __sigs::__default_set_value,
318     template <class...> class _ErrorTransform = __sigs::__default_set_error,
319     class _StoppedSigs = completion_signatures<set_stopped_t()>>
320 using transform_completion_signatures = //
321     __transform_completion_signatures<
322         _Sigs, _ValueTransform, _ErrorTransform, _StoppedSigs,
323         __mtry_q<__concat_completion_signatures>::__f, _MoreSigs>;
324 
325 template <
326     class _Sndr, class _Env = empty_env,
327     class _MoreSigs = completion_signatures<>,
328     template <class...> class _ValueTransform = __sigs::__default_set_value,
329     template <class...> class _ErrorTransform = __sigs::__default_set_error,
330     class _StoppedSigs = completion_signatures<set_stopped_t()>>
331 using transform_completion_signatures_of = //
332     transform_completion_signatures<completion_signatures_of_t<_Sndr, _Env>,
333                                     _MoreSigs, _ValueTransform, _ErrorTransform,
334                                     _StoppedSigs>;
335 
336 using __eptr_completion =
337     completion_signatures<set_error_t(std::exception_ptr)>;
338 
339 template <class _NoExcept>
340 using __eptr_completion_if_t =
341     __if<_NoExcept, completion_signatures<>, __eptr_completion>;
342 
343 template <bool _NoExcept>
344 using __eptr_completion_if = __eptr_completion_if_t<__mbool<_NoExcept>>;
345 
346 template <                                                      //
347     class _Sender,                                              //
348     class _Env = empty_env,                                     //
349     class _More = completion_signatures<>,                      //
350     class _SetValue = __qq<__sigs::__default_set_value>,        //
351     class _SetError = __qq<__sigs::__default_set_error>,        //
352     class _SetStopped = completion_signatures<set_stopped_t()>> //
353 using __try_make_completion_signatures =                        //
354     __transform_completion_signatures<
355         __completion_signatures_of_t<_Sender, _Env>, _SetValue::template __f,
356         _SetError::template __f, _SetStopped,
357         __mtry_q<__concat_completion_signatures>::__f, _More>;
358 
359 template <class _SetTag, class _Completions, class _Tuple,
360           class _Variant>
361 using __gather_completions = //
362     __gather_completion_signatures<
363         _Completions, _SetTag,
364         __mcompose_q<__types, _Tuple::template __f>::template __f,
365         __mconst<__types<>>::__f, __mconcat<_Variant>::template __f>;
366 
367 template <class _SetTag, class _Sender, class _Env, class _Tuple,
368           class _Variant>
369 using __gather_completions_of = //
370     __gather_completions<_SetTag, __completion_signatures_of_t<_Sender, _Env>,
371                          _Tuple, _Variant>;
372 
373 template <                                                             //
374     class _Sender,                                                     //
375     class _Env = empty_env,                                            //
376     class _Sigs = completion_signatures<>,                             //
377     template <class...> class _SetValue = __sigs::__default_set_value, //
378     template <class...> class _SetError = __sigs::__default_set_error, //
379     class _SetStopped = completion_signatures<set_stopped_t()>>
380 using make_completion_signatures =
381     transform_completion_signatures_of<_Sender, _Env, _Sigs, _SetValue,
382                                        _SetError, _SetStopped>;
383 
384 template <                                   //
385     class _Sigs,                             //
386     class _Tuple = __q<__decayed_std_tuple>, //
387     class _Variant = __q<__std_variant>>
388 using __value_types_t =                      //
389     __gather_completions<set_value_t, _Sigs, _Tuple, _Variant>;
390 
391 template <                                   //
392     class _Sender,                           //
393     class _Env = empty_env,                  //
394     class _Tuple = __q<__decayed_std_tuple>, //
395     class _Variant = __q<__std_variant>>
396 using __value_types_of_t =                   //
397     __value_types_t<__completion_signatures_of_t<_Sender, _Env>, _Tuple,
398                     _Variant>;
399 
400 template <class _Sigs, class _Variant = __q<__std_variant>>
401 using __error_types_t =
402     __gather_completions<set_error_t, _Sigs, __q<__midentity>, _Variant>;
403 
404 template <class _Sender, class _Env = empty_env,
405           class _Variant = __q<__std_variant>>
406 using __error_types_of_t =
407     __error_types_t<__completion_signatures_of_t<_Sender, _Env>, _Variant>;
408 
409 template <                                                  //
410     class _Sender,                                          //
411     class _Env = empty_env,                                 //
412     template <class...> class _Tuple = __decayed_std_tuple, //
413     template <class...> class _Variant = __std_variant>
414 using value_types_of_t =
415     __value_types_of_t<_Sender, _Env, __q<_Tuple>, __q<_Variant>>;
416 
417 template <class _Sender, class _Env = empty_env,
418           template <class...> class _Variant = __std_variant>
419 using error_types_of_t = __error_types_of_t<_Sender, _Env, __q<_Variant>>;
420 
421 template <class _Tag, class _Sender, class... _Env>
422 using __count_of = //
423     __gather_completion_signatures<
424         __completion_signatures_of_t<_Sender, _Env...>, _Tag,
425         __mconst<__msize_t<1>>::__f, __mconst<__msize_t<0>>::__f, __mplus_t>;
426 
427 template <class _Tag, class _Sender, class... _Env>
428     requires sender_in<_Sender, _Env...>
429 inline constexpr bool __sends = //
430     __v<__gather_completion_signatures<
431         __completion_signatures_of_t<_Sender, _Env...>, _Tag,
432         __mconst<__mtrue>::__f, __mconst<__mfalse>::__f, __mor_t>>;
433 
434 template <class _Sender, class... _Env>
435 concept sends_stopped = //
436     sender_in<_Sender, _Env...> && __sends<set_stopped_t, _Sender, _Env...>;
437 
438 template <class _Sender, class... _Env>
439 using __single_sender_value_t =
440     __value_types_t<__completion_signatures_of_t<_Sender, _Env...>,
441                     __msingle_or<void>, __q<__msingle>>;
442 
443 template <class _Sender, class... _Env>
444 concept __single_value_sender =    //
445     sender_in<_Sender, _Env...> && //
446     requires { typename __single_sender_value_t<_Sender, _Env...>; };
447 
448 template <class _Sender, class... _Env>
449 using __single_value_variant_sender_t =
450     __value_types_t<__completion_signatures_of_t<_Sender, _Env...>,
451                     __qq<__types>, __q<__msingle>>;
452 
453 template <class _Sender, class... _Env>
454 concept __single_value_variant_sender = //
455     sender_in<_Sender, _Env...> &&      //
456     requires { typename __single_value_variant_sender_t<_Sender, _Env...>; };
457 
458 // The following utilities are needed fairly often:
459 template <class _Fun, class... _Args>
460     requires __invocable<_Fun, _Args...>
461 using __nothrow_invocable_t = __mbool<__nothrow_invocable<_Fun, _Args...>>;
462 
463 template <class _Catch, class _Tag, class _Fun, class _Sender, class... _Env>
464 using __with_error_invoke_t = //
465     __if<__gather_completion_signatures<
466              __completion_signatures_of_t<_Sender, _Env...>, _Tag,
467              __mbind_front<__mtry_catch_q<__nothrow_invocable_t, _Catch>,
468                            _Fun>::template __f,
469              __mconst<__mbool<true>>::__f, __mand>,
470          completion_signatures<>, __eptr_completion>;
471 
472 template <class _Fun, class... _Args>
473     requires __invocable<_Fun, _Args...>
474 using __set_value_invoke_t = //
475     completion_signatures<__minvoke<__mremove<void, __qf<set_value_t>>,
476                                     __invoke_result_t<_Fun, _Args...>>>;
477 } // namespace stdexec
478