xref: /openbmc/sdbusplus/include/sdbusplus/async/stdexec/__detail/__stopped_as_optional.hpp (revision 5cee91570368554a7fcbbd9418f65efda449fa70)
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 "__completion_signatures.hpp"
23 #include "__concepts.hpp"
24 #include "__env.hpp"
25 #include "__receivers.hpp"
26 #include "__sender_adaptor_closure.hpp"
27 #include "__senders_core.hpp"
28 #include "__transform_completion_signatures.hpp"
29 #include "__type_traits.hpp"
30 
31 #include <exception>
32 #include <optional>
33 
34 namespace stdexec
35 {
36 /////////////////////////////////////////////////////////////////////////////
37 // [execution.senders.adaptors.stopped_as_optional]
38 namespace __sao
39 {
40 struct stopped_as_optional_t
41 {
42     template <sender _Sender>
operator ()stdexec::__sao::stopped_as_optional_t43     auto operator()(_Sender&& __sndr) const
44     {
45         return __make_sexpr<stopped_as_optional_t>(
46             __(), static_cast<_Sender&&>(__sndr));
47     }
48 
49     STDEXEC_ATTRIBUTE((always_inline))
operator ()stdexec::__sao::stopped_as_optional_t50     auto operator()() const noexcept -> __binder_back<stopped_as_optional_t>
51     {
52         return {{}, {}, {}};
53     }
54 };
55 
56 struct __stopped_as_optional_impl : __sexpr_defaults
57 {
58     template <class... _Tys>
59         requires(sizeof...(_Tys) == 1)
60     using __set_value_t =
61         completion_signatures<set_value_t(std::optional<__decay_t<_Tys>>...)>;
62 
63     template <class _Ty>
64     using __set_error_t = completion_signatures<set_error_t(_Ty)>;
65 
66     static constexpr auto get_completion_signatures =               //
67         []<class _Self, class... _Env>(_Self&&, _Env&&...) noexcept //
68         -> transform_completion_signatures<
69             __completion_signatures_of_t<__child_of<_Self>, _Env...>,
70             completion_signatures<set_error_t(std::exception_ptr)>,
71             __set_value_t, __set_error_t, completion_signatures<>> {
72         static_assert(sender_expr_for<_Self, stopped_as_optional_t>);
73         return {};
74     };
75 
76     static constexpr auto get_state = //
77         []<class _Self, class _Receiver>(_Self&&, _Receiver&) noexcept
78         requires __single_value_sender<__child_of<_Self>, env_of_t<_Receiver>>
79     {
80         static_assert(sender_expr_for<_Self, stopped_as_optional_t>);
81         using _Value = __decay_t<
82             __single_sender_value_t<__child_of<_Self>, env_of_t<_Receiver>>>;
83         return __mtype<_Value>();
84     };
85 
86     static constexpr auto complete = //
87         []<class _State, class _Receiver, class _Tag, class... _Args>(
88             __ignore, _State&, _Receiver& __rcvr, _Tag,
89             _Args&&... __args) noexcept -> void {
90         if constexpr (__same_as<_Tag, set_value_t>)
91         {
92             try
93             {
94                 static_assert(constructible_from<__t<_State>, _Args...>);
95                 stdexec::set_value(static_cast<_Receiver&&>(__rcvr),
96                                    std::optional<__t<_State>>{
97                                        static_cast<_Args&&>(__args)...});
98             }
99             catch (...)
100             {
101                 stdexec::set_error(static_cast<_Receiver&&>(__rcvr),
102                                    std::current_exception());
103             }
104         }
105         else if constexpr (__same_as<_Tag, set_error_t>)
106         {
107             stdexec::set_error(static_cast<_Receiver&&>(__rcvr),
108                                static_cast<_Args&&>(__args)...);
109         }
110         else
111         {
112             stdexec::set_value(static_cast<_Receiver&&>(__rcvr),
113                                std::optional<__t<_State>>{std::nullopt});
114         }
115     };
116 };
117 } // namespace __sao
118 
119 using __sao::stopped_as_optional_t;
120 inline constexpr stopped_as_optional_t stopped_as_optional{};
121 
122 template <>
123 struct __sexpr_impl<stopped_as_optional_t> : __sao::__stopped_as_optional_impl
124 {};
125 } // namespace stdexec
126