xref: /openbmc/sdbusplus/include/sdbusplus/async/stdexec/__detail/__upon_error.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 "__basic_sender.hpp"
19 #include "__diagnostics.hpp"
20 #include "__domain.hpp"
21 #include "__execution_fwd.hpp"
22 #include "__meta.hpp"
23 #include "__sender_adaptor_closure.hpp"
24 #include "__senders.hpp"
25 #include "__senders_core.hpp"
26 #include "__transform_completion_signatures.hpp"
27 #include "__transform_sender.hpp"
28 
29 // include these after __execution_fwd.hpp
30 namespace stdexec
31 {
32 /////////////////////////////////////////////////////////////////////////////
33 // [execution.senders.adaptors.upon_error]
34 namespace __upon_error
35 {
36 inline constexpr __mstring __upon_error_context =
37     "In stdexec::upon_error(Sender, Function)..."_mstr;
38 using __on_not_callable = __callable_error<__upon_error_context>;
39 
40 template <class _Fun, class _CvrefSender, class... _Env>
41 using __completion_signatures_t = //
42     transform_completion_signatures<
43         __completion_signatures_of_t<_CvrefSender, _Env...>,
44         __with_error_invoke_t<__on_not_callable, set_error_t, _Fun,
45                               _CvrefSender, _Env...>,
46         __sigs::__default_set_value,
47         __mbind_front<__mtry_catch_q<__set_value_invoke_t, __on_not_callable>,
48                       _Fun>::template __f>;
49 
50 ////////////////////////////////////////////////////////////////////////////////////////////////
51 struct upon_error_t
52 {
53     template <sender _Sender, __movable_value _Fun>
operator ()stdexec::__upon_error::upon_error_t54     auto operator()(_Sender&& __sndr, _Fun __fun) const -> __well_formed_sender
55         auto
56     {
57         auto __domain = __get_early_domain(__sndr);
58         return stdexec::transform_sender(
59             __domain,
60             __make_sexpr<upon_error_t>(static_cast<_Fun&&>(__fun),
61                                        static_cast<_Sender&&>(__sndr)));
62     }
63 
64     template <__movable_value _Fun>
65     STDEXEC_ATTRIBUTE((always_inline))
operator ()stdexec::__upon_error::upon_error_t66     auto operator()(_Fun __fun) const -> __binder_back<upon_error_t, _Fun>
67     {
68         return {{static_cast<_Fun&&>(__fun)}, {}, {}};
69     }
70 
71     using _Sender = __1;
72     using _Fun = __0;
73     using __legacy_customizations_t =
74         __types<tag_invoke_t(upon_error_t,
75                              get_completion_scheduler_t<set_value_t>(
76                                  get_env_t(_Sender&)),
77                              _Sender, _Fun),
78                 tag_invoke_t(upon_error_t, _Sender, _Fun)>;
79 };
80 
81 struct __upon_error_impl : __sexpr_defaults
82 {
83     static constexpr auto get_completion_signatures = //
84         []<class _Sender, class... _Env>(_Sender&&, _Env&&...) noexcept
85         -> __completion_signatures_t<__decay_t<__data_of<_Sender>>,
86                                      __child_of<_Sender>, _Env...> {
87         static_assert(sender_expr_for<_Sender, upon_error_t>);
88         return {};
89     };
90 
91     static constexpr auto complete = //
92         []<class _Tag, class _State, class _Receiver, class... _Args>(
93             __ignore, _State& __state, _Receiver& __rcvr, _Tag,
94             _Args&&... __args) noexcept -> void {
95         if constexpr (__same_as<_Tag, set_error_t>)
96         {
97             stdexec::__set_value_invoke(static_cast<_Receiver&&>(__rcvr),
98                                         static_cast<_State&&>(__state),
99                                         static_cast<_Args&&>(__args)...);
100         }
101         else
102         {
103             _Tag()(static_cast<_Receiver&&>(__rcvr),
104                    static_cast<_Args&&>(__args)...);
105         }
106     };
107 };
108 } // namespace __upon_error
109 
110 using __upon_error::upon_error_t;
111 inline constexpr upon_error_t upon_error{};
112 
113 template <>
114 struct __sexpr_impl<upon_error_t> : __upon_error::__upon_error_impl
115 {};
116 } // namespace stdexec
117