|
633 | 633 | struct @\libglobal{bulk_t}@ { @\unspec@ };
|
634 | 634 | struct @\libglobal{bulk_chunked_t}@ { @\unspec@ };
|
635 | 635 | struct @\libglobal{bulk_unchunked_t}@ { @\unspec@ };
|
636 |
| - struct @\libglobal{split_t}@ { @\unspec@ }; |
637 | 636 | struct @\libglobal{when_all_t}@ { @\unspec@ };
|
638 | 637 | struct @\libglobal{when_all_with_variant_t}@ { @\unspec@ };
|
639 | 638 | struct @\libglobal{into_variant_t}@ { @\unspec@ };
|
|
657 | 656 | inline constexpr bulk_t @\libglobal{bulk}@{};
|
658 | 657 | inline constexpr bulk_chunked_t @\libglobal{bulk_chunked}@{};
|
659 | 658 | inline constexpr bulk_unchunked_t @\libglobal{bulk_unchunked}@{};
|
660 |
| - inline constexpr split_t @\libglobal{split}@{}; |
661 | 659 | inline constexpr when_all_t @\libglobal{when_all}@{};
|
662 | 660 | inline constexpr when_all_with_variant_t @\libglobal{when_all_with_variant}@{};
|
663 | 661 | inline constexpr into_variant_t @\libglobal{into_variant}@{};
|
|
4014 | 4012 | ignore cancellation requests.
|
4015 | 4013 | \end{note}
|
4016 | 4014 |
|
4017 |
| -\rSec3[exec.split]{\tcode{execution::split}} |
4018 |
| - |
4019 |
| -\pnum |
4020 |
| -\tcode{split} adapts an arbitrary sender |
4021 |
| -into a sender that can be connected multiple times. |
4022 |
| - |
4023 |
| -\pnum |
4024 |
| -Let \exposid{split-env} be the type of an environment |
4025 |
| -such that, given an instance \tcode{env}, |
4026 |
| -the expression \tcode{get_stop_token(env)} is well-formed and |
4027 |
| -has type \tcode{inplace_stop_token.} |
4028 |
| - |
4029 |
| -\pnum |
4030 |
| -The name \tcode{split} denotes a pipeable sender adaptor object. |
4031 |
| -For a subexpression \tcode{sndr}, let \tcode{Sndr} be \tcode{decltype((sndr))}. |
4032 |
| -If \tcode{\libconcept{sender_in}<Sndr, \exposid{split-env}>} is \tcode{false}, |
4033 |
| -\tcode{split(sndr)} is ill-formed. |
4034 |
| - |
4035 |
| -\pnum |
4036 |
| -Otherwise, the expression \tcode{split(sndr)} is expression-equivalent to: |
4037 |
| -\begin{codeblock} |
4038 |
| -transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(split, {}, sndr)) |
4039 |
| -\end{codeblock} |
4040 |
| -except that \tcode{sndr} is evaluated only once. |
4041 |
| -\begin{note} |
4042 |
| -The default implementation of \tcode{transform_sender} |
4043 |
| -will have the effect of connecting the sender to a receiver. |
4044 |
| -It will return a sender with a different tag type. |
4045 |
| -\end{note} |
4046 |
| - |
4047 |
| -\pnum |
4048 |
| -Let \exposid{local-state} denote the following exposition-only class template: |
4049 |
| - |
4050 |
| -\begin{codeblock} |
4051 |
| -namespace std::execution { |
4052 |
| - struct @\exposid{local-state-base}@ { // \expos |
4053 |
| - virtual ~@\exposid{local-state-base}@() = default; |
4054 |
| - virtual void @\exposid{notify}@() noexcept = 0; // \expos |
4055 |
| - }; |
4056 |
| - |
4057 |
| - template<class Sndr, class Rcvr> |
4058 |
| - struct @\exposid{local-state}@ : @\exposid{local-state-base}@ { // \expos |
4059 |
| - using @\exposid{on-stop-callback}@ = // \expos |
4060 |
| - stop_callback_for_t<stop_token_of_t<env_of_t<Rcvr>>, @\exposid{on-stop-request}@>; |
4061 |
| - |
4062 |
| - @\exposid{local-state}@(Sndr&& sndr, Rcvr& rcvr) noexcept; |
4063 |
| - ~@\exposid{local-state}@(); |
4064 |
| - |
4065 |
| - void @\exposid{notify}@() noexcept override; |
4066 |
| - |
4067 |
| - private: |
4068 |
| - optional<@\exposid{on-stop-callback}@> @\exposid{on_stop}@; // \expos |
4069 |
| - @\exposid{shared-state}@<Sndr>* @\exposid{sh_state}@; // \expos |
4070 |
| - Rcvr* @\exposid{rcvr}@; // \expos |
4071 |
| - }; |
4072 |
| -} |
4073 |
| -\end{codeblock} |
4074 |
| - |
4075 |
| -\begin{itemdecl} |
4076 |
| -@\exposid{local-state}@(Sndr&& sndr, Rcvr& rcvr) noexcept; |
4077 |
| -\end{itemdecl} |
4078 |
| - |
4079 |
| -\begin{itemdescr} |
4080 |
| -\pnum |
4081 |
| -\effects |
4082 |
| -Equivalent to: |
4083 |
| -\begin{codeblock} |
4084 |
| -auto& [_, data, _] = sndr; |
4085 |
| -this->@\exposid{sh_state}@ = data.sh_state.get(); |
4086 |
| -this->@\exposid{sh_state}@->@\exposid{inc-ref}@(); |
4087 |
| -this->@\exposid{rcvr}@ = addressof(rcvr); |
4088 |
| -\end{codeblock} |
4089 |
| -\end{itemdescr} |
4090 |
| - |
4091 |
| -\begin{itemdecl} |
4092 |
| -~@\exposid{local-state}@(); |
4093 |
| -\end{itemdecl} |
4094 |
| - |
4095 |
| -\begin{itemdescr} |
4096 |
| -\pnum |
4097 |
| -\effects |
4098 |
| -Equivalent to: |
4099 |
| -\begin{codeblock} |
4100 |
| -sh_state->@\exposid{dec-ref}@(); |
4101 |
| -\end{codeblock} |
4102 |
| -\end{itemdescr} |
4103 |
| - |
4104 |
| -\begin{itemdecl} |
4105 |
| -void @\exposid{notify}@() noexcept override; |
4106 |
| -\end{itemdecl} |
4107 |
| - |
4108 |
| -\begin{itemdescr} |
4109 |
| -\pnum |
4110 |
| -\effects |
4111 |
| -Equivalent to: |
4112 |
| -\begin{codeblock} |
4113 |
| -@\exposid{on_stop}@.reset(); |
4114 |
| -visit( |
4115 |
| - [this](const auto& tupl) noexcept -> void { |
4116 |
| - apply( |
4117 |
| - [this](auto tag, const auto&... args) noexcept -> void { |
4118 |
| - tag(std::move(*@\exposid{rcvr}@), args...); |
4119 |
| - }, |
4120 |
| - tupl); |
4121 |
| - }, |
4122 |
| - @\exposid{sh_state}@->result); |
4123 |
| -\end{codeblock} |
4124 |
| -\end{itemdescr} |
4125 |
| - |
4126 |
| -\pnum |
4127 |
| -Let \exposid{split-receiver} denote |
4128 |
| -the following exposition-only class template: |
4129 |
| -\begin{codeblock} |
4130 |
| -namespace std::execution { |
4131 |
| - template<class Sndr> |
4132 |
| - struct @\exposid{split-receiver}@ { // \expos |
4133 |
| - using receiver_concept = receiver_t; |
4134 |
| - |
4135 |
| - template<class Tag, class... Args> |
4136 |
| - void @\exposid{complete}@(Tag, Args&&... args) noexcept { // \expos |
4137 |
| - using tuple_t = @\exposid{decayed-tuple}@<Tag, Args...>; |
4138 |
| - try { |
4139 |
| - @\exposid{sh_state}@->result.template emplace<tuple_t>(Tag(), std::forward<Args>(args)...); |
4140 |
| - } catch (...) { |
4141 |
| - using tuple_t = tuple<set_error_t, exception_ptr>; |
4142 |
| - @\exposid{sh_state}@->result.template emplace<tuple_t>(set_error, current_exception()); |
4143 |
| - } |
4144 |
| - @\exposid{sh_state}@->notify(); |
4145 |
| - } |
4146 |
| - |
4147 |
| - template<class... Args> |
4148 |
| - void set_value(Args&&... args) && noexcept { |
4149 |
| - @\exposid{complete}@(execution::set_value, std::forward<Args>(args)...); |
4150 |
| - } |
4151 |
| - |
4152 |
| - template<class Error> |
4153 |
| - void set_error(Error&& err) && noexcept { |
4154 |
| - @\exposid{complete}@(execution::set_error, std::forward<Error>(err)); |
4155 |
| - } |
4156 |
| - |
4157 |
| - void set_stopped() && noexcept { |
4158 |
| - @\exposid{complete}@(execution::set_stopped); |
4159 |
| - } |
4160 |
| - |
4161 |
| - struct @\exposid{env}@ { // \expos |
4162 |
| - @\exposid{shared-state}@<Sndr>* @\exposid{sh-state}@; // \expos |
4163 |
| - |
4164 |
| - inplace_stop_token query(get_stop_token_t) const noexcept { |
4165 |
| - return @\exposid{sh-state}@->stop_src.get_token(); |
4166 |
| - } |
4167 |
| - }; |
4168 |
| - |
4169 |
| - @\exposid{env}@ get_env() const noexcept { |
4170 |
| - return @\exposid{env}@{@\exposid{sh_state}@}; |
4171 |
| - } |
4172 |
| - |
4173 |
| - @\exposid{shared-state}@<Sndr>* @\exposid{sh_state}@; // \expos |
4174 |
| - }; |
4175 |
| -} |
4176 |
| -\end{codeblock} |
4177 |
| - |
4178 |
| -\pnum |
4179 |
| -Let \exposid{shared-state} denote the following exposition-only class template: |
4180 |
| -\begin{codeblock} |
4181 |
| -namespace std::execution { |
4182 |
| - template<class Sndr> |
4183 |
| - struct @\exposid{shared-state}@ { |
4184 |
| - using @\exposid{variant-type}@ = @\seebelow@; // \expos |
4185 |
| - using @\exposid{state-list-type}@ = @\seebelow@; // \expos |
4186 |
| - |
4187 |
| - explicit @\exposid{shared-state}@(Sndr&& sndr); |
4188 |
| - |
4189 |
| - void @\exposid{start-op}@() noexcept; // \expos |
4190 |
| - void @\exposid{notify}@() noexcept; // \expos |
4191 |
| - void @\exposid{inc-ref}@() noexcept; // \expos |
4192 |
| - void @\exposid{dec-ref}@() noexcept; // \expos |
4193 |
| - |
4194 |
| - inplace_stop_source @\exposid{stop_src}@{}; // \expos |
4195 |
| - @\exposid{variant-type}@ @\exposid{result}@{}; // \expos |
4196 |
| - @\exposid{state-list-type}@ @\exposid{waiting_states}@; // \expos |
4197 |
| - atomic<bool> @\exposid{completed}@{false}; // \expos |
4198 |
| - atomic<size_t> @\exposid{ref_count}@{1}; // \expos |
4199 |
| - connect_result_t<Sndr, @\exposid{split-receiver}@<Sndr>> @\exposid{op_state}@; // \expos |
4200 |
| - }; |
4201 |
| -} |
4202 |
| -\end{codeblock} |
4203 |
| - |
4204 |
| -\pnum |
4205 |
| -Let \tcode{Sigs} be a pack of the arguments |
4206 |
| -to the \tcode{completion_signatures} specialization |
4207 |
| -named by \tcode{completion_signatures_of_t<Sndr>}. |
4208 |
| -For type \tcode{Tag} and pack \tcode{Args}, |
4209 |
| -let \exposid{as-tuple} be an alias template |
4210 |
| -such that \tcode{\exposid{as-tuple}<Tag(Args...)>} denotes |
4211 |
| -the type \tcode{\exposid{decayed-tuple}<Tag, Args...>}. |
4212 |
| -Then \exposid{variant-type} denotes the type |
4213 |
| -\begin{codeblock} |
4214 |
| -variant<tuple<set_stopped_t>, tuple<set_error_t, exception_ptr>, @\exposid{as-tuple}@<Sigs>...> |
4215 |
| -\end{codeblock} |
4216 |
| -but with duplicate types removed. |
4217 |
| - |
4218 |
| -\pnum |
4219 |
| -Let \exposid{state-list-type} be a type |
4220 |
| -that stores a list of pointers to \exposid{local-state-base} objects and |
4221 |
| -that permits atomic insertion. |
4222 |
| - |
4223 |
| -\begin{itemdecl} |
4224 |
| -explicit @\exposid{shared-state}@(Sndr&& sndr); |
4225 |
| -\end{itemdecl} |
4226 |
| - |
4227 |
| -\begin{itemdescr} |
4228 |
| -\pnum |
4229 |
| -\effects |
4230 |
| -Initializes \exposid{op_state} with the result of |
4231 |
| -\tcode{connect(std::forward<Sndr>(sndr), \exposid{split-re\-ceiver}\{this\})}. |
4232 |
| - |
4233 |
| -\pnum |
4234 |
| -\ensures |
4235 |
| -\exposid{waiting_states} is empty, and \exposid{completed} is \tcode{false}. |
4236 |
| -\end{itemdescr} |
4237 |
| - |
4238 |
| -\begin{itemdecl} |
4239 |
| -void @\exposid{start-op}@() noexcept; |
4240 |
| -\end{itemdecl} |
4241 |
| - |
4242 |
| -\begin{itemdescr} |
4243 |
| -\pnum |
4244 |
| -\effects |
4245 |
| -Evaluates \tcode{\exposid{inc-ref}()}. |
4246 |
| -If \tcode{stop_src.stop_requested()} is \tcode{true}, |
4247 |
| -evaluates \tcode{\exposid{notify}()}; |
4248 |
| -otherwise, evaluates \tcode{start(\exposid{op_state})}. |
4249 |
| -\end{itemdescr} |
4250 |
| - |
4251 |
| -\begin{itemdecl} |
4252 |
| -void @\exposid{notify}@() noexcept; |
4253 |
| -\end{itemdecl} |
4254 |
| - |
4255 |
| -\begin{itemdescr} |
4256 |
| -\pnum |
4257 |
| -\effects |
4258 |
| -Atomically does the following: |
4259 |
| -\begin{itemize} |
4260 |
| -\item |
4261 |
| -Sets \tcode{completed} to \tcode{true}, and |
4262 |
| -\item |
4263 |
| -Exchanges \tcode{waiting_states} with an empty list, |
4264 |
| -storing the old value in a local \tcode{prior_states}. |
4265 |
| -\end{itemize} |
4266 |
| -Then, for each pointer \tcode{p} in \tcode{prior_states}, |
4267 |
| -evaluates \tcode{p->\exposid{notify}()}. |
4268 |
| -Finally, evaluates \tcode{\exposid{dec-ref}()}. |
4269 |
| -\end{itemdescr} |
4270 |
| - |
4271 |
| -\begin{itemdecl} |
4272 |
| -void @\exposid{inc-ref}@() noexcept; |
4273 |
| -\end{itemdecl} |
4274 |
| - |
4275 |
| -\begin{itemdescr} |
4276 |
| -\pnum |
4277 |
| -\effects |
4278 |
| -Increments \exposid{ref_count}. |
4279 |
| -\end{itemdescr} |
4280 |
| - |
4281 |
| -\begin{itemdecl} |
4282 |
| -void @\exposid{dec-ref}@() noexcept; |
4283 |
| -\end{itemdecl} |
4284 |
| - |
4285 |
| -\begin{itemdescr} |
4286 |
| -\pnum |
4287 |
| -\effects |
4288 |
| -Decrements \exposid{ref_count}. |
4289 |
| -If the new value of \exposid{ref_count} is \tcode{0}, |
4290 |
| -calls \tcode{delete this}. |
4291 |
| - |
4292 |
| -\pnum |
4293 |
| -\sync |
4294 |
| -If an evaluation of \tcode{\exposid{dec-ref}()} does not |
4295 |
| -decrement the \tcode{ref_count} to \tcode{0} then |
4296 |
| -synchronizes with the evaluation of \tcode{dec-ref()} |
4297 |
| -that decrements \tcode{ref_count} to \tcode{0}. |
4298 |
| -\end{itemdescr} |
4299 |
| - |
4300 |
| -\pnum |
4301 |
| -Let \exposid{split-impl-tag} be an empty exposition-only class type. |
4302 |
| -Given an expression \tcode{sndr}, |
4303 |
| -the expression \tcode{split.transform_sender(sndr)} is equivalent to: |
4304 |
| -\begin{codeblock} |
4305 |
| -auto&& [tag, _, child] = sndr; |
4306 |
| -auto* sh_state = new @\exposid{shared-state}@{std::forward_like<decltype((sndr))>(child)}; |
4307 |
| -return @\exposid{make-sender}@(@\exposid{split-impl-tag}@(), @\exposid{shared-wrapper}@{sh_state, tag}); |
4308 |
| -\end{codeblock} |
4309 |
| -where \exposid{shared-wrapper} is an exposition-only class |
4310 |
| -that manages the reference count of the \exposid{shared-state} object |
4311 |
| -pointed to by sh_state. |
4312 |
| -\exposid{shared-wrapper} models \libconcept{copyable} |
4313 |
| -with move operations nulling out the moved-from object, |
4314 |
| -copy operations incrementing the reference count |
4315 |
| -by calling \tcode{sh_state->\exposid{inc-ref}()}, and |
4316 |
| -assignment operations performing a copy-and-swap operation. |
4317 |
| -The destructor has no effect if sh_state is null; |
4318 |
| -otherwise, it decrements the reference count |
4319 |
| -by evaluating \tcode{sh_state->\exposid{dec-ref}()}. |
4320 |
| - |
4321 |
| -\pnum |
4322 |
| -The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} |
4323 |
| -is specialized for \exposid{split-impl-tag} as follows: |
4324 |
| -\begin{codeblock} |
4325 |
| -namespace std::execution { |
4326 |
| - template<> |
4327 |
| - struct @\exposid{impls-for}@<@\exposid{split-impl-tag}@> : @\exposid{default-impls}@ { |
4328 |
| - static constexpr auto @\exposid{get-state}@ = @\seebelow@; |
4329 |
| - static constexpr auto @\exposid{start}@ = @\seebelow@; |
4330 |
| - }; |
4331 |
| -} |
4332 |
| -\end{codeblock} |
4333 |
| - |
4334 |
| -\pnum |
4335 |
| -The member |
4336 |
| -\tcode{\exposid{impls-for}<\exposid{split-impl-tag}>::\exposid{get-state}} |
4337 |
| -is initialized with a callable object equivalent to |
4338 |
| -the following lambda expression: |
4339 |
| -\begin{codeblock} |
4340 |
| -[]<class Sndr>(Sndr&& sndr, auto& rcvr) noexcept { |
4341 |
| - return @\exposid{local-state}@{std::forward<Sndr>(sndr), rcvr}; |
4342 |
| -} |
4343 |
| -\end{codeblock} |
4344 |
| - |
4345 |
| -\pnum |
4346 |
| -The member |
4347 |
| -\tcode{\exposid{impls-for}<\exposid{split-impl-tag}>::\exposid{start}} |
4348 |
| -is initialized with a callable object |
4349 |
| -that has a function call operator equivalent to the following: |
4350 |
| -\begin{codeblock} |
4351 |
| -template<class Sndr, class Rcvr> |
4352 |
| -void operator()(@\exposid{local-state}@<Sndr, Rcvr>& state, Rcvr& rcvr) const noexcept; |
4353 |
| -\end{codeblock} |
4354 |
| - |
4355 |
| -\effects |
4356 |
| -If \tcode{state.\exposid{sh_state}->\exposid{completed}} is \tcode{true}, |
4357 |
| -evaluates \tcode{state.\exposid{notify}()} and returns. |
4358 |
| -Otherwise, does the following in order: |
4359 |
| -\begin{itemize} |
4360 |
| -\item |
4361 |
| -Evaluates |
4362 |
| -\begin{codeblock} |
4363 |
| -state.@\exposid{on_stop}@.emplace( |
4364 |
| - get_stop_token(get_env(rcvr)), |
4365 |
| - @\exposid{on-stop-request}@{state.@\exposid{sh_state}@->@\exposid{stop_src}@}); |
4366 |
| -\end{codeblock} |
4367 |
| -\item |
4368 |
| -Then atomically does the following: |
4369 |
| -\begin{itemize} |
4370 |
| -\item |
4371 |
| -Reads the value \tcode{c} of |
4372 |
| -\tcode{state.\exposid{sh_state}->\exposid{completed}}, and |
4373 |
| -\item |
4374 |
| -Inserts \tcode{addressof(state)} into |
4375 |
| -\tcode{state.\exposid{sh_state}->\exposid{waiting_states}} |
4376 |
| -if \tcode{c} is \tcode{false}. |
4377 |
| -\end{itemize} |
4378 |
| -\item |
4379 |
| -If \tcode{c} is \tcode{true}, |
4380 |
| -calls \tcode{state.\exposid{notify}()} and returns. |
4381 |
| -\item |
4382 |
| -Otherwise, |
4383 |
| -if \tcode{addressof(state)} is the first item added to |
4384 |
| -\tcode{state.\exposid{sh_state}->\exposid{waiting_states}}, |
4385 |
| -evaluates \tcode{state.\exposid{sh_state}->\exposid{start-op}()}. |
4386 |
| -\end{itemize} |
4387 |
| - |
4388 | 4015 | \rSec3[exec.when.all]{\tcode{execution::when_all}}
|
4389 | 4016 |
|
4390 | 4017 | \pnum
|
|
0 commit comments