33 Execution control library [exec]

33.15 Parallel scheduler [exec.par.scheduler]

namespace std::execution { class parallel_scheduler { unspecified }; }
parallel_scheduler models scheduler.
Let sch be an object of type parallel_scheduler, and let BACKEND-OF(sch) be *ptr, where sch is associated with ptr.
The expression get_forward_progress_guarantee(sch) has the value forward_progress_guarantee​::​​parallel.
Let sch2 be an object of type parallel_scheduler.
Two objects sch and sch2 compare equal if and only if BACKEND-OF(sch) and BACKEND-OF(sch2) refer to the same object.
Let rcvr be a receiver.
A proxy for rcvr with base B is an lvalue r of type B such that:
  • r.set_value() has effects equivalent to set_value(std​::​move(rcvr)).
  • r.set_error(e), where e is an exception_ptr object, has effects equivalent to set_error(std​::​move(​rcvr), std​::​move(e)).
  • r.set_stopped() has effects equivalent to set_stopped(std​::​move(rcvr)).
A preallocated backend storage for a proxy r is an object s of type span<byte> such that the range s remains valid and may be overwritten until one of set_value, set_error, or set_stopped is called on r.
[Note 1: 
The storage referenced by s can be used as temporary storage for operations launched via calls to parallel_scheduler_backend.
— end note]
Let b be BACKEND-OF(sch), let sndr be the object returned by schedule(sch), and let rcvr be a receiver.
If rcvr is connected to sndr and the resulting operation state is started, then:
  • If sndr completes successfully, then b.schedule(r, s) is called, where
    • r is a proxy for rcvr with base parallel_scheduler_replacement​::​receiver_proxy and
    • s is a preallocated backend storage for r.
  • All other completion operations are forwarded unchanged.
The expression get_domain(sch) returns an expression of exposition-only type parallel-scheduler-domain, that is equivalent with:
struct parallel-scheduler-domain { template<sender-for<bulk_chunked_t> Sndr, queryable Env> static constexpr decltype(auto) transform_sender(set_value_t, Sndr&& sndr, const Env& env) const noexcept { return see below; } template<sender-for<bulk_unchunked_t> Sndr, queryable Env> static constexpr decltype(auto) transform_sender(set_value_t, Sndr&& sndr, const Env& env) const noexcept { return see below; } };
For argument sndr of the above transform_sender, let child, pol, shape and f be defined by the following declarations: auto& [_, data, child] = sndr; auto& [pol, shape, f] = data;
Let p be
  • true, if the type of the expression pol is cv parallel_policy or cv parallel_unsequenced_policy;
  • implementation-defined, if pol is an implementation-defined execution policy;
  • false, otherwise.
The transform_sender overload that accepts senders with tag bulk_chunked_t returns a sender such that if it is connected to a receiver rcvr and the resulting operation state is started, then:
  • If child completes with values vals, let args be a pack of lvalue subexpressions designating vals, then b.schedule_bulk_chunked(p ? shape : 1, r, s) is called, where
    • r is a proxy for rcvr with base parallel_scheduler_replacement​::​bulk_item_receiver_proxy such that r.execute(i, j) for indices i and j has effects equivalent to f(i, j, args...) if p is true and f(0, shape, args...) otherwise; and
    • s is a preallocated backend storage for r.
  • All other completion operations are forwarded unchanged.
The transform_sender overload that accepts senders with tag bulk_unchunked_t returns a sender such that if it is connected to a receiver rcvr and the resulting operation state is started, then:
  • If child completes with values vals, let args be a pack of lvalue subexpressions designating vals, then b.schedule_bulk_unchunked(p ? shape : 1, r, s) is called, where
    • r is a proxy for rcvr with base parallel_scheduler_replacement​::​bulk_item_receiver_proxy such that r.execute(i, i + 1) for index i has effects equivalent to f(i, args...) if p is true and for (decltype(shape) i = 0; i < shape; i++) { f(i, args...); } otherwise; and
    • s is a preallocated backend storage for r.
  • All other completion operations are forwarded unchanged.
parallel_scheduler get_parallel_scheduler();
Effects: Let eb be the result of parallel_scheduler_replacement​::​query_parallel_scheduler_backend().
If eb == nullptr is true, calls terminate ([except.terminate]).
Otherwise, returns a parallel_scheduler object associated with eb.