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 "__completion_signatures.hpp"
19 #include "__cpo.hpp"
20 #include "__env.hpp"
21 #include "__execution_fwd.hpp"
22 #include "__schedulers.hpp"
23 
24 #include <functional>
25 
26 namespace stdexec
27 {
28 namespace __any_
29 {
30 template <class _Sig>
31 struct __rcvr_vfun;
32 
33 template <class _Tag, class... _Args>
34 struct __rcvr_vfun<_Tag(_Args...)>
35 {
36     void (*__complete_)(void*, _Args&&...) noexcept;
37 
operator ()stdexec::__any_::__rcvr_vfun38     void operator()(void* __obj, _Tag, _Args&&... __args) const noexcept
39     {
40         __complete_(__obj, static_cast<_Args&&>(__args)...);
41     }
42 };
43 
44 template <class _GetReceiver = std::identity, class _Obj, class _Tag,
45           class... _Args>
__rcvr_vfun_fn(_Obj *,_Tag (*)(_Args...))46 constexpr auto __rcvr_vfun_fn(_Obj*, _Tag (*)(_Args...)) noexcept
47 {
48     return +[](void* __ptr, _Args&&... __args) noexcept {
49         _Obj* __obj = static_cast<_Obj*>(__ptr);
50         _Tag()(std::move(_GetReceiver()(*__obj)),
51                static_cast<_Args&&>(__args)...);
52     };
53 }
54 
55 template <class _Sigs, class _Env>
56 struct __receiver_vtable_for;
57 
58 template <class _Env, class... _Sigs>
59 struct __receiver_vtable_for<completion_signatures<_Sigs...>, _Env> :
60     __rcvr_vfun<_Sigs>...
61 {
62     _Env (*__do_get_env)(const void* __op_state) noexcept;
63 
64     template <class _OpState, class _GetEnv>
__s_get_envstdexec::__any_::__receiver_vtable_for65     static auto __s_get_env(const void* __ptr) noexcept -> _Env
66     {
67         auto* __op_state = static_cast<const _OpState*>(__ptr);
68         return _GetEnv()(*__op_state);
69     }
70 
71     template <class _OpState, class _GetEnv, class _GetReceiver = std::identity>
__receiver_vtable_forstdexec::__any_::__receiver_vtable_for72     explicit constexpr __receiver_vtable_for(_OpState* __op, _GetEnv,
73                                              _GetReceiver = {}) noexcept :
74         __rcvr_vfun<_Sigs>{__rcvr_vfun_fn<_GetReceiver>(
75             __op, static_cast<_Sigs*>(nullptr))}...,
76         __do_get_env{&__s_get_env<_OpState, _GetEnv>}
77     {}
78 
79     using __rcvr_vfun<_Sigs>::operator()...;
80 
__get_envstdexec::__any_::__receiver_vtable_for81     auto __get_env(const void* __op_state) const noexcept -> _Env
82     {
83         return __do_get_env(__op_state);
84     }
85 };
86 
87 template <class _OpState, class _GetEnv, class _GetReceiver, class _Env,
88           class _Sigs>
89 inline constexpr __receiver_vtable_for<_Sigs, _Env> __receiver_vtable_for_v{
90     static_cast<_OpState*>(nullptr), _GetEnv{}, _GetReceiver{}};
91 
92 template <class _Sigs, class _Env = empty_env>
93 class __receiver_ref
94 {
95   public:
96     using receiver_concept = receiver_t;
97     using __t = __receiver_ref;
98     using __id = __receiver_ref;
99 
100     template <class _OpState, class _GetEnv, class _GetReceiver = std::identity>
__receiver_ref(_OpState & __op_state,_GetEnv,_GetReceiver={})101     __receiver_ref(_OpState& __op_state, _GetEnv, _GetReceiver = {}) noexcept :
102         __vtable_{&__any_::__receiver_vtable_for_v<_OpState, _GetEnv,
103                                                    _GetReceiver, _Env, _Sigs>},
104         __op_state_{&__op_state}
105     {}
106 
get_env() const107     auto get_env() const noexcept -> decltype(auto)
108     {
109         return __vtable_->__get_env(__op_state_);
110     }
111 
112     template <class... _As>
set_value(_As &&...__as)113     void set_value(_As&&... __as) noexcept
114     {
115         (*__vtable_)(__op_state_, set_value_t(), static_cast<_As&&>(__as)...);
116     }
117 
118     template <class _Error>
set_error(_Error && __err)119     void set_error(_Error&& __err) noexcept
120     {
121         (*__vtable_)(__op_state_, set_error_t(), static_cast<_Error&&>(__err));
122     }
123 
set_stopped()124     void set_stopped() noexcept
125     {
126         (*__vtable_)(__op_state_, set_stopped_t());
127     }
128 
129   private:
130     const __receiver_vtable_for<_Sigs, _Env>* __vtable_;
131     void* __op_state_;
132 };
133 } // namespace __any_
134 } // namespace stdexec
135