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 "__meta.hpp" 24 #include "__sender_adaptor_closure.hpp" 25 #include "__senders.hpp" 26 #include "__shared.hpp" 27 #include "__transform_sender.hpp" 28 #include "__type_traits.hpp" 29 30 namespace stdexec { 31 ///////////////////////////////////////////////////////////////////////////// 32 // [execution.senders.adaptors.ensure_started] 33 namespace __ensure_started { 34 using namespace __shared; 35 36 struct __ensure_started_t { }; 37 38 struct ensure_started_t { 39 template <sender _Sender, class _Env = env<>> 40 requires sender_in<_Sender, _Env> && __decay_copyable<env_of_t<_Sender>> 41 [[nodiscard]] operator ()stdexec::__ensure_started::ensure_started_t42 auto operator()(_Sender&& __sndr, _Env&& __env = {}) const -> __well_formed_sender auto { 43 if constexpr (sender_expr_for<_Sender, __ensure_started_t>) { 44 return static_cast<_Sender&&>(__sndr); 45 } else { 46 auto __early_domain = __get_early_domain(__sndr); 47 auto __domain = __get_late_domain(__sndr, __env, __early_domain); 48 return stdexec::transform_sender( 49 __domain, 50 __make_sexpr<ensure_started_t>( 51 static_cast<_Env&&>(__env), static_cast<_Sender&&>(__sndr))); 52 } 53 } 54 STDEXEC_ATTRIBUTEstdexec::__ensure_started::ensure_started_t55 STDEXEC_ATTRIBUTE(always_inline) 56 auto operator()() const noexcept -> __binder_back<ensure_started_t> { 57 return {{}, {}, {}}; 58 } 59 60 template <class _CvrefSender, class _Env> 61 using __receiver_t = __t<__meval<__receiver, __cvref_id<_CvrefSender>, __id<_Env>>>; 62 63 template <class _Sender> transform_senderstdexec::__ensure_started::ensure_started_t64 static auto transform_sender(_Sender&& __sndr) { 65 using _Receiver = __receiver_t<__child_of<_Sender>, __decay_t<__data_of<_Sender>>>; 66 static_assert(sender_to<__child_of<_Sender>, _Receiver>); 67 68 return __sexpr_apply( 69 static_cast<_Sender&&>(__sndr), 70 [&]<class _Env, class _Child>(__ignore, _Env&& __env, _Child&& __child) { 71 // The shared state starts life with a ref-count of one. 72 auto* __sh_state = 73 new __shared_state{static_cast<_Child&&>(__child), static_cast<_Env&&>(__env)}; 74 75 // Eagerly start the work: 76 __sh_state->__try_start(); // cannot throw 77 78 return __make_sexpr<__ensure_started_t>(__box{__ensure_started_t(), __sh_state}); 79 }); 80 } 81 }; 82 } // namespace __ensure_started 83 84 using __ensure_started::ensure_started_t; 85 inline constexpr ensure_started_t ensure_started{}; 86 87 template <> 88 struct __sexpr_impl<__ensure_started::__ensure_started_t> 89 : __shared::__shared_impl<__ensure_started::__ensure_started_t> { }; 90 91 template <> 92 struct __sexpr_impl<ensure_started_t> : __sexpr_defaults { 93 static constexpr auto get_completion_signatures = []<class _Sender>(_Sender&&) noexcept 94 -> __completion_signatures_of_t<transform_sender_result_t<default_domain, _Sender, env<>>> { 95 }; 96 }; 97 } // namespace stdexec 98