8.4 KiB
[exec.on]
33 Execution control library [exec]
33.9 Senders [exec.snd]
33.9.12 Sender adaptors [exec.adapt]
33.9.12.8 execution::on [exec.on]
The on sender adaptor has two forms:
-
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.
-
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.
The name on denotes a pipeable sender adaptor object.
For subexpressions sch and sndr,on(sch, sndr) is ill-formed if any of the following is true:
decltype((sch)) does not satisfy scheduler, or
decltype((sndr)) does not satisfy sender andsndr is not a pipeable sender adaptor closure object ([exec.adapt.obj]), or
decltype((sndr)) satisfies sender andsndr is also a pipeable sender adaptor closure object.
Otherwise, if decltype((sndr)) satisfies sender, 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.
For subexpressions sndr, sch, and closure, if
decltype((sch)) does not satisfy scheduler, or
decltype((sndr)) does not satisfy sender, or
closure is not a pipeable sender adaptor closure object ([exec.adapt.obj]),
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.
Let out_sndr and env be subexpressions, let OutSndr be decltype((out_sndr)), and let Env be decltype((env)).
If sender-for<OutSndr, on_t> is false, then the expressions on.transform_env(out_sndr, env) andon.transform_sender(out_sndr, env) are ill-formed.
Otherwise: Let not-a-scheduler be an unspecified empty class type.
The expression on.transform_env(out_sndr, env) has effects equivalent to:auto&& [_, data, _] = out_sndr;if constexpr (scheduler<decltype(data)>) {return JOIN-ENV(SCHED-ENV(std::forward_like(data)), FWD-ENV(std::forward(env)));} else {return std::forward(env);}
The expression on.transform_sender(out_sndr, env) has effects equivalent to:auto&& [_, data, child] = out_sndr;if constexpr (scheduler<decltype(data)>) {auto orig_sch =query-with-default(get_scheduler, env, not-a-scheduler()); if constexpr (same_as<decltype(orig_sch), not-a-scheduler>) {return not-a-sender{}; } else {return continues_on( starts_on(std::forward_like(data), std::forward_like(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<decltype(orig_sch), not-a-scheduler>) {return not-a-sender{}; } else {return write_env( continues_on( std::forward_like(closure)( continues_on( write_env(std::forward_like(child), SCHED-ENV(orig_sch)), sch)), orig_sch), SCHED-ENV(sch)); }}
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)).
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
remember the current scheduler, get_scheduler(get_env(rcvr));
start sndr on an execution agent belonging tosch's associated execution resource;
upon sndr's completion, transfer execution back to the execution resource associated with the scheduler remembered in step 1; and
forward sndr's async result to out_rcvr.
If any scheduling operation fails, an error completion on out_rcvr shall be executed on an unspecified execution agent.
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)).
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
remember the current scheduler, which is the first of the following expressions that is well-formed:
get_completion_scheduler<set_value_t>(get_env(sndr))
get_scheduler(get_env(rcvr));
start sndr on the current execution agent;
upon sndr's completion, transfer execution to an agent owned by sch's associated execution resource;
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
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.
If any scheduling operation fails, an error completion on out_rcvr shall be executed on an unspecified execution agent.