xref: /openbmc/sdbusplus/include/sdbusplus/async/stdexec/__detail/__split.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.split]
33   namespace __split {
34     using namespace __shared;
35 
36     struct __split_t { };
37 
38     struct split_t {
39       template <sender _Sender, class _Env = env<>>
40         requires sender_in<_Sender, _Env> && __decay_copyable<env_of_t<_Sender>>
operator ()stdexec::__split::split_t41       auto operator()(_Sender&& __sndr, _Env&& __env = {}) const -> __well_formed_sender auto {
42         auto __domain = __get_late_domain(__sndr, __env, __get_early_domain(__sndr));
43         return stdexec::transform_sender(
44           __domain,
45           __make_sexpr<split_t>(static_cast<_Env&&>(__env), static_cast<_Sender&&>(__sndr)));
46       }
47 
STDEXEC_ATTRIBUTEstdexec::__split::split_t48       STDEXEC_ATTRIBUTE(always_inline)
49       auto operator()() const noexcept -> __binder_back<split_t> {
50         return {{}, {}, {}};
51       }
52 
53       template <class _CvrefSender, class _Env>
54       using __receiver_t = __t<__meval<__receiver, __cvref_id<_CvrefSender>, __id<_Env>>>;
55 
56       template <class _Sender>
transform_senderstdexec::__split::split_t57       static auto transform_sender(_Sender&& __sndr) {
58         using _Receiver = __receiver_t<__child_of<_Sender>, __decay_t<__data_of<_Sender>>>;
59         static_assert(sender_to<__child_of<_Sender>, _Receiver>);
60 
61         return __sexpr_apply(
62           static_cast<_Sender&&>(__sndr),
63           [&]<class _Env, class _Child>(__ignore, _Env&& __env, _Child&& __child) {
64             // The shared state starts life with a ref-count of one.
65             auto* __sh_state =
66               new __shared_state{static_cast<_Child&&>(__child), static_cast<_Env&&>(__env)};
67 
68             return __make_sexpr<__split_t>(__box{__split_t(), __sh_state});
69           });
70       }
71     };
72   } // namespace __split
73 
74   using __split::split_t;
75   inline constexpr split_t split{};
76 
77   template <>
78   struct __sexpr_impl<__split::__split_t> : __shared::__shared_impl<__split::__split_t> { };
79 
80   template <>
81   struct __sexpr_impl<split_t> : __sexpr_defaults {
82     static constexpr auto get_completion_signatures = []<class _Sender>(_Sender&&) noexcept
83       -> __completion_signatures_of_t<transform_sender_result_t<default_domain, _Sender, env<>>> {
84     };
85   };
86 } // namespace stdexec
87