33 Execution control library [exec]

33.13 Coroutine utilities [exec.coro.util]

33.13.5 execution​::​task_scheduler [exec.task.scheduler]

namespace std::execution { class task_scheduler { class ts-domain; // exposition only template<scheduler Sch> class backend-for; // exposition only public: using scheduler_concept = scheduler_tag; template<class Sch, class Allocator = allocator<void>> requires (!same_as<task_scheduler, remove_cvref_t<Sch>>) && scheduler<Sch> explicit task_scheduler(Sch&& sch, Allocator alloc = {}); task_scheduler(const task_scheduler&) = default; task_scheduler& operator=(const task_scheduler&) = default; see below schedule(); friend bool operator==(const task_scheduler& lhs, const task_scheduler& rhs) noexcept; template<class Sch> requires (!same_as<task_scheduler, Sch>) && scheduler<Sch> friend bool operator==(const task_scheduler& lhs, const Sch& rhs) noexcept; private: // see [exec.parschedrepl.psb] shared_ptr<parallel_scheduler_replacement::parallel_scheduler_backend> sch_; // exposition only }; }
task_scheduler is a class that models scheduler ([exec.sched]).
Given an object s of type task_scheduler, let SCHED(s) be the object pointed to by the pointer owned by s.sch_.
The expression get_forward_progress_guarantee(s) is equivalent to get_forward_progress_guarantee(SCHED(s)).
The expression get_completion_domain<set_value_t>(s) is equivalent to task_scheduler​::​ts-domain().
template<class Sch, class Allocator = allocator<void>> requires(!same_as<task_scheduler, remove_cvref_t<Sch>>) && scheduler<Sch> explicit task_scheduler(Sch&& sch, Allocator alloc = {});
Mandates: Sch satisfies infallible-scheduler<env<>>.
Effects: Initializes sch_ with: allocate_shared<backend-for<remove_cvref_t<Sch>>>(alloc, std::forward<Sch>(sch))
Recommended practice: Implementations should avoid the use of dynamically allocated memory for small scheduler objects.
Remarks: Any allocations performed by calls on *this are performed using a copy of alloc.
bool operator==(const task_scheduler& lhs, const task_scheduler& rhs) noexcept;
Effects: Equivalent to: return lhs == SCHED(rhs);
template<class Sch> requires (!same_as<task_scheduler, Sch>) && scheduler<Sch> bool operator==(const task_scheduler& lhs, const Sch& rhs) noexcept;
Returns: false if the type of SCHED(lhs) is not Sch, otherwise SCHED(lhs) == rhs.
For an lvalue r of a type derived from receiver_proxy, let WRAP-RCVR(r) be an object of a type that models receiver and whose completion handlers result in invoking the corresponding completion handlers of r.
namespace std::execution { template<scheduler Sch> class task_scheduler::backend-for : public parallel_scheduler_replacement::parallel_scheduler_backend { // exposition only public: explicit backend-for(Sch sch) : sched_(std::move(sch)) {} void schedule(receiver_proxy& r, span<byte> s) noexcept override; void schedule_bulk_chunked(size_t shape, bulk_item_receiver_proxy& r, span<byte> s) noexcept override; void schedule_bulk_unchunked(size_t shape, bulk_item_receiver_proxy& r, span<byte> s) noexcept override; private: Sch sched_; }; }
Let env be a pack of subexpressions, and let just-sndr-like be a sender whose only value completion signature is set_value_t() and for which the expression get_completion_scheduler<set_value_t>(get_env(just-sndr-like), env...) is expression-equivalent to get_completion_scheduler<set_value_t>(sched_, env...).
void schedule(receiver_proxy& r, span<byte> s) noexcept override;
Effects: Constructs an operation state os with connect(schedule(sched_), WRAP-RCVR(r)) and calls start(os).
void schedule_bulk_chunked(size_t shape, bulk_item_receiver_proxy& r, span<byte> s) noexcept override;
Effects: Let chunk_size be an integer less than or equal to shape, let num_chunks be (shape + chunk_size - 1) / chunk_size, and let fn be a function object such that for an integer i, fn(i) calls r.execute(i * chunk_size, m), where m is the lesser of (i + 1) * chunk_size and shape.
Constructs an operation state os as if with connect(bulk(just-sndr-like, par, num_chunks, fn), WRAP-RCVR(r)) and calls start(os).
void schedule_bulk_unchunked(size_t shape, bulk_item_receiver_proxy& r, span<byte> s) noexcept override;
Effects: Let fn be a function object such that for an integer i, fn(i) is equivalent to r.execute(i, i + 1).
Constructs an operation state os as if with connect(bulk(just-sndr-like, par, shape, fn), WRAP-RCVR(r)) and calls start(os).
see below schedule();
Returns: A prvalue ts-sndr whose type models sender such that:
  • get_completion_scheduler<set_value_t>(get_env(ts-sndr)) is equal to *this.
  • get_completion_domain<set_value_t>(get_env(ts-sndr)) is expression-equivalent to ts-domain().
  • If a receiver rcvr is connected to ts-sndr and the resulting operation state is started, calls sch_->schedule(r, s), where
  • For any type E, completion_signatures_of_t<decltype(ts-sndr), E> denotes completion_signatures<set_value_t()> if unstoppable_token<stop_token_of_t<E>> is true, and otherwise completion_signatures<set_value_t(), set_stopped_t()>.
namespace std::execution { class task_scheduler::ts-domain : public default_domain { // exposition only public: template<class BulkSndr, class Env> static constexpr auto transform_sender(set_value_t, BulkSndr&& bulk_sndr, const Env& env) noexcept(see below); }; }
template<class BulkSndr, class Env> static constexpr auto transform_sender(BulkSndr&& bulk_sndr, const Env& env) noexcept(is_nothrow_constructible_v<decay_t<BulkSndr>, BulkSndr>);
Constraints:
Effects: Equivalent to: auto& [_, data, child] = bulk_sndr; auto& [_, shape, fn] = data; auto sch = call-with-default(get_completion_scheduler<set_value_t>, not-a-scheduler(), get_env(child), FWD-ENV(env)); return e; where e is not-a-sender() if the type of sch is not task_scheduler; otherwise, it is a prvalue whose type models sender such that, if it is connected to a receiver rcvr and the resulting operation state is started, child is connected to an unspecified receiver R and started.
The expression get_env(R) is expression-equivalent to FWD-ENV(get_env(rcvr-copy)), where rcvr-copy is an lvalue subexpression designating an object decay-copied from rcvr.
If child completes with an error or a stopped completion, the completion operation is forwarded unchanged to rcvr.
Otherwise, let args be a pack of lvalue subexpressions designating objects decay-copied from the value result datums.
Then:
  • If bulk_sndr was the result of the evaluation of an expression equivalent to bulk_chunked(child, policy, shape, fn) or a copy of such, then sch_->schedule_bulk_chunked(shape, r, s) is called where r is a bulk chunked proxy ([exec.par.scheduler]) for rcvr with callable fn and arguments args, and s is a preallocated backend storage for r.
  • Otherwise, calls sch_->schedule_bulk_unchunked(shape, r, s) where r is a bulk unchunked proxy for rcvr with callable fn and arguments args, and s is a preallocated backend storage for r.