xref: /openbmc/sdbusplus/include/sdbusplus/async/stdexec/env.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 "../stdexec/execution.hpp"
19 
20 STDEXEC_PRAGMA_PUSH()
21 STDEXEC_PRAGMA_IGNORE_EDG(1302)
22 
23 namespace exec {
24   template <class _Tag, class _Value>
25   using with_t = stdexec::prop<_Tag, _Value>;
26 
27   namespace __envs {
28     struct __with_t {
29       template <class _Tag, class _Value>
operator ()exec::__envs::__with_t30       constexpr auto operator()(_Tag, _Value&& __val) const {
31         return stdexec::prop{_Tag(), static_cast<_Value&&>(__val)};
32       }
33     };
34 
35     struct __without_t {
36       template <class _Env, class _Tag>
operator ()exec::__envs::__without_t37       constexpr auto operator()(_Env&& __env, _Tag) const -> decltype(auto) {
38         return stdexec::__env::__without(static_cast<_Env&&>(__env), _Tag());
39       }
40     };
41 
42     // For making an environment from key/value pairs and optionally
43     // another environment.
44     struct __make_env_t {
45       template <
46         stdexec::__nothrow_move_constructible _Base,
47         stdexec::__nothrow_move_constructible _Env
48       >
operator ()exec::__envs::__make_env_t49       constexpr auto operator()(_Base&& __base, _Env&& __env) const noexcept
50         -> stdexec::__join_env_t<_Env, _Base> {
51         return stdexec::__env::__join(static_cast<_Env&&>(__env), static_cast<_Base&&>(__base));
52       }
53 
54       template <stdexec::__nothrow_move_constructible _Env>
operator ()exec::__envs::__make_env_t55       constexpr auto operator()(_Env&& __env) const noexcept -> _Env {
56         return static_cast<_Env&&>(__env);
57       }
58     };
59   } // namespace __envs
60 
61   inline constexpr __envs::__with_t with{};
62   inline constexpr __envs::__without_t without{};
63   inline constexpr __envs::__make_env_t make_env{};
64 
65   template <class... _Ts>
66   using make_env_t = stdexec::__result_of<make_env, _Ts...>;
67 
68   namespace __read_with_default {
69     using namespace stdexec;
70 
71     struct read_with_default_t;
72 
73     template <class _Tag, class _DefaultId, class _ReceiverId>
74     struct __operation {
75       using _Default = stdexec::__t<_DefaultId>;
76       using _Receiver = stdexec::__t<_ReceiverId>;
77 
78       struct __t : __immovable {
79         using __id = __operation;
80 
81         STDEXEC_ATTRIBUTE(no_unique_address) _Default __default_;
82         _Receiver __rcvr_;
83 
startexec::__read_with_default::__operation::__t84         constexpr void start() & noexcept {
85           STDEXEC_TRY {
86             if constexpr (__callable<_Tag, env_of_t<_Receiver>>) {
87               const auto& __env = get_env(__rcvr_);
88               stdexec::set_value(std::move(__rcvr_), _Tag{}(__env));
89             } else {
90               stdexec::set_value(std::move(__rcvr_), std::move(__default_));
91             }
92           }
93           STDEXEC_CATCH_ALL {
94             stdexec::set_error(std::move(__rcvr_), std::current_exception());
95           }
96         }
97       };
98     };
99 
100     template <class _Tag, class _Default, class _Receiver>
101     using __operation_t = __t<__operation<_Tag, __id<_Default>, __id<_Receiver>>>;
102 
103     template <class _Tag, class _Default>
104     struct __sender {
105       using __id = __sender;
106       using __t = __sender;
107       using sender_concept = stdexec::sender_t;
108       STDEXEC_ATTRIBUTE(no_unique_address) _Default __default_;
109 
110       template <class _Env>
111       using __value_t =
112         __minvoke<__with_default<__mbind_back_q<__call_result_t, _Env>, _Default>, _Tag>;
113       template <class _Env>
114       using __default_t = __if_c<__callable<_Tag, _Env>, __ignore, _Default>;
115 
116       template <class _Env>
117       using __completions_t =
118         completion_signatures<set_value_t(__value_t<_Env>), set_error_t(std::exception_ptr)>;
119 
120       template <__decays_to<__sender> _Self, class _Receiver>
121         requires receiver_of<_Receiver, __completions_t<env_of_t<_Receiver>>>
connectexec::__read_with_default::__sender122       static constexpr auto connect(_Self&& __self, _Receiver __rcvr)
123         noexcept(std::is_nothrow_move_constructible_v<_Receiver>)
124           -> __operation_t<_Tag, __default_t<env_of_t<_Receiver>>, _Receiver> {
125         return {{}, static_cast<_Self&&>(__self).__default_, static_cast<_Receiver&&>(__rcvr)};
126       }
127 
128       template <class _Env>
get_completion_signaturesexec::__read_with_default::__sender129       constexpr auto get_completion_signatures(_Env&&) -> __completions_t<_Env> {
130         return {};
131       }
132     };
133 
134     struct __read_with_default_t {
135       template <class _Tag, class _Default>
136       constexpr auto
operator ()exec::__read_with_default::__read_with_default_t137         operator()(_Tag, _Default&& __default) const -> __sender<_Tag, __decay_t<_Default>> {
138         return {static_cast<_Default&&>(__default)};
139       }
140     };
141   } // namespace __read_with_default
142 
143   inline constexpr __read_with_default::__read_with_default_t read_with_default{};
144 
145   [[deprecated("exec::write has been renamed to stdexec::write_env")]]
146   inline constexpr stdexec::__write::write_env_t write{};
147   [[deprecated("write_env has been moved to the stdexec:: namespace")]]
148   inline constexpr stdexec::__write::write_env_t write_env{};
149 
150   namespace __write_attrs {
151     using namespace stdexec;
152 
153     template <class _SenderId, class _Attrs>
154     struct __sender {
155       using _Sender = stdexec::__t<_SenderId>;
156 
157       struct __t {
158         using sender_concept = sender_t;
159         using __id = __sender;
160         _Sender __sndr_;
161         _Attrs __attrs_;
162 
get_envexec::__write_attrs::__sender::__t163         constexpr auto get_env() const noexcept -> __join_env_t<const _Attrs&, env_of_t<_Sender>> {
164           return stdexec::__env::__join(__attrs_, stdexec::get_env(__sndr_));
165         }
166 
167         template <__decays_to<__t> _Self, class... _Env>
get_completion_signaturesexec::__write_attrs::__sender::__t168         static constexpr auto get_completion_signatures(_Self&&, _Env&&...)
169           -> completion_signatures_of_t<__copy_cvref_t<_Self, _Sender>, _Env...> {
170           return {};
171         }
172 
173         template <__decays_to<__t> _Self, class _Receiver>
174           requires sender_in<__copy_cvref_t<_Self, _Sender>, env_of_t<_Receiver>>
connectexec::__write_attrs::__sender::__t175         static constexpr auto connect(_Self&& __self, _Receiver __rcvr)
176           -> connect_result_t<__copy_cvref_t<_Self, _Sender>, _Receiver> {
177           return stdexec::connect(std::forward<_Self>(__self).__sndr_, std::move(__rcvr));
178         }
179       };
180     };
181 
182     struct __write_attrs_t {
183       template <class _Sender, class _Attrs>
STDEXEC_ATTRIBUTEexec::__write_attrs::__write_attrs_t184       STDEXEC_ATTRIBUTE(host, device)
185       constexpr auto
186         operator()(_Sender snd, _Attrs __attrs_) const -> __write_attrs::__sender<_Sender, _Attrs> {
187         return __t<__write_attrs::__sender<__id<_Sender>, _Attrs>>{
188           static_cast<_Sender&&>(snd), static_cast<_Attrs&&>(__attrs_)};
189       }
190 
191       template <class _Attrs>
192       struct __closure {
193         _Attrs __attrs_;
194 
195         template <class _Sender>
196         STDEXEC_ATTRIBUTE(host, device)
197         friend constexpr auto operator|(_Sender __sndr_, __closure _clsr) {
198           return __t<__write_attrs::__sender<__id<_Sender>, _Attrs>>{
199             static_cast<_Sender&&>(__sndr_), static_cast<_Attrs&&>(_clsr.__attrs_)};
200         }
201       };
202 
203       template <class _Attrs>
STDEXEC_ATTRIBUTEexec::__write_attrs::__write_attrs_t204       STDEXEC_ATTRIBUTE(host, device)
205       constexpr auto operator()(_Attrs __attrs_) const {
206         return __closure<_Attrs>{static_cast<_Attrs&&>(__attrs_)};
207       }
208     };
209   } // namespace __write_attrs
210 
211   inline constexpr __write_attrs::__write_attrs_t write_attrs{};
212 
213 } // namespace exec
214 
215 STDEXEC_PRAGMA_POP()
216