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 and sndr is not a pipeable sender adaptor closure object ([exec.adapt.obj]), or
  • decltype((sndr)) satisfies sender and sndr is also a pipeable sender adaptor closure object.
Otherwise, if decltype((sndr)) satisfies sender, the expression on(sch, sndr) is expression-equivalent to make-sender(on, sch, sndr).
For subexpressions sndr, sch, and closure, if the expression on(sndr, sch, closure) is ill-formed; otherwise, it is expression-equivalent to make-sender(​on, product-typesch, closure, sndr).
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 expression on.transform_sender(out_sndr, env) is ill-formed.
Otherwise, the expression on.transform_sender(set_value, out_sndr, env) has effects equivalent to: auto&& [_, data, child] = out_sndr; if constexpr (scheduler<decltype(data)>) { auto orig_sch = call-with-default(get_start_scheduler, not-a-scheduler(), env); 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 = call-with-default( get_completion_scheduler<set_value_t>, not-a-scheduler(), get_env(child), env); return continues_on( std::forward_like<OutSndr>(closure)(continues_on(std::forward_like<OutSndr>(child), sch)), orig_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, which is obtained by get_start_scheduler(get_env(rcvr));
  • start sndr on an execution agent belonging to sch'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 get_completion_scheduler<set_value_t>(get_env(
    sndr), get_env(out_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.