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