xref: /openbmc/sdbusplus/include/sdbusplus/async/stdexec/__detail/__ensure_started.hpp (revision 10d0b4b7d1498cfd5c3d37edea271a54d1984e41)
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