The member impls-for<schedule_from_t>::complete
is initialized with a callable object equivalent to the following lambda:
[]<class Tag, class... Args>(auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept
-> void {
using result_t = decayed-tuple<Tag, Args...>;
constexpr bool nothrow = (is_nothrow_constructible_v<decay_t<Args>, Args> && ...);
try {
state.async-result.template emplace<result_t>(Tag(), std::forward<Args>(args)...);
} catch (...) {
if constexpr (!nothrow)
state.async-result.template emplace<tuple<set_error_t,
exception_ptr>>(set_error, current_exception());
}
start(state.op-state);
};
impls-for<decayed-typeof<let-cpo>>::get-state
is initialized with a callable object equivalent to the following:
[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) requires see below {
auto& [_, fn, child] = sndr;
using fn_t = decay_t<decltype(fn)>;
using env_t = decltype(let-env(child));
using args_variant_t = see below;
using ops2_variant_t = see below;
struct state-type {
fn_t fn;
env_t env;
args_variant_t args;
ops2_variant_t ops2;
};
return state-type{allocator-aware-forward(std::forward_like<Sndr>(fn), rcvr),
let-env(child), {}, {}};
}
The member impls-for<when_all_t>::get-state
is initialized with a callable object
equivalent to the following lambda expression:
[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept(noexcept(e)) -> decltype(e) {
return e;
}
where e is the expression
std::forward<Sndr>(sndr).apply(make-state<Rcvr>())
and where make-state is the following exposition-only class template:
enum class disposition { started, error, stopped };
template<class Rcvr>
struct make-state {
template<class... Sndrs>
auto operator()(auto, auto, Sndrs&&... sndrs) const {
using values_tuple = see below;
using errors_variant = see below;
using stop_callback = stop_callback_for_t<stop_token_of_t<env_of_t<Rcvr>>, on-stop-request>;
struct state-type {
void arrive(Rcvr& rcvr) noexcept {
if (0 == --count) {
complete(rcvr);
}
}
void complete(Rcvr& rcvr) noexcept;
atomic<size_t> count{sizeof...(sndrs)};
inplace_stop_source stop_src{};
atomic<disposition> disp{disposition::started};
errors_variant errors{};
values_tuple values{};
optional<stop_callback> on_stop{nullopt};
};
return state-type{};
}
};
The member impls-for<when_all_t>::start
is initialized with a callable object
equivalent to the following lambda expression:
[]<class State, class Rcvr, class... Ops>(
State& state, Rcvr& rcvr, Ops&... ops) noexcept -> void {
state.on_stop.emplace(
get_stop_token(get_env(rcvr)),
on-stop-request{state.stop_src});
if (state.stop_src.stop_requested()) {
state.on_stop.reset();
set_stopped(std::move(rcvr));
} else {
(start(ops), ...);
}
}
The member impls-for<associate_t>::get-state
is initialized with a callable object equivalent to the following lambda:
[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept(see below) {
auto [_, data] = std::forward<Sndr>(sndr);
auto dataParts = std::move(data).release();
using scope_tkn = decltype(dataParts->first);
using wrap_sender = decltype(dataParts->second);
using op_t = connect_result_t<wrap_sender, Rcvr>;
struct op_state {
bool associated = false;
union {
Rcvr* rcvr;
struct {
scope_tkn token;
op_t op;
} assoc;
};
explicit op_state(Rcvr& r) noexcept
: rcvr(addressof(r)) {}
explicit op_state(scope_tkn tkn, wrap_sender&& sndr, Rcvr& r) try
: associated(true),
assoc(tkn, connect(std::move(sndr), std::move(r))) {
}
catch (...) {
tkn.disassociate();
throw;
}
op_state(op_state&&) = delete;
~op_state() {
if (associated) {
assoc.op.~op_t();
assoc.token.disassociate();
assoc.token.~scope_tkn();
}
}
void run() noexcept {
if (associated)
start(assoc.op);
else
set_stopped(std::move(*rcvr));
}
};
if (dataParts)
return op_state{std::move(dataParts->first), std::move(dataParts->second), rcvr};
else
return op_state{rcvr};
}