xref: /openbmc/sdbusplus/include/sdbusplus/async/stdexec/__detail/__any_receiver_ref.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 "__completion_signatures.hpp"
21 #include "__receivers.hpp"
22 
23 #include <functional>
24 
25 namespace stdexec::__any_ {
26   template <class _Sig>
27   struct __rcvr_vfun;
28 
29   template <class _Tag, class... _Args>
30   struct __rcvr_vfun<_Tag(_Args...)> {
31     void (*__complete_)(void*, _Args...) noexcept;
32 
operator ()stdexec::__any_::__rcvr_vfun33     void operator()(void* __obj, _Tag, _Args... __args) const noexcept {
34       __complete_(__obj, static_cast<_Args&&>(__args)...);
35     }
36   };
37 
38   template <class _GetReceiver = std::identity, class _Obj, class _Tag, class... _Args>
__rcvr_vfun_fn(_Obj *,_Tag (*)(_Args...))39   constexpr auto __rcvr_vfun_fn(_Obj*, _Tag (*)(_Args...)) noexcept {
40     return +[](void* __ptr, _Args... __args) noexcept {
41       _Obj* __obj = static_cast<_Obj*>(__ptr);
42       _Tag()(std::move(_GetReceiver()(*__obj)), static_cast<_Args&&>(__args)...);
43     };
44   }
45 
46   template <class _Sigs, class _Env>
47   struct __receiver_vtable_for;
48 
49   template <class _Env, class... _Sigs>
50   struct __receiver_vtable_for<completion_signatures<_Sigs...>, _Env> : __rcvr_vfun<_Sigs>... {
51     _Env (*__do_get_env)(const void* __op_state) noexcept;
52 
53     template <class _OpState, class _GetEnv>
__s_get_envstdexec::__any_::__receiver_vtable_for54     static auto __s_get_env(const void* __ptr) noexcept -> _Env {
55       auto* __op_state = static_cast<const _OpState*>(__ptr);
56       return _GetEnv()(*__op_state);
57     }
58 
59     template <class _OpState, class _GetEnv, class _GetReceiver = std::identity>
__receiver_vtable_forstdexec::__any_::__receiver_vtable_for60     explicit constexpr __receiver_vtable_for(_OpState* __op, _GetEnv, _GetReceiver = {}) noexcept
61       : __rcvr_vfun<_Sigs>{__rcvr_vfun_fn<_GetReceiver>(__op, static_cast<_Sigs*>(nullptr))}...
62       , __do_get_env{&__s_get_env<_OpState, _GetEnv>} {
63     }
64 
65     template <class _Tag, class... _Args>
66       requires __one_of<_Tag(_Args...), _Sigs...>
operator ()stdexec::__any_::__receiver_vtable_for67     void operator()(void* __obj, _Tag, _Args&&... __args) const noexcept {
68       const __rcvr_vfun<_Tag(_Args...)>& __vfun = *this;
69       __vfun(__obj, _Tag{}, static_cast<_Args&&>(__args)...);
70     }
71 
__get_envstdexec::__any_::__receiver_vtable_for72     auto __get_env(const void* __op_state) const noexcept -> _Env {
73       return __do_get_env(__op_state);
74     }
75   };
76 
77   template <class _OpState, class _GetEnv, class _GetReceiver, class _Env, class _Sigs>
78   inline constexpr __receiver_vtable_for<_Sigs, _Env>
79     __receiver_vtable_for_v{static_cast<_OpState*>(nullptr), _GetEnv{}, _GetReceiver{}};
80 
81   template <class _Sigs, class _Env = env<>>
82   class __receiver_ref {
83    public:
84     using receiver_concept = receiver_t;
85     using __t = __receiver_ref;
86     using __id = __receiver_ref;
87 
88     template <class _OpState, class _GetEnv, class _GetReceiver = std::identity>
__receiver_ref(_OpState & __op_state,_GetEnv,_GetReceiver={})89     __receiver_ref(_OpState& __op_state, _GetEnv, _GetReceiver = {}) noexcept
90       : __vtable_{&__any_::__receiver_vtable_for_v<_OpState, _GetEnv, _GetReceiver, _Env, _Sigs>}
91       , __op_state_{&__op_state} {
92     }
93 
get_env() const94     auto get_env() const noexcept -> decltype(auto) {
95       return __vtable_->__get_env(__op_state_);
96     }
97 
98     template <class... _As>
99       requires __callable<__receiver_vtable_for<_Sigs, _Env>, void*, set_value_t, _As...>
set_value(_As &&...__as)100     void set_value(_As&&... __as) noexcept {
101       (*__vtable_)(__op_state_, set_value_t(), static_cast<_As&&>(__as)...);
102     }
103 
104     template <class _Error>
105       requires __callable<__receiver_vtable_for<_Sigs, _Env>, void*, set_error_t, _Error>
set_error(_Error && __err)106     void set_error(_Error&& __err) noexcept {
107       (*__vtable_)(__op_state_, set_error_t(), static_cast<_Error&&>(__err));
108     }
109 
set_stopped()110     void set_stopped() noexcept
111       requires __callable<__receiver_vtable_for<_Sigs, _Env>, void*, set_stopped_t>
112     {
113       (*__vtable_)(__op_state_, set_stopped_t());
114     }
115 
116    private:
117     const __receiver_vtable_for<_Sigs, _Env>* __vtable_;
118     void* __op_state_;
119   };
120 } // namespace stdexec::__any_
121