xref: /openbmc/sdbusplus/include/sdbusplus/async/stdexec/__detail/__upon_stopped.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 "__basic_sender.hpp"
21 #include "__diagnostics.hpp"
22 #include "__domain.hpp"
23 #include "__meta.hpp"
24 #include "__senders_core.hpp"
25 #include "__sender_adaptor_closure.hpp"
26 #include "__transform_completion_signatures.hpp"
27 #include "__transform_sender.hpp"
28 #include "__senders.hpp" // IWYU pragma: keep for __well_formed_sender
29 
30 // include these after __execution_fwd.hpp
31 namespace stdexec {
32   /////////////////////////////////////////////////////////////////////////////
33   // [execution.senders.adaptors.upon_stopped]
34   namespace __upon_stopped {
35     inline constexpr __mstring __upon_stopped_context =
36       "In stdexec::upon_stopped(Sender, Function)..."_mstr;
37     using __on_not_callable = __callable_error<__upon_stopped_context>;
38 
39     template <class _Fun, class _CvrefSender, class... _Env>
40     using __completion_signatures_t = transform_completion_signatures<
41       __completion_signatures_of_t<_CvrefSender, _Env...>,
42       __with_error_invoke_t<__on_not_callable, set_stopped_t, _Fun, _CvrefSender, _Env...>,
43       __sigs::__default_set_value,
44       __sigs::__default_set_error,
45       __set_value_invoke_t<_Fun>
46     >;
47 
48     ////////////////////////////////////////////////////////////////////////////////////////////////
49     struct upon_stopped_t {
50       template <sender _Sender, __movable_value _Fun>
51         requires __callable<_Fun>
operator ()stdexec::__upon_stopped::upon_stopped_t52       auto operator()(_Sender&& __sndr, _Fun __fun) const -> __well_formed_sender auto {
53         auto __domain = __get_early_domain(__sndr);
54         return stdexec::transform_sender(
55           __domain,
56           __make_sexpr<upon_stopped_t>(static_cast<_Fun&&>(__fun), static_cast<_Sender&&>(__sndr)));
57       }
58 
59       template <__movable_value _Fun>
60         requires __callable<_Fun>
STDEXEC_ATTRIBUTEstdexec::__upon_stopped::upon_stopped_t61       STDEXEC_ATTRIBUTE(always_inline)
62       auto operator()(_Fun __fun) const -> __binder_back<upon_stopped_t, _Fun> {
63         return {{static_cast<_Fun&&>(__fun)}, {}, {}};
64       }
65     };
66 
67     struct __upon_stopped_impl : __sexpr_defaults {
68       static constexpr auto get_completion_signatures =
69         []<class _Sender, class... _Env>(_Sender&&, _Env&&...) noexcept
70         -> __completion_signatures_t<__decay_t<__data_of<_Sender>>, __child_of<_Sender>, _Env...> {
71         static_assert(sender_expr_for<_Sender, upon_stopped_t>);
72         return {};
73       };
74 
75       static constexpr auto complete =
76         []<class _Tag, class _State, class _Receiver, class... _Args>(
77           __ignore,
78           _State& __state,
79           _Receiver& __rcvr,
80           _Tag,
81           _Args&&... __args) noexcept -> void {
82         if constexpr (__same_as<_Tag, set_stopped_t>) {
83           stdexec::__set_value_invoke(
84             static_cast<_Receiver&&>(__rcvr),
85             static_cast<_State&&>(__state),
86             static_cast<_Args&&>(__args)...);
87         } else {
88           _Tag()(static_cast<_Receiver&&>(__rcvr), static_cast<_Args&&>(__args)...);
89         }
90       };
91     };
92   } // namespace __upon_stopped
93 
94   using __upon_stopped::upon_stopped_t;
95   inline constexpr upon_stopped_t upon_stopped{};
96 
97   template <>
98   struct __sexpr_impl<upon_stopped_t> : __upon_stopped::__upon_stopped_impl { };
99 
100 } // namespace stdexec
101