[exec.schedule.from]

# 33 Execution control library [[exec]](./#exec)

## 33.9 Senders [[exec.snd]](exec.snd#exec.schedule.from)

### 33.9.12 Sender adaptors [[exec.adapt]](exec.adapt#exec.schedule.from)

#### 33.9.12.7 execution​::​schedule_from [exec.schedule.from]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3359)

schedule_from schedules work dependent on the completion of a sender
onto a scheduler's associated execution resource[.](#1.sentence-1)

[*Note [1](#note-1)*:

schedule_from is not meant to be used in user code;
it is used in the implementation of continues_on[.](#1.sentence-2)

â *end note*]

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3367)

The name schedule_from denotes a customization point object[.](#2.sentence-1)

For some subexpressions sch and sndr,
let Sch be decltype((sch)) andSndr be decltype((sndr))[.](#2.sentence-2)

If Sch does not satisfy [scheduler](exec.sched#concept:scheduler "33.6 Schedulers [exec.sched]"), orSndr does not satisfy [sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]"),schedule_from(sch, sndr) is ill-formed[.](#2.sentence-3)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3376)

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[.](#3.sentence-1)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3386)

The exposition-only class template *impls-for* ([[exec.snd.expos]](exec.snd.expos "33.9.2 Exposition-only entities"))
is specialized for schedule_from_t as follows:

[ð](#lib:impls-for%3cschedule_from_t%3e)

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*(); };}

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3404)

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)));}

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3413)

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](exec.snd.concepts#concept:sender_in "33.9.3 Sender concepts [exec.snd.concepts]")<*child-type*<Sndr>, *FWD-ENV-T*(env_of_t<Rcvr>)> {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 only*explicit *state-type*(sched_t sch, Rcvr& rcvr) noexcept(nothrow): *rcvr*(rcvr), *op-state*(connect(schedule(sch), receiver_t{this})) {}}; return *state-type*{sch, rcvr};}

[ð](#lib:check-types,impls-for%3cschedule_from_t%3e)

`template<class Sndr, class... Env>
  static consteval void check-types();
`

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3448)

*Effects*: Equivalent to:get_completion_signatures<schedule_result_t<*data-type*<Sndr>>, *FWD-ENV-T*(Env)...>();auto cs = get_completion_signatures<*child-type*<Sndr>, *FWD-ENV-T*(Env)...>();*decay-copyable-result-datums*(cs); // see [[exec.snd.expos]](exec.snd.expos "33.9.2 Exposition-only entities")

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3458)

Objects of the local class *state-type* can be used
to initialize a structured binding[.](#8.sentence-1)

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3462)

Let Sigs be
a pack of the arguments to the completion_signatures specialization
named by completion_signatures_of_t<*child-type*<Sndr>, *FWD-ENV-T*(env_of_t<Rcvr>)>[.](#9.sentence-1)

Let *as-tuple* be an alias template such that*as-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>, Args> && ...)[.](#9.sentence-2)

Let *error-completion* be a pack consisting of
the type set_error_t(exception_ptr) if (*is-nothrow-decay-copy-sig*<Sigs> &&...) is false,
and an empty pack otherwise[.](#9.sentence-3)

Then variant_t denotes
the type variant<monostate, *as-tuple*<Sigs>..., *error-completion*...>,
except with duplicate types removed[.](#9.sentence-4)

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3481)

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 only*void set_value() && noexcept { visit([this]<class Tuple>(Tuple& result) noexcept -> void {if constexpr (![same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<monostate, Tuple>) {auto& [tag, ...args] = result;
 tag(std::move(*state*->*rcvr*), std::move(args)...); }}, *state*->*async-result*); }template<class Error>void set_error(Error&& err) && noexcept { execution::set_error(std::move(*state*->*rcvr*), std::forward<Error>(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*)); }};}

[11](#11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3516)

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[.](#11.sentence-1)

[12](#12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3522)

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*);};

[13](#13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3542)

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))[.](#13.sentence-1)

Let out_rcvr be a subexpression denoting a receiver
that has an environment of type Env such that [sender_in](exec.snd.concepts#concept:sender_in "33.9.3 Sender concepts [exec.snd.concepts]")<OutSndr, Env> is true[.](#13.sentence-2)

Let op be an lvalue referring to the operation state
that results from connecting out_sndr with out_rcvr[.](#13.sentence-3)

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[.](#13.sentence-4)

If scheduling onto sch fails,
an error completion on out_rcvr shall be executed
on an unspecified execution agent[.](#13.sentence-5)
