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 "__basic_sender.hpp" 22 #include "__concepts.hpp" 23 #include "__intrusive_ptr.hpp" 24 #include "__meta.hpp" 25 #include "__sender_adaptor_closure.hpp" 26 #include "__senders.hpp" 27 #include "__shared.hpp" 28 #include "__transform_sender.hpp" 29 #include "__type_traits.hpp" 30 31 #include <utility> 32 33 namespace stdexec 34 { 35 ///////////////////////////////////////////////////////////////////////////// 36 // [execution.senders.adaptors.ensure_started] 37 namespace __ensure_started 38 { 39 using namespace __shared; 40 41 struct __ensure_started_t 42 {}; 43 44 struct ensure_started_t 45 { 46 template <sender _Sender, class _Env = empty_env> 47 requires sender_in<_Sender, _Env> && __decay_copyable<env_of_t<_Sender>> operator ()stdexec::__ensure_started::ensure_started_t48 [[nodiscard]] auto operator()(_Sender&& __sndr, _Env&& __env = {}) const 49 -> __well_formed_sender auto 50 { 51 if constexpr (sender_expr_for<_Sender, __ensure_started_t>) 52 { 53 return static_cast<_Sender&&>(__sndr); 54 } 55 else 56 { 57 auto __domain = __get_late_domain(__sndr, __env); 58 return stdexec::transform_sender( 59 __domain, 60 __make_sexpr<ensure_started_t>(static_cast<_Env&&>(__env), 61 static_cast<_Sender&&>(__sndr))); 62 } 63 } 64 65 STDEXEC_ATTRIBUTE((always_inline)) operator ()stdexec::__ensure_started::ensure_started_t66 auto operator()() const noexcept -> __binder_back<ensure_started_t> 67 { 68 return {{}, {}, {}}; 69 } 70 71 using _Sender = __1; 72 using __legacy_customizations_t = // 73 __types<tag_invoke_t(ensure_started_t, 74 get_completion_scheduler_t<set_value_t>( 75 get_env_t(const _Sender&)), 76 _Sender), 77 tag_invoke_t(ensure_started_t, _Sender)>; 78 79 template <class _CvrefSender, class _Env> 80 using __receiver_t = 81 __t<__meval<__receiver, __cvref_id<_CvrefSender>, __id<_Env>>>; 82 83 template <class _Sender> transform_senderstdexec::__ensure_started::ensure_started_t84 static auto transform_sender(_Sender&& __sndr) 85 { 86 using _Receiver = 87 __receiver_t<__child_of<_Sender>, __decay_t<__data_of<_Sender>>>; 88 static_assert(sender_to<__child_of<_Sender>, _Receiver>); 89 90 return __sexpr_apply( 91 static_cast<_Sender&&>(__sndr), 92 [&]<class _Env, class _Child>(__ignore, _Env&& __env, 93 _Child&& __child) { 94 // The shared state starts life with a ref-count of one. 95 auto __sh_state = 96 __make_intrusive<__shared_state<_Child, __decay_t<_Env>>, 97 2>(static_cast<_Child&&>(__child), 98 static_cast<_Env&&>(__env)); 99 100 // Eagerly start the work: 101 __sh_state->__try_start(); 102 103 return __make_sexpr<__ensure_started_t>( 104 __box{__ensure_started_t(), std::move(__sh_state)}); 105 }); 106 } 107 }; 108 } // namespace __ensure_started 109 110 using __ensure_started::ensure_started_t; 111 inline constexpr ensure_started_t ensure_started{}; 112 113 template <> 114 struct __sexpr_impl<__ensure_started::__ensure_started_t> : 115 __shared::__shared_impl<__ensure_started::__ensure_started_t> 116 {}; 117 118 template <> 119 struct __sexpr_impl<ensure_started_t> : __sexpr_defaults 120 { 121 static constexpr auto get_completion_signatures = // 122 []<class _Sender>(_Sender&&) noexcept // 123 -> __completion_signatures_of_t< // 124 transform_sender_result_t<default_domain, _Sender, empty_env>> {}; 125 }; 126 } // namespace stdexec 127