Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions include/exec/fork_join.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Sndr, STDEXEC::__rcvr_ref_t<_opstate_t, _env_t>>;
STDEXEC::connect_result_t<Sndr, STDEXEC::__receiver_ref<_opstate_t, _env_t>>;
using _fork_opstate_t =
STDEXEC::connect_result_t<_when_all_sndr_t, STDEXEC::__rcvr_ref_t<Rcvr>>;
STDEXEC::connect_result_t<_when_all_sndr_t, STDEXEC::__receiver_ref<Rcvr>>;
using _cache_sndr_t =
fork_join_impl_t::_cache_sndr_t<_variant_t<_child_completions_t>, _domain_t>;

Expand All @@ -159,11 +159,11 @@ namespace experimental::execution
, _fork_opstate_(STDEXEC::connect(STDEXEC::__apply(_mk_when_all_fn{},
static_cast<Closures&&>(closures),
_cache_sndr_t{&_cache_}),
STDEXEC::__ref_rcvr(_rcvr_)))
STDEXEC::__receiver_ref(_rcvr_)))
{
_child_opstate_.__construct_from(STDEXEC::connect,
static_cast<Sndr&&>(sndr),
STDEXEC::__ref_rcvr(*this));
STDEXEC::__receiver_ref(*this));
}

STDEXEC_IMMOVABLE(_opstate_t);
Expand Down
8 changes: 4 additions & 4 deletions include/exec/unless_stop_requested.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -99,7 +99,7 @@ namespace experimental::execution

template <class _Receiver>
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 = //
[]<class _Sender, class _Receiver>(_Sender&& __sndr, _Receiver __rcvr) noexcept(
Expand Down
86 changes: 19 additions & 67 deletions include/stdexec/__detail/__receiver_ref.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,106 +22,58 @@
#include "__receivers.hpp"

#include <memory>
#include <utility>

namespace STDEXEC
{
template <class _Rcvr, class _Env = env_of_t<_Rcvr>>
struct __rcvr_ref
template <class _RcvrPtr, class _Env = env_of_t<decltype(*_RcvrPtr())>>
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 <class... _As>
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 <class _Error>
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<decltype(*_RcvrPtr())>>,
"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 <class _Rcvr, class _Env = env_of_t<_Rcvr>>
struct __receiver_ref : __pointer_receiver<_Rcvr*, _Env>
{
template <class _Rcvr, size_t = sizeof(_Rcvr)>
STDEXEC_ATTRIBUTE(host, device)
constexpr auto __is_type_complete(int) noexcept
{
return true;
}

template <class _Rcvr>
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 <class _Env = void, class _Rcvr>
STDEXEC_ATTRIBUTE(nodiscard, host, device)
constexpr auto __ref_rcvr(_Rcvr& __rcvr) noexcept
{
if constexpr (__same_as<_Env, void>)
{
return STDEXEC::__ref_rcvr<env_of_t<_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 <class _Rcvr, class _Env = env_of_t<_Rcvr>>
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
Loading