diff --git a/include/exec/fork_join.hpp b/include/exec/fork_join.hpp index f2fbaf7f2..97b79ccf5 100644 --- a/include/exec/fork_join.hpp +++ b/include/exec/fork_join.hpp @@ -147,9 +147,9 @@ namespace experimental::execution using _when_all_sndr_t = fork_join_impl_t::_when_all_sndr_t<_child_completions_t, Closures, _domain_t>; using _child_opstate_t = - STDEXEC::connect_result_t>; + STDEXEC::connect_result_t>; using _fork_opstate_t = - STDEXEC::connect_result_t<_when_all_sndr_t, STDEXEC::__rcvr_ref_t>; + STDEXEC::connect_result_t<_when_all_sndr_t, STDEXEC::__receiver_ref>; using _cache_sndr_t = fork_join_impl_t::_cache_sndr_t<_variant_t<_child_completions_t>, _domain_t>; @@ -159,11 +159,11 @@ namespace experimental::execution , _fork_opstate_(STDEXEC::connect(STDEXEC::__apply(_mk_when_all_fn{}, static_cast(closures), _cache_sndr_t{&_cache_}), - STDEXEC::__ref_rcvr(_rcvr_))) + STDEXEC::__receiver_ref(_rcvr_))) { _child_opstate_.__construct_from(STDEXEC::connect, static_cast(sndr), - STDEXEC::__ref_rcvr(*this)); + STDEXEC::__receiver_ref(*this)); } STDEXEC_IMMOVABLE(_opstate_t); diff --git a/include/exec/unless_stop_requested.hpp b/include/exec/unless_stop_requested.hpp index 2d6ff219f..1dfb7a942 100644 --- a/include/exec/unless_stop_requested.hpp +++ b/include/exec/unless_stop_requested.hpp @@ -46,13 +46,13 @@ namespace experimental::execution struct __opstate { using receiver_concept = receiver_t; - using __child_op_t = connect_result_t<_CvChild, __rcvr_ref_t<_Receiver>>; + using __child_op_t = connect_result_t<_CvChild, __receiver_ref<_Receiver>>; constexpr explicit __opstate(_CvChild&& __child, _Receiver __rcvr) - noexcept(__nothrow_connectable<_CvChild, __rcvr_ref_t<_Receiver>>) + noexcept(__nothrow_connectable<_CvChild, __receiver_ref<_Receiver>>) : __rcvr_(static_cast<_Receiver&&>(__rcvr)) , __child_op_( - STDEXEC::connect(static_cast<_CvChild&&>(__child), STDEXEC::__ref_rcvr(__rcvr_))) + STDEXEC::connect(static_cast<_CvChild&&>(__child), STDEXEC::__receiver_ref(__rcvr_))) {} constexpr void start() noexcept @@ -99,7 +99,7 @@ namespace experimental::execution template using __rcvr_t = - __if_c<__unstoppable_receiver<_Receiver>, _Receiver, __rcvr_ref_t<_Receiver>>; + __if_c<__unstoppable_receiver<_Receiver>, _Receiver, __receiver_ref<_Receiver>>; static constexpr auto __connect = // [](_Sender&& __sndr, _Receiver __rcvr) noexcept( diff --git a/include/stdexec/__detail/__receiver_ref.hpp b/include/stdexec/__detail/__receiver_ref.hpp index 954b039b2..bf89dfdf1 100644 --- a/include/stdexec/__detail/__receiver_ref.hpp +++ b/include/stdexec/__detail/__receiver_ref.hpp @@ -22,106 +22,58 @@ #include "__receivers.hpp" #include +#include namespace STDEXEC { - template > - struct __rcvr_ref + template > + struct __pointer_receiver { using receiver_concept = receiver_t; STDEXEC_ATTRIBUTE(host, device) - constexpr explicit __rcvr_ref(_Rcvr& __rcvr) noexcept - : __rcvr_{std::addressof(__rcvr)} + constexpr explicit __pointer_receiver(_RcvrPtr __rcvr_ptr) noexcept + : __rcvr_ptr_{__rcvr_ptr} {} template STDEXEC_ATTRIBUTE(host, device) constexpr void set_value(_As&&... __as) noexcept { - STDEXEC::set_value(static_cast<_Rcvr&&>(*__rcvr_), static_cast<_As&&>(__as)...); + STDEXEC::set_value(std::move(*__rcvr_ptr_), static_cast<_As&&>(__as)...); } template STDEXEC_ATTRIBUTE(host, device) constexpr void set_error(_Error&& __err) noexcept { - STDEXEC::set_error(static_cast<_Rcvr&&>(*__rcvr_), static_cast<_Error&&>(__err)); + STDEXEC::set_error(std::move(*__rcvr_ptr_), static_cast<_Error&&>(__err)); } - STDEXEC_ATTRIBUTE(host, device) constexpr void set_stopped() noexcept + STDEXEC_ATTRIBUTE(host, device) + constexpr void set_stopped() noexcept { - STDEXEC::set_stopped(static_cast<_Rcvr&&>(*__rcvr_)); + STDEXEC::set_stopped(std::move(*__rcvr_ptr_)); } STDEXEC_ATTRIBUTE(nodiscard, host, device) constexpr auto get_env() const noexcept -> _Env { - static_assert(__same_as<_Env, env_of_t<_Rcvr>>, + static_assert(__same_as<_Env, env_of_t>, "get_env() must return the same type as env_of_t<_Rcvr>"); - return STDEXEC::get_env(*__rcvr_); + return STDEXEC::get_env(*__rcvr_ptr_); } private: - _Rcvr* __rcvr_; + _RcvrPtr __rcvr_ptr_; }; - namespace __detail + template > + struct __receiver_ref : __pointer_receiver<_Rcvr*, _Env> { - template - STDEXEC_ATTRIBUTE(host, device) - constexpr auto __is_type_complete(int) noexcept - { - return true; - } - - template STDEXEC_ATTRIBUTE(host, device) - constexpr auto __is_type_complete(long) noexcept - { - return false; - } - } // namespace __detail - - // The __ref_rcvr function and its helpers are used to avoid wrapping a receiver in a - // __rcvr_ref when that is possible. The logic goes as follows: - - // 1. If the receiver is an instance of __rcvr_ref, return it. - // 2. If the type is incomplete or an operation state, return a __rcvr_ref wrapping the - // receiver. - // 3. If the receiver is nothrow copy constructible, return it. - // 4. Otherwise, return a __rcvr_ref wrapping the receiver. - template - STDEXEC_ATTRIBUTE(nodiscard, host, device) - constexpr auto __ref_rcvr(_Rcvr& __rcvr) noexcept - { - if constexpr (__same_as<_Env, void>) - { - return STDEXEC::__ref_rcvr>(__rcvr); - } - else if constexpr (__is_instance_of<_Rcvr, __rcvr_ref>) - { - return __rcvr; - } - else if constexpr (!__detail::__is_type_complete<_Rcvr>(0)) - { - return __rcvr_ref<_Rcvr, _Env>{__rcvr}; - } - else if constexpr (operation_state<_Rcvr>) - { - return __rcvr_ref<_Rcvr, _Env>{__rcvr}; - } - else if constexpr (__nothrow_constructible_from<_Rcvr, _Rcvr const &>) - { - return const_cast<_Rcvr const &>(__rcvr); - } - else - { - return __rcvr_ref{__rcvr}; - } - STDEXEC_UNREACHABLE(); - } - - template > - using __rcvr_ref_t = decltype(STDEXEC::__ref_rcvr<_Env>(STDEXEC::__declval<_Rcvr&>())); + constexpr __receiver_ref(_Rcvr& __rcvr) noexcept + : __pointer_receiver<_Rcvr*, _Env>(std::addressof(__rcvr)) + {} + }; } // namespace STDEXEC