212 lines
8.4 KiB
Markdown
212 lines
8.4 KiB
Markdown
[exec.on]
|
||
|
||
# 33 Execution control library [[exec]](./#exec)
|
||
|
||
## 33.9 Senders [[exec.snd]](exec.snd#exec.on)
|
||
|
||
### 33.9.12 Sender adaptors [[exec.adapt]](exec.adapt#exec.on)
|
||
|
||
#### 33.9.12.8 execution::on [exec.on]
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3561)
|
||
|
||
The on sender adaptor has two forms:
|
||
|
||
- [(1.1)](#1.1)
|
||
|
||
on(sch, sndr),
|
||
which starts a sender sndr on an execution agent
|
||
belonging to a scheduler sch's associated execution resource and
|
||
that, upon sndr's completion,
|
||
transfers execution back to the execution resource
|
||
on which the on sender was started[.](#1.1.sentence-1)
|
||
|
||
- [(1.2)](#1.2)
|
||
|
||
on(sndr, sch, closure),
|
||
which upon completion of a sender sndr,
|
||
transfers execution to an execution agent
|
||
belonging to a scheduler sch's associated execution resource,
|
||
then executes a sender adaptor closure closure with the async results of the sender, and
|
||
that then transfers execution back to the execution resource
|
||
on which sndr completed[.](#1.2.sentence-1)
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3582)
|
||
|
||
The name on denotes a pipeable sender adaptor object[.](#2.sentence-1)
|
||
|
||
For subexpressions sch and sndr,on(sch, sndr) is ill-formed if any of the following is true:
|
||
|
||
- [(2.1)](#2.1)
|
||
|
||
decltype((sch)) does not satisfy [scheduler](exec.sched#concept:scheduler "33.6 Schedulers [exec.sched]"), or
|
||
|
||
- [(2.2)](#2.2)
|
||
|
||
decltype((sndr)) does not satisfy [sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]") andsndr is not
|
||
a pipeable sender adaptor closure object ([[exec.adapt.obj]](exec.adapt.obj "33.9.12.2 Closure objects")), or
|
||
|
||
- [(2.3)](#2.3)
|
||
|
||
decltype((sndr)) satisfies [sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]") andsndr is also a pipeable sender adaptor closure object[.](#2.sentence-2)
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3598)
|
||
|
||
Otherwise, if decltype((sndr)) satisfies [sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]"),
|
||
the expression on(sch, sndr) is expression-equivalent to:transform_sender(*query-with-default*(get_domain, sch, default_domain()), *make-sender*(on, sch, sndr)) except that sch is evaluated only once[.](#3.sentence-1)
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3608)
|
||
|
||
For subexpressions sndr, sch, and closure, if
|
||
|
||
- [(4.1)](#4.1)
|
||
|
||
decltype((sch)) does not satisfy [scheduler](exec.sched#concept:scheduler "33.6 Schedulers [exec.sched]"), or
|
||
|
||
- [(4.2)](#4.2)
|
||
|
||
decltype((sndr)) does not satisfy [sender](exec.snd.concepts#concept:sender "33.9.3 Sender concepts [exec.snd.concepts]"), or
|
||
|
||
- [(4.3)](#4.3)
|
||
|
||
closure is not a pipeable sender adaptor closure object ([[exec.adapt.obj]](exec.adapt.obj "33.9.12.2 Closure objects")),
|
||
|
||
the expression on(sndr, sch, closure) is ill-formed;
|
||
otherwise, it is expression-equivalent to:transform_sender(*get-domain-early*(sndr), *make-sender*(on, *product-type*{sch, closure}, sndr)) except that sndr is evaluated only once[.](#4.sentence-1)
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3627)
|
||
|
||
Let out_sndr and env be subexpressions,
|
||
let OutSndr be decltype((out_sndr)), and
|
||
let Env be decltype((env))[.](#5.sentence-1)
|
||
|
||
If [*sender-for*](exec.snd.concepts#concept:sender-for "33.9.3 Sender concepts [exec.snd.concepts]")<OutSndr, on_t> is false,
|
||
then the expressions on.transform_env(out_sndr, env) andon.transform_sender(out_sndr, env) are ill-formed[.](#5.sentence-2)
|
||
|
||
[6](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3635)
|
||
|
||
Otherwise:
|
||
Let *not-a-scheduler* be an unspecified empty class type[.](#6.sentence-1)
|
||
|
||
[7](#7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3639)
|
||
|
||
The expression on.transform_env(out_sndr, env) has effects equivalent to:auto&& [_, data, _] = out_sndr;if constexpr ([scheduler](exec.sched#concept:scheduler "33.6 Schedulers [exec.sched]")<decltype(data)>) {return *JOIN-ENV*(*SCHED-ENV*(std::forward_like<OutSndr>(data)), *FWD-ENV*(std::forward<Env>(env)));} else {return std::forward<Env>(env);}
|
||
|
||
[8](#8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3651)
|
||
|
||
The expression on.transform_sender(out_sndr, env) has effects equivalent to:auto&& [_, data, child] = out_sndr;if constexpr ([scheduler](exec.sched#concept:scheduler "33.6 Schedulers [exec.sched]")<decltype(data)>) {auto orig_sch =*query-with-default*(get_scheduler, env, *not-a-scheduler*()); if constexpr ([same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<decltype(orig_sch), *not-a-scheduler*>) {return *not-a-sender*{}; } else {return continues_on( starts_on(std::forward_like<OutSndr>(data), std::forward_like<OutSndr>(child)),
|
||
std::move(orig_sch)); }} else {auto& [sch, closure] = data; auto orig_sch = *query-with-default*( get_completion_scheduler<set_value_t>,
|
||
get_env(child), *query-with-default*(get_scheduler, env, *not-a-scheduler*())); if constexpr ([same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<decltype(orig_sch), *not-a-scheduler*>) {return *not-a-sender*{}; } else {return write_env( continues_on( std::forward_like<OutSndr>(closure)( continues_on( write_env(std::forward_like<OutSndr>(child), *SCHED-ENV*(orig_sch)),
|
||
sch)),
|
||
orig_sch), *SCHED-ENV*(sch)); }}
|
||
|
||
[9](#9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3689)
|
||
|
||
Let out_sndr be a subexpression denoting
|
||
a sender returned from on(sch, sndr) or one equal to such, and
|
||
let OutSndr be the type decltype((out_sndr))[.](#9.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[.](#9.sentence-2)
|
||
|
||
Let op be an lvalue referring to the operation state
|
||
that results from connecting out_sndr with out_rcvr[.](#9.sentence-3)
|
||
|
||
Calling start(op) shall
|
||
|
||
- [(9.1)](#9.1)
|
||
|
||
remember the current scheduler, get_scheduler(get_env(rcvr));
|
||
|
||
- [(9.2)](#9.2)
|
||
|
||
start sndr on an execution agent belonging tosch's associated execution resource;
|
||
|
||
- [(9.3)](#9.3)
|
||
|
||
upon sndr's completion,
|
||
transfer execution back to the execution resource
|
||
associated with the scheduler remembered in step 1; and
|
||
|
||
- [(9.4)](#9.4)
|
||
|
||
forward sndr's async result to out_rcvr[.](#9.sentence-4)
|
||
|
||
If any scheduling operation fails,
|
||
an error completion on out_rcvr shall be executed
|
||
on an unspecified execution agent[.](#9.sentence-5)
|
||
|
||
[10](#10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L3716)
|
||
|
||
Let out_sndr be a subexpression denoting
|
||
a sender returned from on(sndr, sch, closure) or one equal to such, and
|
||
let OutSndr be the type decltype((out_sndr))[.](#10.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[.](#10.sentence-2)
|
||
|
||
Let op be an lvalue referring to the operation state
|
||
that results from connecting out_sndr with out_rcvr[.](#10.sentence-3)
|
||
|
||
Calling start(op) shall
|
||
|
||
- [(10.1)](#10.1)
|
||
|
||
remember the current scheduler,
|
||
which is the first of the following expressions that is well-formed:
|
||
* [(10.1.1)](#10.1.1)
|
||
|
||
get_completion_scheduler<set_value_t>(get_env(sndr))
|
||
|
||
* [(10.1.2)](#10.1.2)
|
||
|
||
get_scheduler(get_env(rcvr));
|
||
|
||
- [(10.2)](#10.2)
|
||
|
||
start sndr on the current execution agent;
|
||
|
||
- [(10.3)](#10.3)
|
||
|
||
upon sndr's completion,
|
||
transfer execution to an agent
|
||
owned by sch's associated execution resource;
|
||
|
||
- [(10.4)](#10.4)
|
||
|
||
forward sndr's async result as if by
|
||
connecting and starting a sender closure(S),
|
||
where S is a sender
|
||
that completes synchronously with sndr's async result; and
|
||
|
||
- [(10.5)](#10.5)
|
||
|
||
upon completion of the operation started in the previous step,
|
||
transfer execution back to the execution resource
|
||
associated with the scheduler remembered in step 1 and
|
||
forward the operation's async result to out_rcvr[.](#10.sentence-4)
|
||
|
||
If any scheduling operation fails,
|
||
an error completion on out_rcvr shall be executed on
|
||
an unspecified execution agent[.](#10.sentence-5)
|