|
7447 | 7447 | \begin{codeblock} |
7448 | 7448 | namespace std::execution { |
7449 | 7449 | class @\libglobal{task_scheduler}@ { |
7450 | | - class @\exposidnc{ts-sender}@; // \expos |
| 7450 | + class @\exposid{ts-domain}@; // \expos |
7451 | 7451 |
|
7452 | | - template<@\libconcept{receiver}@ R> |
7453 | | - class @\exposidnc{state}@; // \expos |
| 7452 | + template<@\libconcept{scheduler}@ Sch> |
| 7453 | + class @\exposid{backend-for}@; // \expos |
7454 | 7454 |
|
7455 | 7455 | public: |
7456 | 7456 | using scheduler_concept = scheduler_t; |
7457 | 7457 |
|
7458 | 7458 | template<class Sch, class Allocator = allocator<void>> |
7459 | | - requires (!@\libconcept{same_as}@<task_scheduler, remove_cvref_t<Sch>>) |
7460 | | - && @\libconcept{scheduler}@<Sch> |
| 7459 | + requires (!@\libconcept{same_as}@<task_scheduler, remove_cvref_t<Sch>>) && @\libconcept{scheduler}@<Sch> |
7461 | 7460 | explicit task_scheduler(Sch&& sch, Allocator alloc = {}); |
7462 | 7461 |
|
7463 | 7462 | task_scheduler(const task_scheduler&) = default; |
7464 | 7463 | task_scheduler& operator=(const task_scheduler&) = default; |
7465 | 7464 |
|
7466 | | - @\exposid{ts-sender}@ schedule(); |
| 7465 | + @\seebelow@ schedule(); |
7467 | 7466 |
|
7468 | | - friend bool operator==(const task_scheduler& lhs, const task_scheduler& rhs) |
7469 | | - noexcept; |
| 7467 | + friend bool operator==(const task_scheduler& lhs, const task_scheduler& rhs) noexcept; |
7470 | 7468 | template<class Sch> |
7471 | | - requires (!@\libconcept{same_as}@<task_scheduler, Sch>) |
7472 | | - && @\libconcept{scheduler}@<Sch> |
| 7469 | + requires (!@\libconcept{same_as}@<task_scheduler, Sch>) && @\libconcept{scheduler}@<Sch> |
7473 | 7470 | friend bool operator==(const task_scheduler& lhs, const Sch& rhs) noexcept; |
7474 | 7471 |
|
7475 | 7472 | private: |
7476 | | - shared_ptr<void> @\exposidnc{sch_}@; // \expos |
| 7473 | + // see \ref{exec.sysctxrepl.psb} |
| 7474 | + shared_ptr<system_context_replaceability::parallel_scheduler_backend> @\exposidnc{sch_}@; // \expos |
7477 | 7475 | }; |
7478 | 7476 | } |
7479 | 7477 | \end{codeblock} |
|
7484 | 7482 | Given an object \tcode{s} of type \tcode{task_scheduler}, let |
7485 | 7483 | \tcode{\exposid{SCHED}(s)} be the object |
7486 | 7484 | pointed to by the pointer owned by \tcode{s.\exposid{sch_}}. |
| 7485 | +The expression \tcode{get_forward_progress_guarantee(s)} is equivalent to |
| 7486 | +\tcode{get_forward_progress_guarantee(\exposid{SCHED}(s))}. |
| 7487 | +The expression \tcode{get_completion_domain<set_value_t>(s)} is equivalent to |
| 7488 | +\tcode{task_scheduler::\exposid{ts-domain}()}. |
7487 | 7489 |
|
7488 | 7490 | \indexlibraryctor{task_scheduler} |
7489 | 7491 | \begin{itemdecl} |
|
7498 | 7500 |
|
7499 | 7501 | \pnum |
7500 | 7502 | \effects |
7501 | | -Initialize \exposid{sch_} with |
7502 | | -\tcode{allocate_shared<remove_cvref_t<Sch>>(alloc,\brk{} std::forward<Sch>\brk{}(sch))}. |
| 7503 | +Initializes \exposid{sch_} with: |
| 7504 | +\begin{codeblock} |
| 7505 | +allocate_shared<@\exposid{backend-for}@<remove_cvref_t<Sch>>>(alloc, std::forward<Sch>(sch)) |
| 7506 | +\end{codeblock} |
7503 | 7507 |
|
7504 | 7508 | \pnum |
7505 | 7509 | \recommended |
|
7508 | 7512 |
|
7509 | 7513 | \pnum |
7510 | 7514 | \remarks |
7511 | | -Any allocations performed by construction of \exposid{ts-sender} or |
7512 | | -\exposid{state} objects resulting from calls on \tcode{*this} are |
| 7515 | +Any allocations performed by calls on \tcode{*this} are |
7513 | 7516 | performed using a copy of \tcode{alloc}. |
7514 | 7517 | \end{itemdescr} |
7515 | 7518 |
|
7516 | | -\indexlibrarymember{scheduler}{task_scheduler}% |
7517 | | -\begin{itemdecl} |
7518 | | -@\exposid{ts-sender}@ schedule(); |
7519 | | -\end{itemdecl} |
7520 | | -\begin{itemdescr} |
7521 | | -\pnum |
7522 | | -\effects |
7523 | | -Returns an object of type \exposid{ts-sender} containing a sender |
7524 | | -initialized with \tcode{sched\-ule(\brk{}\exposid{SCHED}\brk{}(*this))}. |
7525 | | -\end{itemdescr} |
7526 | | - |
7527 | 7519 | \indexlibrarymember{operator==}{task_scheduler}% |
7528 | 7520 | \begin{itemdecl} |
7529 | 7521 | bool operator==(const task_scheduler& lhs, const task_scheduler& rhs) noexcept; |
|
7549 | 7541 | \end{itemdescr} |
7550 | 7542 |
|
7551 | 7543 | \pnum |
| 7544 | +For an lvalue \tcode{r} of a type derived from \tcode{receiver_proxy}, |
| 7545 | +let \tcode{\exposid{WRAP-RCVR}(r)} be an object of a type |
| 7546 | +that models \libconcept{receiver} and |
| 7547 | +whose completion handlers result in |
| 7548 | +invoking the corresponding completion handlers of \tcode{r}. |
7552 | 7549 | \begin{codeblock} |
7553 | 7550 | namespace std::execution { |
7554 | | - class task_scheduler::@\exposidnc{ts-sender}@ { // \expos |
| 7551 | + template<@\libconcept{scheduler}@ Sch> |
| 7552 | + class task_scheduler::@\exposid{backend-for}@ |
| 7553 | + : public system_context_replaceability::parallel_scheduler_backend { // \expos |
7555 | 7554 | public: |
7556 | | - using sender_concept = sender_t; |
| 7555 | + explicit @\exposid{backend-for}@(Sch sch) : @\exposid{sched_}@(std::move(sch)) {} |
7557 | 7556 |
|
7558 | | - template<@\libconcept{receiver}@ Rcvr> |
7559 | | - @\exposid{state}@<Rcvr> connect(Rcvr&& rcvr) &&; |
| 7557 | + void schedule(receiver_proxy& r, span<byte> s) noexcept override; |
| 7558 | + void schedule_bulk_chunked(size_t shape, bulk_item_receiver_proxy& r, |
| 7559 | + span<byte> s) noexcept override; |
| 7560 | + void schedule_bulk_unchunked(size_t shape, bulk_item_receiver_proxy& r, |
| 7561 | + span<byte> s) noexcept override; |
| 7562 | + |
| 7563 | + private: |
| 7564 | + Sch @\exposid{sched_}@; |
7560 | 7565 | }; |
7561 | 7566 | } |
7562 | 7567 | \end{codeblock} |
7563 | | -\exposid{ts-sender} is an exposition-only class that models |
7564 | | -\libconcept{sender}\iref{exec.snd} and for which |
7565 | | -\tcode{completion_signatures_of_t<\exposid{ts-sender}, E>} denotes |
7566 | | -\tcode{completion_signatures<set_value_t()>} |
7567 | | -if \tcode{unstoppable_token<stop_token_of_t<E>>} is \tcode{true}, and |
7568 | | -otherwise \tcode{completion_signatures<set_value_t(), set_stopped_t()>}. |
7569 | 7568 |
|
7570 | 7569 | \pnum |
7571 | | -Let \tcode{\placeholder{sch}} be an object of type \tcode{task_scheduler} |
7572 | | -and let \tcode{sndr} be an object of type \exposid{ts-sender} obtained |
7573 | | -from \tcode{schedule(\placeholder{sch})}. |
7574 | | -Then \tcode{get_completion_scheduler<set_value_t>(get_env(sndr)) == \placeholder{sch}} |
7575 | | -is \tcode{true}. |
7576 | | -The object \tcode{\exposid{SENDER}(sndr)} is the sender object contained by |
7577 | | -\tcode{sndr} or an object move constructed from it. |
| 7570 | +Let \tcode{env} be a pack of subexpressions, and |
| 7571 | +let \exposid{just-sndr-like} be a sender |
| 7572 | +whose only value completion signature is \tcode{set_value_t()} and |
| 7573 | +for which the expression |
| 7574 | +\tcode{get_completion_scheduler<set_value_t>(get_env(\exposid{just-sndr-like)}, env...)} |
| 7575 | +is expression-equivalent to |
| 7576 | +\tcode{get_completion_scheduler<set_value_t>(\exposid{sched_}, env...)}. |
7578 | 7577 |
|
7579 | | -\indexlibrarymember{connect}{task_scheduler::\exposid{ts-sender}}% |
7580 | 7578 | \begin{itemdecl} |
7581 | | -template<@\libconcept{receiver}@ Rcvr> |
7582 | | - @\exposid{state}@<Rcvr> connect(Rcvr&& rcvr) &&; |
| 7579 | +void schedule(receiver_proxy& r, span<byte> s) noexcept override; |
| 7580 | +\end{itemdecl} |
| 7581 | + |
| 7582 | +\begin{itemdescr} |
| 7583 | +\pnum |
| 7584 | +\effects |
| 7585 | +Constructs an operation state \tcode{os} |
| 7586 | +with \tcode{connect(schedule(\exposid{sched_}), \exposid{WRAP-RCVR}(r))} and |
| 7587 | +calls \tcode{start(os)}. |
| 7588 | +\end{itemdescr} |
| 7589 | + |
| 7590 | +\begin{itemdecl} |
| 7591 | +void schedule_bulk_chunked(size_t shape, bulk_item_receiver_proxy& r, |
| 7592 | + span<byte> s) noexcept override; |
7583 | 7593 | \end{itemdecl} |
| 7594 | + |
7584 | 7595 | \begin{itemdescr} |
7585 | 7596 | \pnum |
7586 | 7597 | \effects |
7587 | | -Let \tcode{\placeholder{r}} be an object of a type that models \libconcept{receiver} |
7588 | | -and whose completion handlers result in invoking the corresponding |
7589 | | -completion handlers of \tcode{rcvr} or copy thereof. |
7590 | | -Returns an object of type \tcode{\exposid{state}<Rcvr>} containing |
7591 | | -an operation state object initialized with \tcode{connect(\exposid{SENDER}(*this), |
7592 | | -std::move(\placeholder{r}))}. |
| 7598 | +Let \tcode{chunk_size} be an integer less than or equal to \tcode{shape}, |
| 7599 | +let \tcode{num_chunks} be \tcode{(shape + chunk_size - 1) / chunk_size}, and |
| 7600 | +let \tcode{fn} be a function object such that |
| 7601 | +for an integer \tcode{i}, |
| 7602 | +\tcode{fn(i)} calls \tcode{r.execute(i * chunk_size, m)}, |
| 7603 | +where \tcode{m} is the lesser of \tcode{(i + 1) * chunk_size} and \tcode{shape}. |
| 7604 | +Constructs an operation state \tcode{os} as if with |
| 7605 | +\begin{codeblock} |
| 7606 | +connect(bulk(@\exposid{just-sndr-like}@, par, num_chunks, fn), @\exposid{WRAP-RCVR}@(r)) |
| 7607 | +\end{codeblock} |
| 7608 | +and calls \tcode{start(os)}. |
7593 | 7609 | \end{itemdescr} |
7594 | 7610 |
|
| 7611 | +\begin{itemdecl} |
| 7612 | +void schedule_bulk_unchunked(size_t shape, bulk_item_receiver_proxy& r, |
| 7613 | + span<byte> s) noexcept override; |
| 7614 | +\end{itemdecl} |
| 7615 | + |
| 7616 | +\begin{itemdescr} |
7595 | 7617 | \pnum |
| 7618 | +\effects |
| 7619 | +Let \tcode{fn} be a function object such that |
| 7620 | +for an integer \tcode{i}, |
| 7621 | +\tcode{fn(i)} is equivalent to \tcode{r.execute(i, i + 1)}. |
| 7622 | +Constructs an operation state \tcode{os} as if with |
| 7623 | +\begin{codeblock} |
| 7624 | +connect(bulk(@\exposid{just-sndr-like}@, par, shape, fn), @\exposid{WRAP-RCVR}@(r)) |
| 7625 | +\end{codeblock} |
| 7626 | +and calls \tcode{start(os)}. |
| 7627 | +\end{itemdescr} |
| 7628 | + |
| 7629 | +\begin{itemdecl} |
| 7630 | +@\seebelow@ schedule(); |
| 7631 | +\end{itemdecl} |
| 7632 | + |
| 7633 | +\begin{itemdescr} |
| 7634 | +\pnum |
| 7635 | +\returns |
| 7636 | +A prvalue \exposid{ts-sndr} whose type models \libconcept{sender} such that: |
| 7637 | +\begin{itemize} |
| 7638 | +\item |
| 7639 | +\tcode{get_completion_scheduler<set_value_t>(get_env(\exposid{ts-sndr}))} |
| 7640 | +is equal to \tcode{*this.} |
| 7641 | +\item |
| 7642 | +\tcode{get_completion_domain<set_value_t>(get_env(\exposid{ts-sndr}))} |
| 7643 | +is expression-equivalent to \tcode{\exposid{ts-do\-main}()}. |
| 7644 | +\item |
| 7645 | +If a receiver \tcode{rcvr} is connected to \exposid{ts-sndr} and |
| 7646 | +the resulting operation state is started, |
| 7647 | +calls \tcode{\exposid{sch_}->schedule(r, s)}, where |
| 7648 | +\begin{itemize} |
| 7649 | +\item |
| 7650 | +\tcode{r} is a proxy for \tcode{rcvr} with base |
| 7651 | +\tcode{system_context_replaceability::receiver_proxy}\iref{exec.par.scheduler} |
| 7652 | +and |
| 7653 | +\item |
| 7654 | +\tcode{s} is a preallocated backend storage for \tcode{r}. |
| 7655 | +\end{itemize} |
| 7656 | +\item |
| 7657 | +For any type \tcode{E}, |
| 7658 | +\tcode{completion_signatures_of_t<decltype(\exposid{ts-sndr}), E>} denotes |
| 7659 | +\tcode{completion_signatures<set_value_t()>} if |
| 7660 | +\tcode{\libconcept{unstoppable_token}<stop_token_of_t<E>>} is \tcode{true}, and |
| 7661 | +otherwise \tcode{completion_signatures<set_value_t(), set_stopped_t()>}. |
| 7662 | +\end{itemize} |
| 7663 | +\end{itemdescr} |
| 7664 | + |
7596 | 7665 | \begin{codeblock} |
7597 | 7666 | namespace std::execution { |
7598 | | - template<@\libconcept{receiver}@ R> |
7599 | | - class task_scheduler::@\exposidnc{state}@ { // \expos |
| 7667 | + class task_scheduler::@\exposid{ts-domain}@ : public default_domain { // \expos |
7600 | 7668 | public: |
7601 | | - using operation_state_concept = operation_state_t; |
7602 | | - |
7603 | | - void start() & noexcept; |
| 7669 | + template<class BulkSndr, class Env> |
| 7670 | + static constexpr auto transform_sender(set_value_t, BulkSndr&& bulk_sndr, const Env& env) |
| 7671 | + noexcept(@\seebelow@); |
7604 | 7672 | }; |
7605 | 7673 | } |
7606 | 7674 | \end{codeblock} |
7607 | | -\exposid{state} is an exposition-only class template whose |
7608 | | -specializations model \libconcept{operation_state}\iref{exec.opstate}. |
7609 | 7675 |
|
7610 | | -\indexlibrarymember{start}{task_scheduler::\exposid{state}}% |
7611 | 7676 | \begin{itemdecl} |
7612 | | -void start() & noexcept; |
| 7677 | +template<class BulkSndr, class Env> |
| 7678 | + static constexpr auto transform_sender(BulkSndr&& bulk_sndr, const Env& env) |
| 7679 | + noexcept(is_nothrow_constructible_v<decay_t<BulkSndr>, BulkSndr>); |
7613 | 7680 | \end{itemdecl} |
| 7681 | + |
7614 | 7682 | \begin{itemdescr} |
| 7683 | +\pnum |
| 7684 | +\constraints |
| 7685 | +\begin{itemize} |
| 7686 | +\item |
| 7687 | +\tcode{\libconcept{sender_in}<BulkSndr, Env>} is \tcode{true}, |
| 7688 | +\item |
| 7689 | +\tcode{auto(std::forward<BulkSndr>(bulk_sndr))} is well-formed, and |
| 7690 | +\item |
| 7691 | +either |
| 7692 | +\begin{itemize} |
| 7693 | +\item |
| 7694 | +\tcode{\exposconcept{sender-for}<BulkSndr, bulk_chunked_t>} or |
| 7695 | +\item |
| 7696 | +\tcode{\exposconcept{sender-for}<BulkSndr, bulk_un\-chunked_t>} |
| 7697 | +\end{itemize} |
| 7698 | +is \tcode{true}. |
| 7699 | +\end{itemize} |
| 7700 | + |
7615 | 7701 | \pnum |
7616 | 7702 | \effects |
7617 | | -Equivalent to \tcode{start(st)} where \tcode{st} is the operation |
7618 | | -state object contained by \tcode{*this}. |
| 7703 | +Equivalent to: |
| 7704 | +\begin{codeblock} |
| 7705 | +auto& [_, data, child] = bulk_sndr; |
| 7706 | +auto& [_, shape, fn] = data; |
| 7707 | +auto sch = @\exposidnc{call-with-default}@(get_completion_scheduler<set_value_t>, |
| 7708 | + @\exposidnc{not-a-scheduler}@(), get_env(child), @\exposidnc{FWD-ENV}@(env)); |
| 7709 | +return @$e$@; |
| 7710 | +\end{codeblock} |
| 7711 | +where $e$ is \tcode{\exposid{not-a-sender}()} |
| 7712 | +if the type of \tcode{sch} is not \tcode{task_scheduler}; |
| 7713 | +otherwise, it is a prvalue whose type models \libconcept{sender} such that, |
| 7714 | +if it is connected to a receiver \tcode{rcvr} and |
| 7715 | +the resulting operation state is started, |
| 7716 | +\tcode{child} is connected to an unspecified receiver \tcode{R} and started. |
| 7717 | +The expression \tcode{get_env(R)} |
| 7718 | +is expression-equivalent to \tcode{\exposid{FWD-ENV}(get_env(\exposid{rcvr-copy}))}, |
| 7719 | +where \exposid{rcvr-copy} is an lvalue subexpression |
| 7720 | +designating an object decay-copied from \tcode{rcvr}. |
| 7721 | + |
| 7722 | +If \tcode{child} completes with an error or a stopped completion, |
| 7723 | +the completion operation is forwarded unchanged to \tcode{rcvr}. |
| 7724 | +Otherwise, let \tcode{args} be a pack of lvalue subexpressions |
| 7725 | +designating objects decay-copied from the value result datums. |
| 7726 | +Then: |
| 7727 | +\begin{itemize} |
| 7728 | +\item |
| 7729 | +If \tcode{bulk_sndr} was the result of the evaluation of |
| 7730 | +an expression equivalent to \tcode{bulk_chunked(child, policy, shape, fn)} or |
| 7731 | +a copy of such, |
| 7732 | +then \tcode{\exposid{sch_}->schedule_bulk_chunked(shape, r, s)} is called |
| 7733 | +where \tcode{r} is a bulk chunked proxy\iref{exec.par.scheduler} |
| 7734 | +for \tcode{rcvr} with callable \tcode{fn} and arguments \tcode{args}, and |
| 7735 | +\tcode{s} is a preallocated backend storage for \tcode{r}. |
| 7736 | +\item |
| 7737 | +Otherwise, calls \tcode{\exposid{sch_}->schedule_bulk_unchunked(shape, r, s)} |
| 7738 | +where \tcode{r} is a bulk unchunked proxy for \tcode{rcvr} |
| 7739 | +with callable \tcode{fn} and arguments \tcode{args}, and |
| 7740 | +\tcode{s} is a preallocated backend storage for \tcode{r}. |
| 7741 | +\end{itemize} |
7619 | 7742 | \end{itemdescr} |
7620 | 7743 |
|
7621 | 7744 | \rSec2[exec.task]{\tcode{execution::task}} |
|
0 commit comments