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 "__concepts.hpp" 22 #include "__diagnostics.hpp" 23 #include "__domain.hpp" 24 #include "__env.hpp" 25 #include "__let.hpp" 26 #include "__meta.hpp" 27 #include "__schedulers.hpp" 28 #include "__senders_core.hpp" 29 #include "__tag_invoke.hpp" 30 #include "__transform_sender.hpp" 31 #include "__utility.hpp" 32 33 namespace stdexec 34 { 35 namespace __detail 36 { 37 //! Constant function object always returning `__val_`. 38 template <class _Ty, class = __name_of<__decay_t<_Ty>>> 39 struct __always 40 { 41 _Ty __val_; 42 operator ()stdexec::__detail::__always43 auto operator()() noexcept -> _Ty 44 { 45 return static_cast<_Ty&&>(__val_); 46 } 47 }; 48 49 template <class _Ty> 50 __always(_Ty) -> __always<_Ty>; 51 } // namespace __detail 52 53 ///////////////////////////////////////////////////////////////////////////// 54 // [execution.senders.adaptors.starts_on] 55 namespace __starts_on_ns 56 { 57 struct starts_on_t 58 { 59 using _Sender = __1; 60 using _Scheduler = __0; 61 using __legacy_customizations_t = 62 __types<tag_invoke_t(starts_on_t, _Scheduler, _Sender)>; 63 64 template <scheduler _Scheduler, sender _Sender> operator ()stdexec::__starts_on_ns::starts_on_t65 auto operator()(_Scheduler&& __sched, _Sender&& __sndr) const 66 -> __well_formed_sender auto 67 { 68 auto __domain = query_or(get_domain, __sched, default_domain()); 69 return stdexec::transform_sender( 70 __domain, 71 __make_sexpr<starts_on_t>(static_cast<_Scheduler&&>(__sched), 72 static_cast<_Sender&&>(__sndr))); 73 } 74 75 template <class _Env> 76 STDEXEC_ATTRIBUTE((always_inline)) __transform_env_fnstdexec::__starts_on_ns::starts_on_t77 static auto __transform_env_fn(_Env&& __env) noexcept 78 { 79 return [&](__ignore, auto __sched, __ignore) noexcept { 80 return __detail::__mkenv_sched(static_cast<_Env&&>(__env), __sched); 81 }; 82 } 83 84 template <class _Sender, class _Env> transform_envstdexec::__starts_on_ns::starts_on_t85 static auto transform_env(const _Sender& __sndr, _Env&& __env) noexcept 86 { 87 return __sexpr_apply(__sndr, 88 __transform_env_fn(static_cast<_Env&&>(__env))); 89 } 90 91 template <class _Sender, class _Env> transform_senderstdexec::__starts_on_ns::starts_on_t92 static auto transform_sender(_Sender&& __sndr, const _Env&) 93 { 94 return __sexpr_apply( 95 static_cast<_Sender&&>(__sndr), 96 []<class _Data, class _Child>(__ignore, _Data&& __data, 97 _Child&& __child) { 98 // This is the heart of starts_on: It uses `let_value` to 99 // schedule `__child` on the given scheduler: 100 return let_value( 101 schedule(__data), 102 __detail::__always{static_cast<_Child&&>(__child)}); 103 }); 104 } 105 }; 106 } // namespace __starts_on_ns 107 108 using __starts_on_ns::starts_on_t; 109 inline constexpr starts_on_t starts_on{}; 110 111 using on_t = starts_on_t; 112 inline constexpr starts_on_t on{}; 113 114 using start_on_t = starts_on_t; 115 inline constexpr starts_on_t start_on{}; 116 117 template <> 118 struct __sexpr_impl<starts_on_t> : __sexpr_defaults 119 { 120 static constexpr auto get_completion_signatures = // 121 []<class _Sender>(_Sender&&) noexcept // 122 -> __completion_signatures_of_t< // 123 transform_sender_result_t<default_domain, _Sender, empty_env>> { 124 return {}; 125 }; 126 }; 127 } // namespace stdexec 128