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