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
63 changes: 41 additions & 22 deletions include/stdexec/__detail/__finally.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
// include these after execution_fwd.hpp
#include "__basic_sender.hpp"
#include "__optional.hpp"
#include "__schedulers.hpp"
#include "__sender_adaptor_closure.hpp"
#include "__senders.hpp"
#include "__transform_completion_signatures.hpp"
Expand Down Expand Up @@ -64,8 +65,8 @@ namespace STDEXEC
transform_sender(STDEXEC::set_value_t, _Sender&& __sndr, STDEXEC::__ignore)
{
auto& [__tag, __ign, __initial, __final] = __sndr;
return __final ::__sender{STDEXEC::__forward_like<_Sender>(__initial), //
STDEXEC::__forward_like<_Sender>(__final)};
return STDEXEC::__final::__sender{STDEXEC::__forward_like<_Sender>(__initial), //
STDEXEC::__forward_like<_Sender>(__final)};
}
};

Expand Down Expand Up @@ -98,10 +99,12 @@ namespace STDEXEC
_CvInitialSender,
_Receiver>;

template <class _ResultType, class _Receiver>
template <class _ResultType, class _Receiver, class _Env2>
struct __opstate_base
{
_Receiver __rcvr_{};
_Receiver __rcvr_{};
STDEXEC_ATTRIBUTE(no_unique_address)
_Env2 const __env2_{};
_ResultType __result_{__no_init}; // __variant<__tuple<set_tag, args...>, ...>
};

Expand All @@ -123,10 +126,11 @@ namespace STDEXEC
}
};

template <class _ResultType, class _Receiver>
template <class _ResultType, class _Receiver, class _Env2>
struct __final_receiver
{
using receiver_concept = receiver_t;
using __env2_t = __join_env_t<_Env2 const &, __fwd_env_t<env_of_t<_Receiver>>>;

constexpr void set_value() noexcept
{
Expand All @@ -146,26 +150,28 @@ namespace STDEXEC
}

[[nodiscard]]
constexpr auto get_env() const noexcept -> __fwd_env_t<env_of_t<_Receiver>>
constexpr auto get_env() const noexcept -> __env2_t
{
return __fwd_env(STDEXEC::get_env(__opstate_->__rcvr_));
return __env::__join(__opstate_->__env2_, __fwd_env(STDEXEC::get_env(__opstate_->__rcvr_)));
}

__opstate_base<_ResultType, _Receiver>* __opstate_;
__opstate_base<_ResultType, _Receiver, _Env2>* __opstate_;
};

template <class _CvFinalSender, class _ResultType, class _Receiver>
struct __final_opstate : __opstate_base<_ResultType, _Receiver>
template <class _CvFinalSender, class _ResultType, class _Receiver, class _Env2>
struct __final_opstate : __opstate_base<_ResultType, _Receiver, _Env2>
{
using __results_t = _ResultType;
using __cleanup_callback_t = void(__final_opstate*) noexcept;
using __final_receiver_t = __final_receiver<_ResultType, _Receiver>;
using __final_receiver_t = __final_receiver<_ResultType, _Receiver, _Env2>;
using __final_opstate_t = connect_result_t<_CvFinalSender, __final_receiver_t>;

constexpr explicit __final_opstate(__cleanup_callback_t* __cleanup_callback,
_CvFinalSender&& __final,
_Receiver&& __rcvr) noexcept
: __opstate_base<_ResultType, _Receiver>{static_cast<_Receiver&&>(__rcvr)}
_Receiver&& __rcvr,
_Env2 __env2) noexcept
: __opstate_base<_ResultType, _Receiver, _Env2>{static_cast<_Receiver&&>(__rcvr),
static_cast<_Env2&&>(__env2)}
, __cleanup_callback_{__cleanup_callback}
, __final_opstate_(
STDEXEC::connect(static_cast<_CvFinalSender&&>(__final), __final_receiver_t{this}))
Expand Down Expand Up @@ -205,27 +211,40 @@ namespace STDEXEC
__final_opstate_t __final_opstate_;
};

template <class _CvFinalSender, class _ResultType, class _Receiver>
template <class _CvFinalSender, class _ResultType, class _Receiver, class _Env2>
struct __initial_receiver;

template <class _CvInitialSender, class _CvFinalSender, class _Receiver>
template <class _CvInitialSender, class _CvFinalSender, class _Receiver, class _Env2>
using __final_opstate_t =
__final_opstate<_CvFinalSender,
__result_variant_t<_CvInitialSender, _CvFinalSender, _Receiver>,
_Receiver>;
_Receiver,
_Env2>;

using __mk_secondary_env_t =
STDEXEC::__mk_secondary_env_t<set_value_t, set_error_t, set_stopped_t>;

template <class _CvInitialSender, class _Receiver>
using __env2_t = __call_result_t<__mk_secondary_env_t, _CvInitialSender, env_of_t<_Receiver>>;

