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