8.3 KiB
[exec.schedule.from]
33 Execution control library [exec]
33.9 Senders [exec.snd]
33.9.12 Sender adaptors [exec.adapt]
33.9.12.7 execution::schedule_from [exec.schedule.from]
schedule_from schedules work dependent on the completion of a sender onto a scheduler's associated execution resource.
[Note 1:
schedule_from is not meant to be used in user code; it is used in the implementation of continues_on.
â end note]
The name schedule_from denotes a customization point object.
For some subexpressions sch and sndr, let Sch be decltype((sch)) andSndr be decltype((sndr)).
If Sch does not satisfy scheduler, orSndr does not satisfy sender,schedule_from(sch, sndr) is ill-formed.
Otherwise, the expression schedule_from(sch, sndr) is expression-equivalent to:transform_sender(query-with-default(get_domain, sch, default_domain()), make-sender(schedule_from, sch, sndr)) except that sch is evaluated only once.
The exposition-only class template impls-for ([exec.snd.expos]) is specialized for schedule_from_t as follows:
namespace std::execution {template<>struct impls-for<schedule_from_t> : default-impls {static constexpr auto get-attrs = see below; static constexpr auto get-state = see below; static constexpr auto complete = see below; template<class Sndr, class... Env>static consteval void check-types(); };}
The member impls-for<schedule_from_t>::get-attrs is initialized with a callable object equivalent to the following lambda:[](const auto& data, const auto& child) noexcept -> decltype(auto) {return JOIN-ENV(SCHED-ATTRS(data), FWD-ENV(get_env(child)));}
The member impls-for<schedule_from_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)requires sender_in<child-type, FWD-ENV-T(env_of_t)> {auto& [_, sch, child] = sndr; using sched_t = decltype(auto(sch)); using variant_t = see below; using receiver_t = see below; using operation_t = connect_result_t<schedule_result_t<sched_t>, receiver_t>; constexpr bool nothrow = noexcept(connect(schedule(sch), receiver_t{nullptr})); struct state-type { Rcvr& rcvr; // exposition only variant_t async-result; // exposition only operation_t op-state; // exposition onlyexplicit state-type(sched_t sch, Rcvr& rcvr) noexcept(nothrow): rcvr(rcvr), op-state(connect(schedule(sch), receiver_t{this})) {}}; return state-type{sch, rcvr};}
template<class Sndr, class... Env> static consteval void check-types();
Effects: Equivalent to:get_completion_signatures<schedule_result_t<data-type>, FWD-ENV-T(Env)...>();auto cs = get_completion_signatures<child-type, FWD-ENV-T(Env)...>();decay-copyable-result-datums(cs); // see [exec.snd.expos]
Objects of the local class state-type can be used to initialize a structured binding.
Let Sigs be a pack of the arguments to the completion_signatures specialization named by completion_signatures_of_t<child-type, FWD-ENV-T(env_of_t)>.
Let as-tuple be an alias template such thatas-tuple<Tag(Args...)> denotes
the type decayed-tuple<Tag, Args...>, and
let is-nothrow-decay-copy-sig be a variable template such thatauto(is-nothrow-decay-copy-sig<Tag(Args...
)>) is
a constant expression of type bool and
equal to (is_nothrow_constructible_v<decay_t, Args> && ...).
Let error-completion be a pack consisting of the type set_error_t(exception_ptr) if (is-nothrow-decay-copy-sig &&...) is false, and an empty pack otherwise.
Then variant_t denotes the type variant<monostate, as-tuple..., error-completion...>, except with duplicate types removed.
receiver_t is an alias for the following exposition-only class:namespace std::execution {struct receiver-type {using receiver_concept = receiver_t; state-type* state; // exposition onlyvoid set_value() && noexcept { visit([this](Tuple& result) noexcept -> void {if constexpr (<monostate, Tuple>) {auto& [tag, ...args] = result;
tag(std::move(state->rcvr), std::move(args)...); }}, state->async-result); }templatevoid set_error(Error&& err) && noexcept { execution::set_error(std::move(state->rcvr), std::forward(err)); }void set_stopped() && noexcept { execution::set_stopped(std::move(state->rcvr)); }decltype(auto) get_env() const noexcept {return FWD-ENV(execution::get_env(state->rcvr)); }};}
The expression in the noexcept clause of the lambda is true if the construction of the returned state-type object is not potentially throwing; otherwise, false.
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> && ...); try { state.async-result.template emplace<result_t>(Tag(), std::forward(args)...); } catch (...) {if constexpr (!nothrow) state.async-result.template emplace<tuple<set_error_t, exception_ptr>>(set_error, current_exception()); } start(state.op-state);};
Let out_sndr be a subexpression denoting a sender returned from schedule_from(sch, sndr) or one equal to such, and let OutSndr be the type decltype((out_sndr)).
Let out_rcvr be a subexpression denoting a receiver that has an environment of type Env such that sender_in<OutSndr, Env> is true.
Let op be an lvalue referring to the operation state that results from connecting out_sndr with out_rcvr.
Calling start(op) shall start sndr on the current execution agent and execute completion operations on out_rcvr on an execution agent of the execution resource associated with sch.
If scheduling onto sch fails, an error completion on out_rcvr shall be executed on an unspecified execution agent.