template <class _CvInitialSender, class _CvFinalSender, class _Receiver>
struct __opstate : __final_opstate_t<_CvInitialSender, _CvFinalSender, _Receiver>
struct __opstate
: __final_opstate_t<_CvInitialSender,
_CvFinalSender,
_Receiver,
__env2_t<_CvInitialSender, _Receiver>>
{
using __base_t = __final_opstate_t<_CvInitialSender, _CvFinalSender, _Receiver>;
using __env2_t = __final::__env2_t<_CvInitialSender, _Receiver>;
using __base_t = __final_opstate_t<_CvInitialSender, _CvFinalSender, _Receiver, __env2_t>;
using __initial_results_t = __base_t::__results_t;

constexpr explicit __opstate(_CvInitialSender&& __initial,
_CvFinalSender&& __final,
_Receiver __rcvr)
: __base_t(&__cleanup_initial_opstate,
static_cast<_CvFinalSender&&>(__final),
static_cast<_Receiver&&>(__rcvr))
static_cast<_Receiver&&>(__rcvr),
__mk_secondary_env_t{}(__initial, STDEXEC::get_env(__rcvr)))
{
__initial_opstate_.__emplace_from(STDEXEC::connect,
static_cast<_CvInitialSender&&>(__initial),
Expand All @@ -239,7 +258,7 @@ namespace STDEXEC

private:
using __initial_receiver_t =
__initial_receiver<_CvFinalSender, __initial_results_t, _Receiver>;
__initial_receiver<_CvFinalSender, __initial_results_t, _Receiver, __env2_t>;
using __initial_opstate_t = connect_result_t<_CvInitialSender, __initial_receiver_t>;

static constexpr void __cleanup_initial_opstate(__base_t* __base) noexcept
Expand All @@ -251,7 +270,7 @@ namespace STDEXEC
__optional<__initial_opstate_t> __initial_opstate_{};
};

template <class _CvFinalSender, class _ResultType, class _Receiver>
template <class _CvFinalSender, class _ResultType, class _Receiver, class _Env2>
struct __initial_receiver
{
using receiver_concept = receiver_t;
Expand Down Expand Up @@ -281,7 +300,7 @@ namespace STDEXEC
return STDEXEC::get_env(__opstate_->__rcvr_);
}

__final_opstate<_CvFinalSender, _ResultType, _Receiver>* __opstate_;
__final_opstate<_CvFinalSender, _ResultType, _Receiver, _Env2>* __opstate_;
};

template <class _CvInitialSender, class _CvFinalSender, class... _Env>
Expand Down
70 changes: 21 additions & 49 deletions include/stdexec/__detail/__let.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,37 +64,11 @@ namespace STDEXEC
using __on_not_callable =
__mbind_front_q<__callable_error_t, decltype(__let_from_set<_SetTag>)>;

// This environment is part of the receiver used to connect the secondary sender.
template <class _SetTag, class _Attrs, class... _Env>
constexpr auto __mk_env2(_Attrs const & __attrs, _Env const &... __env) noexcept
{
if constexpr (__callable<get_completion_scheduler_t<_SetTag>,
_Attrs const &,
__fwd_env_t<_Env const &>...>)
{
return __mk_sch_env(get_completion_scheduler<_SetTag>(__attrs, __fwd_env(__env)...),
__fwd_env(__env)...);
}
else if constexpr (__callable<get_completion_domain_t<_SetTag>,
_Attrs const &,
__fwd_env_t<_Env const &>...>)
{
using __domain_t = __call_result_t<get_completion_domain_t<_SetTag>,
_Attrs const &,
__fwd_env_t<_Env const &>...>;
return prop{get_domain, __domain_t{}};
}
else
{
return env{};
}
}
template <class _SetTag, class _Sender, class... _Env>
using __env2_t = __call_result_t<__mk_secondary_env_t<_SetTag>, _Sender, _Env const &...>;

template <class _SetTag, class _Attrs, class... _Env>
using __env2_t = decltype(__let::__mk_env2<_SetTag>(__declval<_Attrs>(), __declval<_Env>()...));

template <class _SetTag, class _Attrs, class _Env>
using __result_env_t = __join_env_t<__env2_t<_SetTag, _Attrs, _Env>, _Env>;
template <class _SetTag, class _Sender, class _Env>
using __result_env_t = __join_env_t<__env2_t<_SetTag, _Sender, _Env>, _Env>;

template <class _Receiver, class _Env2>
struct __rcvr_env
Expand Down Expand Up @@ -209,10 +183,9 @@ namespace STDEXEC
using __completions_t = __gather_completion_signatures_t<
__completion_signatures_of_t<_CvSender, _Env...>,
__t<_LetTag>,
__transform_signal_fn<
__t<_LetTag>,
_Fun,
__result_env_t<__t<_LetTag>, env_of_t<_CvSender>, _Env>...>::template __f,
__transform_signal_fn<__t<_LetTag>,
_Fun,
__result_env_t<__t<_LetTag>, _CvSender, _Env>...>::template __f,
__cmplsigs::__default_completion,
__mtry_q<__concat_completion_signatures_t>::__f>;

