Iros
 
Loading...
Searching...
No Matches
zip.h
Go to the documentation of this file.
1#pragma once
2
24#include "di/meta/core.h"
25#include "di/meta/util.h"
30#include "di/util/addressof.h"
32#include "di/util/exchange.h"
33#include "di/util/immovable.h"
34#include "di/util/move.h"
38
39namespace di::execution {
40namespace zip_ns {
41 using when_all_ns::Env;
52
53 template<typename Rec, typename... Seqs>
54 struct OuterDataT {
55 struct Type {
56 public:
58 using Value = ValueStorage<Env, Seqs...>;
59 using Error = ErrorStorage<Env, Seqs...>;
60 using Count = usize;
62 using StopCallback = StopToken::template CallbackType<StopCallbackFunction>;
63
64 explicit Type(Rec outer_out_r_) : outer_out_r(util::move(outer_out_r_)) {}
65
68
69 void did_complete(bool stopped) {
70 // Reset inner counters and state. There can't be races here since all sequences are lockstep.
71 inner_error.template emplace<NotError>();
74
75 // Complete inner receivers.
76 for (auto& inner_callback : inner_complete_callbacks) {
77 auto callback = util::move(inner_callback);
78 inner_callback = nullptr;
79 if (callback) {
80 callback(stopped);
81 }
82 }
83 }
84
85 template<usize index, typename... Types>
86 void report_inner_value(Constexpr<index>, Types&&... values) {
87 if constexpr (never_sends_value<Env, Seqs...>) {
88 ((void) values, ...);
89 } else {
90 auto& optional = util::get<index>(inner_value);
91 optional.emplace(util::forward<Types>(values)...);
92 }
94 }
95
96 template<typename E>
97 void report_inner_error(E&& error) {
98 auto old = inner_failed.exchange(true, sync::MemoryOrder::AcquireRelease);
99 if (!old) {
100 // NOTE: Do not request stop here since inner errors can be reported multiple times.
101 this->inner_error.template emplace<meta::Decay<E>>(util::forward<E>(error));
102 }
104 }
105
107 auto old = inner_failed.exchange(true, sync::MemoryOrder::AcquireRelease);
108 if (!old) {
109 stop_source.request_stop();
110 inner_error.template emplace<Stopped>();
111 }
113 }
114
116 auto old_value = inner_remaining.fetch_sub(1, sync::MemoryOrder::AcquireRelease);
117 if (old_value == 1) {
119 }
120 }
121
124
126 }
127
128 template<typename E>
129 void report_outer_error(E&& error) {
131
132 auto old = outer_failed.exchange(true, sync::MemoryOrder::AcquireRelease);
133 if (!old) {
134 stop_source.request_stop();
135 this->outer_error.template emplace<meta::Decay<E>>(util::forward<E>(error));
136 }
138 }
139
142
143 auto old = outer_failed.exchange(true, sync::MemoryOrder::AcquireRelease);
144 if (!old) {
145 stop_source.request_stop();
146 outer_error.template emplace<Stopped>();
147 }
149 }
150
152 auto old_value = outer_remaining.fetch_sub(1, sync::MemoryOrder::AcquireRelease);
153 if (old_value == 1) {
154 // Reset the stop callback.
155 stop_callback.reset();
156
157 // Check if an error occurred. This does not need to be atomic because we're done and just used
158 // acquire release ordering.
162 [&]<typename E>(E&& e) {
164 set_error(util::move(outer_out_r), util::forward<E>(e));
165 }
166 },
167 util::move(outer_error));
168 } else {
169 set_stopped(util::move(outer_out_r));
170 }
171 } else {
172 set_value(util::move(outer_out_r));
173 }
174 }
175 }
176
177 auto at_least_one_sequence_stopped() const -> bool {
178 // This can use relaxed memory ordering, since it's only checked after all sequences have either
179 // completed or have sent their next value.
180 return outer_remaining.load(sync::MemoryOrder::Relaxed) < sizeof...(Seqs);
181 }
182
183 [[no_unique_address]] Value inner_value;
184 [[no_unique_address]] Error inner_error;
189
190 [[no_unique_address]] Error outer_error;
191 [[no_unique_address]] Rec outer_out_r;
194
197 };
198 };
199
200 template<concepts::Receiver Rec, concepts::Sender... Sends>
201 using OuterData = meta::Type<OuterDataT<Rec, Sends...>>;
202
203 template<usize index, typename Data>
205 struct Type {
206 using is_receiver = void;
207
208 Data* data;
209
210 template<typename... Types>
211 friend void tag_invoke(Tag<set_value>, Type&& self, Types&&... values) {
212 self.data->report_inner_value(c_<index>, util::forward<Types>(values)...);
213 }
214
215 template<typename E>
216 friend void tag_invoke(Tag<set_error>, Type&& self, E&& error) {
217 self.data->report_inner_error(util::forward<E>(error));
218 }
219
220 friend void tag_invoke(Tag<set_stopped>, Type&& self) { self.data->report_inner_stop(); }
221
222 friend auto tag_invoke(Tag<get_env>, Type const& self) {
223 return make_env(get_env(self.data->outer_out_r),
224 with(get_stop_token, self.data->stop_source.get_stop_token()));
225 }
226 };
227 };
228
229 template<usize index, typename Data>
231
232 template<usize index, typename Send, typename Data, typename R>
235 public:
238
239 explicit Type(Data* data, Send&& sender, R receiver)
240 : m_data(data)
241 , m_receiver(util::move(receiver))
242 , m_op(connect(util::forward<Send>(sender), InnerRec(data))) {}
243
244 private:
245 friend void tag_invoke(Tag<start>, Type& self) {
246 // Type-erasure is used here because there is no way to know the receiver type R before the operation
247 // exists. Ideally, we could store a Tuple<R...> in the data, and use it to directly complete the
248 // receiver. Since R is not known up front, this cannot be done. At least, the type-erased function
249 // won't require allocations, since we only capture a single pointer.
250 self.m_data->inner_complete_callbacks[index] = [&self](bool stopped) {
251 if (stopped) {
252 set_stopped(util::move(self.m_receiver));
253 } else {
254 set_value(util::move(self.m_receiver));
255 }
256 };
257
258 start(self.m_op);
259 }
260
261 Data* m_data;
262 [[no_unique_address]] R m_receiver;
264 };
265 };
266
267 template<usize index, typename Send, typename Data, typename R>
269
270 template<usize index, typename Send, typename Data>
272 struct Type {
273 using is_sender = void;
274
276
277 Data* data;
278 [[no_unique_address]] Send sender;
279
280 template<concepts::ReceiverOf<CompletionSignatures> R>
281 friend auto tag_invoke(Tag<connect>, Type&& self, R receiver) {
282 return InnerNextOperationState<index, Send, Data, R>(self.data, util::move(self.sender),
283 util::move(receiver));
284 }
285
286 friend auto tag_invoke(Tag<get_env>, Type const& self) { return make_env(get_env(self.sender)); }
287 };
288 };
289
290 template<usize index, typename Send, typename Data>
292
293 template<usize index, typename Seq, typename Data>
294 struct ReceiverT {
295 struct Type {
296 using is_receiver = void;
297
298 Data* data;
299
300 friend void tag_invoke(Tag<set_value>, Type&& self) { self.data->report_outer_value(); }
301
302 template<typename E>
303 friend void tag_invoke(Tag<set_error>, Type&& self, E&& error) {
304 self.data->report_outer_error(util::forward<E>(error));
305 }
306
307 friend void tag_invoke(Tag<set_stopped>, Type&& self) { self.data->report_outer_stop(); }
308
310
311 template<concepts::SenderTo<NextRec> Send>
312 friend auto tag_invoke(Tag<set_next>, Type& self, Send&& sender) {
313 return InnerNextSender<index, Send, Data>(self.data, util::forward<Send>(sender));
314 }
315
316 friend auto tag_invoke(Tag<get_env>, Type const& self) {
317 return make_env(get_env(self.data->outer_out_r),
318 with(get_stop_token, self.data->stop_source.get_stop_token()));
319 }
320 };
321 };
322
323 template<usize index, concepts::Sender Seq, typename Data>
325
326 template<typename Rec, typename Indices, typename Seqs>
328
329 template<typename Rec, usize... indices, typename... Seqs>
330 struct NextReceiverT<Rec, meta::ListV<indices...>, meta::List<Seqs...>> {
331 struct Type {
332 using is_receiver = void;
333
334 OuterData<Rec, Seqs...>* data;
335
336 friend void tag_invoke(Tag<set_value>, Type&& self) { self.data->did_complete_outer_value(); }
337 friend void tag_invoke(Tag<set_stopped>, Type&& self) { self.data->did_complete_outer_stopped(); }
338
339 friend auto tag_invoke(Tag<get_env>, Type const& self) {
340 return make_env(get_env(self.data->outer_out_r),
341 with(get_stop_token, self.data->stop_source.get_stop_token()));
342 }
343 };
344 };
345
346 template<typename Rec, typename Indices, typename Seqs>
348
349 template<typename Rec, typename Indices, typename Seqs, typename R>
351
352 template<typename Rec, usize... indices, typename... Seqs, typename R>
353 struct NextOperationStateT<Rec, meta::ListV<indices...>, meta::List<Seqs...>, R> {
355 explicit Type(OuterData<Rec, Seqs...>* data, R receiver) : m_data(data), m_receiver(util::move(receiver)) {}
356
357 friend void tag_invoke(Tag<start>, Type& self) {
358 // The sent values have already been stored in the data, so just complete immediately.
359 auto& data = *self.m_data;
360 if (!vocab::holds_alternative<NotError>(data.inner_error)) {
361 if (!vocab::holds_alternative<Stopped>(data.inner_error)) {
363 [&]<typename E>(E&& e) {
365 execution::set_error(util::move(self.m_receiver), util::forward<E>(e));
366 }
367 },
368 util::move(data.inner_error));
369 } else {
370 execution::set_stopped(util::move(self.m_receiver));
371 }
372 } else {
373 if constexpr (!never_sends_value<meta::EnvOf<Rec>, Seqs...>) {
374 // Value is a Tuple<Optional<Vs...>, ...>, and we need to return all Vs's. Do this be
375 // concatenating all the tuples and then unpacking them.
376 auto lvalues = vocab::apply(
377 [](auto&... optionals) {
378 return vocab::tuple_cat(vocab::apply(vocab::tie, *optionals)...);
379 },
380 data.inner_value);
382 [&](auto&... values) {
383 execution::set_value(util::move(self.m_receiver), util::move(values)...);
384 },
385 lvalues);
386 } else {
388 }
389 }
390 }
391
392 private:
393 OuterData<Rec, Seqs...>* m_data;
394 [[no_unique_address]] R m_receiver;
395 };
396 };
397
398 template<typename Rec, typename Indices, typename Seqs, typename R>
400
401 template<typename Rec, typename Indices, typename Seqs>
403
404 template<typename Rec, usize... indices, typename... Seqs>
405 struct NextSenderT<Rec, meta::ListV<indices...>, meta::List<Seqs...>> {
406 struct Type {
407 public:
408 using is_sender = void;
409
411
412 OuterData<Rec, Seqs...>* data;
413
414 template<concepts::ReceiverOf<CompletionSignatures> R>
415 friend auto tag_invoke(Tag<connect>, Type&& self, R receiver) {
416 return NextOperationState<Rec, meta::ListV<indices...>, meta::List<Seqs...>, R>(self.data,
417 util::move(receiver));
418 }
419 };
420 };
421
422 template<typename Rec, typename Indices, typename Seqs>
424
425 template<typename Rec, typename Indices, typename Seqs>
427
428 template<typename Rec, usize... indices, typename... Seqs>
429 struct OperationStateT<Rec, meta::ListV<indices...>, meta::List<Seqs...>> {
431 public:
432 using Data = OuterData<Rec, Seqs...>;
434
435 using ItemSend = NextSender<Rec, meta::ListV<indices...>, meta::List<Seqs...>>;
437 using NextRec = NextReceiver<Rec, meta::ListV<indices...>, meta::List<Seqs...>>;
439
440 explicit Type(Rec out_r, Seqs&&... sequences)
441 : m_data(util::move(out_r))
442 , m_op_states(util::DeferConstruct([&] -> meta::SubscribeResult<Seqs, Receiver<indices, Seqs, Data>> {
443 return subscribe(util::forward<Seqs>(sequences),
444 Receiver<indices, Seqs, Data> { util::addressof(m_data) });
445 })...) {}
446
447 private:
448 friend void tag_invoke(Tag<start>, Type& self) {
449 // Emplace construct stop callback.
450 self.m_data.stop_callback.emplace(get_stop_token(get_env(self.m_data.outer_out_r)),
451 StopCallbackFunction { self.m_data.stop_source });
452
453 // Check if stop requested:
454 if (self.m_data.stop_source.stop_requested()) {
455 set_stopped(util::move(self.m_data.outer_out_r));
456 return;
457 }
458
459 // Setup callback for when all inner next senders have completed.
460 self.m_data.inner_finish_callback = [&self] {
461 // If any of the sequences stopped, then their is nothing to send at all. Instead, we complete this
462 // round.
463 if (self.m_data.at_least_one_sequence_stopped()) {
464 return self.m_data.did_complete_outer_stopped();
465 }
466
467 self.m_next_op.emplace(util::DeferConstruct([&] {
468 return connect(set_next(self.m_data.outer_out_r, ItemSend(util::addressof(self.m_data))),
469 NextRec(util::addressof(self.m_data)));
470 }));
471 start(*self.m_next_op);
472 };
473
474 // Call start on all operations.
475 vocab::tuple_for_each(start, self.m_op_states);
476 }
477
478 [[no_unique_address]] Data m_data;
479 [[no_unique_address]] OpStates m_op_states;
481 };
482 };
483
484 template<concepts::Receiver Rec, typename Indices, concepts::TypeList Seqs>
486
487 template<typename... Seqs>
488 struct SequenceT {
489 struct Type {
490 public:
492
493 template<typename... Ts>
494 explicit Type(InPlace, Seqs&&... sequences) : m_sequences(util::forward<Seqs>(sequences)...) {}
495
496 private:
497 template<concepts::RemoveCVRefSameAs<Type> Self, typename E>
498 requires(ValidSenders<Env<E>, meta::Like<Self, Seqs>...>)
500 return {};
501 }
502
503 template<concepts::RemoveCVRefSameAs<Type> Self, concepts::Receiver Rec>
504 requires(
506 friend auto tag_invoke(Tag<subscribe>, Self&& self, Rec out_r) {
507 return vocab::apply(
508 [&](auto&&... sequences) {
509 return OperationState<Rec, meta::MakeIndexSequence<sizeof...(Seqs)>,
511 util::move(out_r), util::forward<decltype(sequences)>(sequences)...
512 };
513 },
514 util::forward<Self>(self).m_sequences);
515 }
516
522
523 vocab::Tuple<Seqs...> m_sequences;
524 };
525 };
526
527 template<concepts::Sender... Seqs>
529
530 struct Function {
531 template<concepts::Sender... Seqs>
532 requires(sizeof...(Seqs) > 0)
533 auto operator()(Seqs&&... sequences) const {
534 if constexpr (concepts::TagInvocable<Function, Seqs...>) {
536 "zip() customizations must return a sequence sender");
537 return tag_invoke(*this, util::forward<Seqs>(sequences)...);
538 } else {
540 in_place, into_lockstep_sequence(util::forward<Seqs>(sequences))...
541 };
542 }
543 }
544 };
545
547 template<concepts::Sender... Seqs>
548 requires(sizeof...(Seqs) > 0)
549 auto operator()(Seqs&&... sequences) const {
550 if constexpr (concepts::TagInvocable<VariantFunction, Seqs...>) {
552 "zip_with_variant() customizations must return a sequence sender");
553 return tag_invoke(*this, util::forward<Seqs>(sequences)...);
554 } else {
555 return Function {}(into_variant_each(util::forward<Seqs>(sequences))...);
556 }
557 }
558
559 auto operator()() const { return empty_sequence(); }
560 };
561}
562
583constexpr inline auto zip = zip_ns::Function {};
584
597constexpr inline auto zip_with_variant = zip_ns::VariantFunction {};
598}
Definition function.h:365
Definition atomic.h:15
Definition in_place_stop_source.h:11
Definition defer_construct.h:8
Definition optional_forward_declaration.h:5
Definition tuple_forward_declaration.h:5
#define DI_IMMOVABLE_NO_UNIQUE_ADDRESS
Definition compiler.h:15
Definition core.h:117
Definition receiver.h:10
Definition sender.h:11
Definition sequence_sender.h:102
Definition sequence_sender.h:128
Definition tag_invoke.h:33
constexpr auto min
Definition min.h:47
meta::AsLanguageFunction< SetValue, meta::Transform< meta::Concat< meta::ValueTypesOf< Sends, Env, meta::List, meta::TypeIdentity >... >, meta::Quote< DecayedRValue > > > ValueCompletion
Definition when_all.h:83
meta::Unique< meta::PushBack< meta::Transform< meta::Concat< meta::ErrorTypesOf< Sends, Env, meta::List >... >, meta::Compose< meta::BindFront< meta::Quote< meta::AsLanguageFunction >, SetError >, meta::Quote< meta::List >, meta::Quote< DecayedRValue > > >, SetStopped()> > NonValueCompletions
Definition when_all.h:75
meta::Type< CompletionSignaturesT< E, Sends... > > Sigs
Definition when_all.h:102
MakeEnv< E, With< Tag< get_stop_token >, sync::InPlaceStopToken > > Env
Definition when_all.h:88
meta::Type< ValueStorageT< Env, Sends... > > ValueStorage
Definition when_all.h:117
meta::AsTemplate< DecayedVariant, meta::Concat< meta::List< NotError, Stopped >, meta::ErrorTypesOf< Sends, Env, meta::List >... > > ErrorStorage
Definition when_all.h:126
constexpr bool never_sends_value
Definition when_all.h:71
Definition zip.h:40
meta::Type< OperationStateT< Rec, Indices, Seqs > > OperationState
Definition zip.h:485
meta::Type< InnerReceiverT< index, Data > > InnerReceiver
Definition zip.h:230
meta::Type< InnerNextSenderT< index, meta::RemoveCVRef< Send >, Data > > InnerNextSender
Definition zip.h:291
meta::Type< InnerNextOperationStateT< index, Send, Data, R > > InnerNextOperationState
Definition zip.h:268
meta::Type< NextOperationStateT< Rec, Indices, Seqs, R > > NextOperationState
Definition zip.h:399
meta::Type< NextSenderT< Rec, Indices, Seqs > > NextSender
Definition zip.h:423
meta::Type< ReceiverT< index, Seq, Data > > Receiver
Definition zip.h:324
meta::Type< SequenceT< meta::RemoveCVRef< Seqs >... > > Sequence
Definition zip.h:528
constexpr bool never_sends_value
Definition when_all.h:71
meta::Type< NextReceiverT< Rec, Indices, Seqs > > NextReceiver
Definition zip.h:347
meta::Type< OuterDataT< Rec, Sends... > > OuterData
Definition zip.h:201
Definition bulk.h:30
constexpr auto set_error
Definition set_error.h:14
constexpr auto set_next
Set the next sender of a sequence.
Definition sequence_sender.h:77
constexpr auto into_variant_each
Transform the values of a sequence into a variant.
Definition into_variant_each.h:33
constexpr auto stopped
Definition just.h:91
constexpr auto empty_sequence
A sequence sender that completes immediately without ever sending a value.
Definition empty_sequence.h:56
constexpr auto start
Definition start.h:20
constexpr auto make_env
Create an environment with overrides for queries.
Definition make_env.h:147
constexpr auto set_stopped
Definition set_stopped.h:14
constexpr auto get_sequence_cardinality
A query that returns the cardinality of a sequence.
Definition get_sequence_cardinality.h:45
constexpr auto with
Specify an override for an environment query.
Definition make_env.h:112
constexpr auto subscribe
Subscribe a receiver to a sequence.
Definition sequence_sender.h:234
constexpr auto is_always_lockstep_sequence
A query that returns whether or not a sequence is always lockstep.
Definition is_always_lockstep_sequence.h:53
constexpr auto get_stop_token
Definition get_stop_token.h:25
constexpr auto into_lockstep_sequence
Converts a sequence into a lockstep sequence.
Definition into_lockstep_sequence.h:47
constexpr auto get_env
Definition get_env.h:27
constexpr auto connect
Definition connect.h:42
constexpr auto zip_with_variant
Zip multiple sequences together, allowing them to send different types of values.
Definition zip.h:597
constexpr auto set_value
Definition set_value.h:14
constexpr auto zip
Zip multiple sequences together.
Definition zip.h:583
Definition merge_interfaces.h:6
meta::RemoveCVRef< decltype(execution::get_stop_token(util::declval< T >()))> StopTokenOf
Definition stop_token_of.h:7
T::Type Type
Definition core.h:26
Type< detail::LikeHelper< T, U > > Like
Definition language.h:468
MakeIntegerSequence< usize, count > MakeIndexSequence
Definition algorithm.h:285
decltype(di::function::tag_invoke(util::declval< Tag >(), util::declval< Args >()...)) TagInvokeResult
Definition tag_invoke.h:40
decltype(execution::set_next(util::declval< meta::RemoveCVRef< Rec > & >(), util::declval< Send >())) NextSenderOf
Definition sequence_sender.h:82
constexpr auto SequenceCardinality
Gets the cardinality of a sequence.
Definition get_sequence_cardinality.h:55
decltype(execution::get_env(util::declval< T >())) EnvOf
Definition env_of.h:8
decltype(execution::connect(util::declval< Send >(), util::declval< Rec >())) ConnectResult
Definition connect_result.h:7
@ Relaxed
Definition memory_order.h:7
@ AcquireRelease
Definition memory_order.h:11
size_t usize
Definition integers.h:33
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
Definition vocab.h:96
constexpr auto get(T &&value) -> decltype(auto)
Definition get.h:8
void unreachable()
Definition unreachable.h:4
constexpr auto tuple_cat(Tups &&... tuples)
Definition tuple_cat.h:11
constexpr auto tie
Definition tie.h:15
constexpr auto apply(F &&f, Tup &&tuple) -> decltype(detail::apply_impl(meta::MakeIndexSequence< meta::TupleSize< Tup > > {}, util::forward< F >(f), util::forward< Tup >(tuple)))
Definition apply.h:22
constexpr auto visit(Vis &&visitor, Vars &&... variants) -> R
Definition visit.h:39
constexpr void tuple_for_each(F &&function, Tup &&tuple)
Definition tuple_for_each.h:22
constexpr auto holds_alternative
Definition holds_alternative.h:21
constexpr tag_invoke_detail::TagInvokeFn tag_invoke
Definition tag_invoke.h:22
constexpr auto c_
A value of type Constexpr<val>.
Definition constexpr.h:252
constexpr auto data
Definition data.h:51
constexpr auto in_place
Definition in_place.h:8
constexpr auto empty_env
Definition empty_env.h:6
Defines the sequence sender concepts and related CPOs.
Definition sequence_sender.h:86
Definition set_stopped.h:6
Definition set_value.h:6
Definition when_all.h:122
Definition when_all.h:123
InnerReceiver< index, Data > InnerRec
Definition zip.h:236
friend void tag_invoke(Tag< start >, Type &self)
Definition zip.h:245
meta::ConnectResult< Send, InnerRec > Op
Definition zip.h:237
Type(Data *data, Send &&sender, R receiver)
Definition zip.h:239
friend auto tag_invoke(Tag< connect >, Type &&self, R receiver)
Definition zip.h:281
types::CompletionSignatures< SetValue(), SetStopped()> CompletionSignatures
Definition zip.h:275
friend auto tag_invoke(Tag< get_env >, Type const &self)
Definition zip.h:286
friend void tag_invoke(Tag< set_error >, Type &&self, E &&error)
Definition zip.h:216
friend void tag_invoke(Tag< set_stopped >, Type &&self)
Definition zip.h:220
friend void tag_invoke(Tag< set_value >, Type &&self, Types &&... values)
Definition zip.h:211
friend auto tag_invoke(Tag< get_env >, Type const &self)
Definition zip.h:222
friend void tag_invoke(Tag< set_stopped >, Type &&self)
Definition zip.h:337
friend auto tag_invoke(Tag< get_env >, Type const &self)
Definition zip.h:339
friend auto tag_invoke(Tag< connect >, Type &&self, R receiver)
Definition zip.h:415
vocab::Tuple< meta::SubscribeResult< Seqs, Receiver< indices, Seqs, Data > >... > OpStates
Definition zip.h:433
NextReceiver< Rec, meta::ListV< indices... >, meta::List< Seqs... > > NextRec
Definition zip.h:437
NextSender< Rec, meta::ListV< indices... >, meta::List< Seqs... > > ItemSend
Definition zip.h:435
StopToken::template CallbackType< StopCallbackFunction > StopCallback
Definition zip.h:62
void report_inner_error(E &&error)
Definition zip.h:97
vocab::Optional< StopCallback > stop_callback
Definition zip.h:196
void finish_one_inner()
Definition zip.h:115
void report_outer_error(E &&error)
Definition zip.h:129
Error outer_error
Definition zip.h:190
void did_complete_outer_stopped()
Definition zip.h:66
ValueStorage< Env, Seqs... > Value
Definition zip.h:58
ErrorStorage< Env, Seqs... > Error
Definition zip.h:59
Error inner_error
Definition zip.h:184
Type(Rec outer_out_r_)
Definition zip.h:64
sync::Atomic< bool > outer_failed
Definition zip.h:193
void did_complete(bool stopped)
Definition zip.h:69
void finish_one_outer()
Definition zip.h:151
vocab::Array< function::Function< void(bool)>, sizeof...(Seqs)> inner_complete_callbacks
Definition zip.h:187
Rec outer_out_r
Definition zip.h:191
void report_outer_stop()
Definition zip.h:140
void report_outer_value()
Definition zip.h:122
sync::InPlaceStopSource stop_source
Definition zip.h:195
void did_complete_outer_value()
Definition zip.h:67
auto at_least_one_sequence_stopped() const -> bool
Definition zip.h:177
sync::Atomic< bool > inner_failed
Definition zip.h:186
meta::StopTokenOf< Env > StopToken
Definition zip.h:61
void report_inner_value(Constexpr< index >, Types &&... values)
Definition zip.h:86
function::Function< void()> inner_finish_callback
Definition zip.h:188
Value inner_value
Definition zip.h:183
void report_inner_stop()
Definition zip.h:106
sync::Atomic< Count > inner_remaining
Definition zip.h:185
meta::EnvOf< Rec > Env
Definition zip.h:57
sync::Atomic< Count > outer_remaining
Definition zip.h:192
void is_receiver
Definition zip.h:296
Data * data
Definition zip.h:298
friend void tag_invoke(Tag< set_error >, Type &&self, E &&error)
Definition zip.h:303
friend void tag_invoke(Tag< set_stopped >, Type &&self)
Definition zip.h:307
friend auto tag_invoke(Tag< set_next >, Type &self, Send &&sender)
Definition zip.h:312
InnerReceiver< index, Data > NextRec
Definition zip.h:309
friend void tag_invoke(Tag< set_value >, Type &&self)
Definition zip.h:300
friend auto tag_invoke(Tag< get_env >, Type const &self)
Definition zip.h:316
friend auto tag_invoke(Tag< get_completion_signatures >, Self &&, E &&) -> Sigs< E, meta::Like< Self, Seqs >... >
Definition zip.h:499
friend auto tag_invoke(Tag< get_env >, Type const &)
Definition zip.h:517
friend auto tag_invoke(Tag< subscribe >, Self &&self, Rec out_r)
Definition zip.h:506
SequenceTag is_sender
Definition zip.h:491
Type(InPlace, Seqs &&... sequences)
Definition zip.h:494
auto operator()() const
Definition zip.h:559
A wrapper for a constexpr value.
Definition core.h:77
Definition core.h:8
Definition core.h:5
Definition completion_signuatures.h:7
Definition in_place.h:4
Definition immovable.h:4
Definition span_fixed_size.h:37