|
7029 | 7029 | \begin{codeblock} |
7030 | 7030 | namespace std::execution { |
7031 | 7031 | class @\libglobal{task_scheduler}@ { |
7032 | | - class @\exposidnc{ts-sender}@; // \expos |
| 7032 | + class @\exposidnc{ts-domain}@; // \expos |
7033 | 7033 |
|
7034 | | - template<@\libconcept{receiver}@ R> |
7035 | | - class @\exposidnc{state}@; // \expos |
| 7034 | + template<@\libconcept{scheduler}@ Sch> |
| 7035 | + class @\exposid{backend-for}@; // \expos |
7036 | 7036 |
|
7037 | 7037 | public: |
7038 | 7038 | using scheduler_concept = scheduler_t; |
|
7045 | 7045 | task_scheduler(const task_scheduler&) = default; |
7046 | 7046 | task_scheduler& operator=(const task_scheduler&) = default; |
7047 | 7047 |
|
7048 | | - @\exposid{ts-sender}@ schedule(); |
| 7048 | + @\seebelow@ schedule(); |
7049 | 7049 |
|
7050 | 7050 | friend bool operator==(const task_scheduler& lhs, const task_scheduler& rhs) |
7051 | 7051 | noexcept; |
|
7055 | 7055 | friend bool operator==(const task_scheduler& lhs, const Sch& rhs) noexcept; |
7056 | 7056 |
|
7057 | 7057 | private: |
7058 | | - shared_ptr<void> @\exposidnc{sch_}@; // \expos |
| 7058 | + shared_ptr<system_context_replaceability::parallel_scheduler_backend> @\exposidnc{sch_}@; // \expos; see \ref{exec.sysctxrepl.psb} |
7059 | 7059 | }; |
7060 | 7060 | } |
7061 | 7061 | \end{codeblock} |
|
7066 | 7066 | Given an object \tcode{s} of type \tcode{task_scheduler}, let |
7067 | 7067 | \tcode{\exposid{SCHED}(s)} be the object |
7068 | 7068 | pointed to by the pointer owned by \tcode{s.\exposid{sch_}}. |
| 7069 | +The expression \tcode{get_forward_progress_guarantee(s)} is equivalent to |
| 7070 | +\tcode{get_forward_progress_guarantee(SCHED(s))}. |
| 7071 | +The expression \tcode{get_completion_domain<set_value_t>(s)} is equivalent to |
| 7072 | +\tcode{task_scheduler::ts-domain()}. |
7069 | 7073 |
|
7070 | 7074 | \indexlibraryctor{task_scheduler} |
7071 | 7075 | \begin{itemdecl} |
|
7077 | 7081 | \pnum |
7078 | 7082 | \effects |
7079 | 7083 | Initialize \exposid{sch_} with |
7080 | | -\tcode{allocate_shared<remove_cvref_t<Sch>>(alloc,\brk{} std::forward<Sch>\brk{}(sch))}. |
| 7084 | +\tcode{allocate_shared<\exposid{backend-for}<remove_cvref_t<Sch>>>(alloc, std::forward<Sch>(sch))}. |
7081 | 7085 |
|
7082 | 7086 | \pnum |
7083 | 7087 | \recommended |
|
7086 | 7090 |
|
7087 | 7091 | \pnum |
7088 | 7092 | \remarks |
7089 | | -Any allocations performed by construction of \exposid{ts-sender} or |
7090 | | -\exposid{state} objects resulting from calls on \tcode{*this} are |
| 7093 | +Any allocations performed by calls on \tcode{*this} are |
7091 | 7094 | performed using a copy of \tcode{alloc}. |
7092 | 7095 | \end{itemdescr} |
7093 | 7096 |
|
7094 | | -\indexlibrarymember{scheduler}{task_scheduler}% |
7095 | | -\begin{itemdecl} |
7096 | | -@\exposid{ts-sender}@ schedule(); |
7097 | | -\end{itemdecl} |
7098 | | -\begin{itemdescr} |
7099 | | -\pnum |
7100 | | -\effects |
7101 | | -Returns an object of type \exposid{ts-sender} containing a sender |
7102 | | -initialized with \tcode{sched\-ule(\brk{}\exposid{SCHED}\brk{}(*this))}. |
7103 | | -\end{itemdescr} |
7104 | | - |
7105 | 7097 | \indexlibrarymember{operator==}{task_scheduler}% |
7106 | 7098 | \begin{itemdecl} |
7107 | 7099 | bool operator==(const task_scheduler& lhs, const task_scheduler& rhs) noexcept; |
|
7127 | 7119 | \end{itemdescr} |
7128 | 7120 |
|
7129 | 7121 | \pnum |
| 7122 | +For an lvalue \tcode{r} of a type derived from \tcode{receiver_proxy}, |
| 7123 | +let \tcode{\exposid{WRAP-RCVR}(r)}x be an object of a type |
| 7124 | +that models \libconcept{receiver} and |
| 7125 | +whose completion handlers result in |
| 7126 | +invoking the corresponding completion handlers of \tcode{r}. |
7130 | 7127 | \begin{codeblock} |
7131 | 7128 | namespace std::execution { |
7132 | | - class task_scheduler::@\exposidnc{ts-sender}@ { // \expos |
| 7129 | + template<@\libconcept{scheduler}@ Sch> |
| 7130 | + class task_scheduler::@\exposid{backend-for}@ |
| 7131 | + : public system_context_replaceability::parallel_scheduler_backend { // \expos |
7133 | 7132 | public: |
7134 | | - using sender_concept = sender_t; |
| 7133 | + explicit @\exposid{backend-for}@(Sch sch) : @\exposid{sched_}@(std::move(sch)) {} |
7135 | 7134 |
|
7136 | | - template<@\libconcept{receiver}@ Rcvr> |
7137 | | - @\exposid{state}@<Rcvr> connect(Rcvr&& rcvr) &&; |
| 7135 | + void schedule(receiver_proxy& r, span<byte> s) noexcept override; |
| 7136 | + void schedule_bulk_chunked(size_t shape, bulk_item_receiver_proxy& r, |
| 7137 | + span<byte> s) noexcept override; |
| 7138 | + void schedule_bulk_unchunked(size_t shape, bulk_item_receiver_proxy& r, |
| 7139 | + span<byte> s) noexcept override; |
| 7140 | + |
| 7141 | + private: |
| 7142 | + Sch @\exposid{sched_}@; |
7138 | 7143 | }; |
7139 | 7144 | } |
7140 | 7145 | \end{codeblock} |
7141 | | -\exposid{ts-sender} is an exposition-only class that models |
7142 | | -\libconcept{sender}\iref{exec.snd} and for which |
7143 | | -\tcode{completion_signatures_of_t<\exposid{ts-sender}>} denotes: |
7144 | | -\begin{codeblock} |
7145 | | -completion_signatures< |
7146 | | - set_value_t(), |
7147 | | - set_error_t(error_code), |
7148 | | - set_error_t(exception_ptr), |
7149 | | - set_stopped_t()> |
7150 | | -\end{codeblock} |
7151 | 7146 |
|
7152 | 7147 | \pnum |
7153 | | -Let \tcode{\placeholder{sch}} be an object of type \tcode{task_scheduler} |
7154 | | -and let \tcode{sndr} be an object of type \exposid{ts-sender} obtained |
7155 | | -from \tcode{schedule(\placeholder{sch})}. |
7156 | | -Then \tcode{get_completion_scheduler<set_value_t>(get_env(sndr)) == \placeholder{sch}} |
7157 | | -is \tcode{true}. |
7158 | | -The object \tcode{\exposid{SENDER}(sndr)} is the sender object contained by |
7159 | | -\tcode{sndr} or an object move constructed from it. |
| 7148 | +Let \tcode{env} be a pack of subexpressions, and |
| 7149 | +let \exposid{just-sndr-like} be a sender |
| 7150 | +whose only value completion signature is \tcode{set_value_t()} and |
| 7151 | +for which the expression |
| 7152 | +\tcode{get_completion_scheduler<set_value_t>(get_env(\exposid{just-sndr-like)}, env...)} |
| 7153 | +is expression-equivalent to |
| 7154 | +\tcode{get_completion_scheduler<set_value_t>(\exposid{sched_}, env...)}. |
7160 | 7155 |
|
7161 | | -\indexlibrarymember{connect}{task_scheduler::\exposid{ts-sender}}% |
7162 | 7156 | \begin{itemdecl} |
7163 | | -template<@\libconcept{receiver}@ Rcvr> |
7164 | | - @\exposid{state}@<Rcvr> connect(Rcvr&& rcvr) &&; |
| 7157 | +void schedule(receiver_proxy& r, span<byte> s) noexcept override; |
7165 | 7158 | \end{itemdecl} |
| 7159 | + |
7166 | 7160 | \begin{itemdescr} |
7167 | 7161 | \pnum |
7168 | 7162 | \effects |
7169 | | -Let \tcode{\placeholder{r}} be an object of a type that models \libconcept{receiver} |
7170 | | -and whose completion handlers result in invoking the corresponding |
7171 | | -completion handlers of \tcode{rcvr} or copy thereof. |
7172 | | -Returns an object of type \tcode{\exposid{state}<Rcvr>} containing |
7173 | | -an operation state object initialized with \tcode{connect(\exposid{SENDER}(*this), |
7174 | | -std::move(\placeholder{r}))}. |
| 7163 | +Constructs an operation state \tcode{os} |
| 7164 | +with \tcode{connect(schedule(\exposid{sched_}), \exposid{WRAP-RCVR}(r))} and |
| 7165 | +calls \tcode{start(os)}. |
7175 | 7166 | \end{itemdescr} |
7176 | 7167 |
|
| 7168 | +\begin{itemdecl} |
| 7169 | +void schedule_bulk_chunked(size_t shape, bulk_item_receiver_proxy& r, |
| 7170 | + span<byte> s) noexcept override; |
| 7171 | +\end{itemdecl} |
| 7172 | + |
| 7173 | +\begin{itemdescr} |
7177 | 7174 | \pnum |
| 7175 | +\effects |
| 7176 | +Let \tcode{chunk_size} be an integer less than or equal to \tcode{shape}, |
| 7177 | +let \tcode{num_chunks} be \tcode{(shape + chunk_size - 1) / chunk_size}, and |
| 7178 | +let \tcode{fn} be a function object such that |
| 7179 | +for an integer \tcode{i}, |
| 7180 | +\tcode{fn(i)} calls \tcode{r.execute(i * chunk_size, m)}, |
| 7181 | +where \tcode{m} is the lesser of \tcode{(i + 1) * chunk_size} and \tcode{shape}. |
| 7182 | +Constructs an operation state \tcode{os} as if with |
| 7183 | +\begin{codeblock} |
| 7184 | +connect(bulk(@\exposid{just-sndr-like}@, par, num_chunks, fn), @\exposid{WRAP-RCVR}@(r)) |
| 7185 | +\end{codeblock} |
| 7186 | +and calls \tcode{start(os)}. |
| 7187 | +\end{itemdescr} |
| 7188 | + |
| 7189 | +\begin{itemdecl} |
| 7190 | +void schedule_bulk_unchunked(size_t shape, bulk_item_receiver_proxy& r, |
| 7191 | + span<byte> s) noexcept override; |
| 7192 | +\end{itemdecl} |
| 7193 | + |
| 7194 | +\begin{itemdescr} |
| 7195 | +\pnum |
| 7196 | +\effects |
| 7197 | +Let \tcode{fn} be a function object such that |
| 7198 | +for an integer \tcode{i}, |
| 7199 | +\tcode{fn(i)} is equivalent to \tcode{r.execute(i, i + 1)}. |
| 7200 | +Constructs an operation state \tcode{os} as if with |
| 7201 | +\tcode{connect(bulk(\exposid{just-sndr-like}, par, shape, fn), \exposid{WRAP-RCVR}(r))} |
| 7202 | +and calls \tcode{start(os)}. |
| 7203 | +\end{itemdescr} |
| 7204 | + |
| 7205 | +\begin{itemdecl} |
| 7206 | +@\seebelow@ schedule(); |
| 7207 | +\end{itemdecl} |
| 7208 | + |
| 7209 | +\begin{itemdescr} |
| 7210 | +\pnum |
| 7211 | +\returns |
| 7212 | +A prvalue \exposid{ts-sndr} whose type models \libconcept{sender} such that: |
| 7213 | +\begin{itemize} |
| 7214 | +\item |
| 7215 | +\tcode{get_completion_scheduler<set_value_t>(get_env(\exposid{ts-sndr}))} |
| 7216 | +is equal to \tcode{*this.} |
| 7217 | +\item |
| 7218 | +\tcode{get_completion_domain<set_value_t>(get_env(\exposid{ts-sndr}))} |
| 7219 | +is expression-equivalent to \tcode{\exposid{ts-domain}()}. |
| 7220 | +\item |
| 7221 | +If a receiver \tcode{rcvr} is connected to \exposid{ts-sndr} and |
| 7222 | +the resulting operation state is started, |
| 7223 | +calls \tcode{\exposid{sch_}->schedule(r, s)}, where |
| 7224 | +\begin{itemize} |
| 7225 | +\item |
| 7226 | +\tcode{r} is a proxy for \tcode{rcvr} with base |
| 7227 | +\tcode{system_context_replaceability::eceiver_proxy}\iref{exec.par.scheduler} |
| 7228 | +and |
| 7229 | +\item |
| 7230 | +\tcode{s} is a preallocated backend storage for \tcode{r}. |
| 7231 | +\end{itemize} |
| 7232 | +\item |
| 7233 | +For any type \tcode{E}, |
| 7234 | +\tcode{completion_signatures_of_t<decltype(\exposid{ts-sndr}), E>} denotes |
| 7235 | +\tcode{completion_signatures<set_value_t()>} if |
| 7236 | +\tcode{\libconcept{unstoppable_token}<stop_token_of_t<E>>} is \tcode{true}, and |
| 7237 | +otherwise \tcode{completion_signatures<set_value_t(), set_stopped_t()>}. |
| 7238 | +\end{itremize} |
| 7239 | +\end{itemdescr} |
| 7240 | + |
7178 | 7241 | \begin{codeblock} |
7179 | 7242 | namespace std::execution { |
7180 | | - template<@\libconcept{receiver}@ R> |
7181 | | - class task_scheduler::@\exposidnc{state}@ { // \expos |
| 7243 | + class task_scheduler::@\exposid{ts-domain}@ : public default_domain { // \expos |
7182 | 7244 | public: |
7183 | | - using operation_state_concept = operation_state_t; |
7184 | | - |
7185 | | - void start() & noexcept; |
| 7245 | + template<class BulkSndr, class Env> |
| 7246 | + static constexpr auto transform_sender(set_value_t, BulkSndr&& bulk_sndr, const Env& env) |
| 7247 | + noexcept(@\seebelow@); |
7186 | 7248 | }; |
7187 | 7249 | } |
7188 | 7250 | \end{codeblock} |
7189 | | -\exposid{state} is an exposition-only class template whose |
7190 | | -specializations model \libconcept{operation_state}\iref{exec.opstate}. |
7191 | 7251 |
|
7192 | | -\indexlibrarymember{start}{task_scheduler::\exposid{state}}% |
7193 | 7252 | \begin{itemdecl} |
7194 | | -void start() & noexcept; |
| 7253 | +template<class BulkSndr, class Env> |
| 7254 | + static constexpr auto transform_sender(BulkSndr&& bulk_sndr, const Env& env) |
| 7255 | + noexcept(is_nothrow_constructible_v<decay_t<BulkSndr>, BulkSndr>); |
7195 | 7256 | \end{itemdecl} |
| 7257 | + |
7196 | 7258 | \begin{itemdescr} |
| 7259 | +\pnum |
| 7260 | +\constraints |
| 7261 | +\begin{itemize} |
| 7262 | +\item |
| 7263 | +\tcode{\libconcept{sender_in}<BulkSndr, Env>} is \tcode{true}, |
| 7264 | +\item |
| 7265 | +\tcode{auto(std::forward<BulkSndr>(bulk_sndr))} is well-formed, and |
| 7266 | +either \tcode{\exposconcept{sender-for}<BulkSndr, bulk_chunked_t>} or |
| 7267 | +\exposconcept{sender-for}<BulkSndr, bulk_unchunked_t> is \tcode{true}. |
| 7268 | +\end{itemize} |
| 7269 | + |
7197 | 7270 | \pnum |
7198 | 7271 | \effects |
7199 | | -Equivalent to \tcode{start(st)} where \tcode{st} is the operation |
7200 | | -state object contained by \tcode{*this}. |
| 7272 | +Equivalent to: |
| 7273 | +\begin{codeblock} |
| 7274 | +auto& [_, data, child] = bulk_sndr; |
| 7275 | +auto& [_, shape, fn] = data; |
| 7276 | +auto sch = @\exposid{call-with-default}@(get_completion_scheduler<set_value_t>, |
| 7277 | + @\exposid{not-a-scheduler}@(), get_env(child), @\exposid{FWD-ENV}@(env)); |
| 7278 | +return @$e$@; |
| 7279 | +\end{codeblock} |
| 7280 | +where $e$ is \tcode{\exposid{not-a-sender}()} |
| 7281 | +if the type of \tcode{sch} is not \tcode{task_scheduler}; |
| 7282 | +otherwise, it is a prvalue whose type models \libconcept{sender} such that, |
| 7283 | +if it is connected to a receiver \tcode{rcvr} and |
| 7284 | +the resulting operation state is started, |
| 7285 | +\tcode{child} is connected to an unspecified receiver \tcode{R} and started. |
| 7286 | +The expression \tcode{get_env(R)} |
| 7287 | +is expression-equivalent to \tcode{\exposid{FWD-ENV}(get_env(\exposid{rcvr-copy}))}, |
| 7288 | +where \exposid{rcvr-copy} is an lvalue subexpression |
| 7289 | +designating an object decay-copied from \tcode{rcvr}. |
| 7290 | + |
| 7291 | +If \tcode{child} completes with an error or a stopped completion, |
| 7292 | +the completion operation is forwarded unchanged to \tcode{rcvr}. |
| 7293 | +Otherwise, let \tcode{args} be a pack of lvalue subexpressions |
| 7294 | +designating objects decay-copied from the value result datums. |
| 7295 | +Then: |
| 7296 | +\begin{itemize} |
| 7297 | +\item |
| 7298 | +If \tcode{bulk_sndr} was the result of the evaluation of |
| 7299 | +an expression equivalent to \tcode{bulk_chunked(child, policy, shape, fn)} or |
| 7300 | +a copy of such, |
| 7301 | +then \tcode{\exposid{sch_}->schedule_bulk_chunked(shape, r, s)} is called |
| 7302 | +where \tcode{r} is a bulk chunked proxy\iref{exec.par.scheduler} |
| 7303 | +for \tcode{rcvr} with callable \tcode{fn} and arguments \tcode{args}, and |
| 7304 | +\tcode{s} is a preallocated backend storage for \tcode{r}. |
| 7305 | +\item |
| 7306 | +Otherwise, calls \tcode{\exposid{sch_}->schedule_bulk_unchunked(shape, r, s)} |
| 7307 | +where \tcode{r} is a bulk unchunked proxy for \tcode{rcvr} |
| 7308 | +with callable \tcode{fn} and arguments \tcode{args}, and |
| 7309 | +\tcode{s} is a preallocated backend storage for \tcode{r}. |
| 7310 | +\end{itemize} |
7201 | 7311 | \end{itemdescr} |
7202 | 7312 |
|
7203 | 7313 | \rSec2[exec.task]{\tcode{execution::task}} |
|
0 commit comments