Expand Down Expand Up @@ -243,7 +216,7 @@ namespace STDEXEC
using __result_domain_t = __gather_completions_t<
_SetTag,
__completion_signatures_of_t<_Child, _Env>,
__result_sender_fn<_SetTag, _Fun, __result_env_t<_SetTag, env_of_t<_Child>, _Env>>,
__result_sender_fn<_SetTag, _Fun, __result_env_t<_SetTag, _Child, _Env>>,
__try_common_domain_fn<_SetTag, _Env>>;

//! Metafunction creating the operation state needed to connect the result of calling
Expand Down Expand Up @@ -278,7 +251,7 @@ namespace STDEXEC
using __has_nothrow_completions_t = __gather_completions_t<
completion_signatures_of_t<_Child, _Env>,
_SetTag,
__has_nothrow_completions_fn<_Fn, __result_env_t<_SetTag, env_of_t<_Child>, _Env>>,
__has_nothrow_completions_fn<_Fn, __result_env_t<_SetTag, _Child, _Env>>,
__qq<__mand_t>>;

//! The core of the operation state for `let_*`.
Expand All @@ -289,15 +262,15 @@ namespace STDEXEC
using __env2_t = _Env2;
using __second_rcvr_t = __rcvr_env<_Receiver, _Env2>;

template <class _Attrs>
template <class _Sender>
constexpr explicit __opstate_base(_SetTag,
_Attrs const & __attrs,
_Fun __fn,
_Receiver&& __rcvr) noexcept
_Sender const & __sndr,
_Fun __fn,
_Receiver&& __rcvr) noexcept
: __rcvr_(static_cast<_Receiver&&>(__rcvr))
, __fn_(STDEXEC::__allocator_aware_forward(static_cast<_Fun&&>(__fn), __rcvr_))
// TODO(ericniebler): this needs a fallback:
, __env2_(__let::__mk_env2<_SetTag>(__attrs, STDEXEC::get_env(__rcvr_)))
, __env2_(__mk_secondary_env_t<_SetTag>()(__sndr, STDEXEC::get_env(__rcvr_)))
{}

constexpr virtual void __start_next() = 0;
Expand Down Expand Up @@ -400,7 +373,7 @@ namespace STDEXEC
: __opstate_base<_SetTag,
_Fun,
_Receiver,
__let::__env2_t<_SetTag, env_of_t<_Child>, env_of_t<_Receiver>>,
__let::__env2_t<_SetTag, _Child, env_of_t<_Receiver>>,
_Tuples...>
{
using __env2_t = __opstate::__opstate_base::__env2_t;
Expand All @@ -415,7 +388,7 @@ namespace STDEXEC
noexcept(__nothrow_connectable<_Child, __first_rcvr_t>
&& __nothrow_move_constructible<_Fun>)
: __opstate::__opstate_base(_SetTag(),
STDEXEC::get_env(__child),
__child,
static_cast<_Fun&&>(__fn),
static_cast<_Receiver&&>(__rcvr))
{
Expand Down Expand Up @@ -512,16 +485,16 @@ namespace STDEXEC
using __f = decltype(__impl<_Ts...>());
};

template <class _SetTag, class _Fn, class _Attrs, class... _Env>
template <class _SetTag, class _Fn, class _Sender, class... _Env>
struct __domain_transform_fn
{
using __result_sender_fn =
__let::__result_sender_fn<_SetTag, _Fn, __result_env_t<_SetTag, _Attrs, _Env>...>;
__let::__result_sender_fn<_SetTag, _Fn, __result_env_t<_SetTag, _Sender, _Env>...>;

template <class... _As>
using __f = __completion_domain_of_t<_SetTag,
__mcall<__result_sender_fn, _As...>,
__result_env_t<_SetTag, _Attrs, _Env>...>;
__result_env_t<_SetTag, _Sender, _Env>...>;
};

//! @tparam _LetTag The tag type for the let_ operation.
Expand All @@ -534,8 +507,7 @@ namespace STDEXEC
{
if constexpr (sender_in<_Sndr, _Env...>)
{
using __domain_transform_fn =
__let::__domain_transform_fn<_SetTag, _Fn, env_of_t<_Sndr>, _Env...>;
using __domain_transform_fn = __let::__domain_transform_fn<_SetTag, _Fn, _Sndr, _Env...>;
return __minvoke_or_q<__gather_completions_t,
indeterminate_domain<>,
__t<_LetTag>,
Expand Down Expand Up @@ -606,7 +578,7 @@ namespace STDEXEC
using __transform_fn =
__result_completion_behavior_fn<__set_tag_t,
_Fn,
__result_env_t<__set_tag_t, env_of_t<_Sndr>, _Env>...>;
__result_env_t<__set_tag_t, _Sndr, _Env>...>;
using __completions_t = __completion_signatures_of_t<_Sndr, __fwd_env_t<_Env>...>;

constexpr auto __pred_behavior =
Expand Down
Loading
Loading