Iros
 
Loading...
Searching...
No Matches
first_value.h
Go to the documentation of this file.
1#pragma once
2
22#include "di/function/invoke.h"
25#include "di/meta/algorithm.h"
26#include "di/meta/core.h"
27#include "di/meta/language.h"
28#include "di/meta/util.h"
30#include "di/sync/atomic.h"
32#include "di/util/addressof.h"
33#include "di/util/immovable.h"
38
39namespace di::execution {
40namespace first_value_ns {
41 template<typename Seq, typename Rec>
42 struct DataT {
43 struct Type {
45
48 using Tags =
57
58 template<typename... Args>
59 void complete_inner_value(Args&&... args) {
60 complete_inner([&] {
61 storage.template emplace<meta::DecayedTuple<SetValue, Args...>>(set_value,
62 util::forward<Args>(args)...);
63 });
64 }
65
66 template<typename E>
67 void complete_inner_error(E&& error) {
68 complete_inner([&] {
69 storage.template emplace<meta::DecayedTuple<SetError, E>>(set_error, util::forward<E>(error));
70 });
71 }
72
74 complete_inner([&] {
75 storage.template emplace<meta::DecayedTuple<SetStopped>>(set_stopped);
76 });
77 }
78
80 auto was_first = [&] {
81 if constexpr (is_lockstep) {
84 return !result;
85 } else {
87 }
88 }();
89
90 if (was_first) {
91 emplace();
92 }
93 }
94
97 [&](auto&& tuple) {
99 [&](auto tag, auto&&... values) {
100 if constexpr (concepts::SameAs<SetValue, decltype(tag)>) {
101 set_value(util::move(receiver), util::forward<decltype(values)>(values)...);
102 } else if constexpr (concepts::SameAs<SetError, decltype(tag)>) {
103 set_error(util::move(receiver), util::forward<decltype(values)>(values)...);
104 } else if constexpr (concepts::SameAs<SetStopped, decltype(tag)>) {
105 set_stopped(util::move(receiver));
106 }
107 },
108 util::forward<decltype(tuple)>(tuple));
109 },
110 util::move(storage));
111 }
112
113 template<typename E>
114 void complete_outer_error(E&& error) {
115 auto decayed_error = util::forward<E>(error);
116 set_error(util::move(receiver), util::move(decayed_error));
117 }
118
120
121 [[no_unique_address]] Rec receiver;
122 [[no_unique_address]] Storage storage {};
124 };
125 };
126
127 template<typename Seq, typename Rec>
129
130 template<typename Seq, typename Rec, typename Next, typename R>
131 struct NextDataT {
132 struct Type {
133 [[no_unique_address]] R next_receiver;
134 };
135 };
136
137 template<typename Seq, typename Rec, typename Next, typename R>
139
140 template<typename Seq, typename Rec, typename Next, typename R>
142 struct Type : ReceiverAdaptor<Type> {
143 private:
144 using Base = ReceiverAdaptor<Type>;
145 friend Base;
146
147 public:
149 : m_next_data(next_data), m_data(data) {}
150
151 auto base() const& -> R const& { return m_next_data->next_receiver; }
152 auto base() && -> R&& { return util::move(m_next_data->next_receiver); }
153
154 private:
155 template<typename... Args>
156 void set_value(Args&&... values) && {
157 m_data->complete_inner_value(util::forward<Args>(values)...);
158 execution::set_stopped(util::move(*this).base());
159 }
160
161 template<typename E>
162 void set_error(E&& error) && {
163 m_data->complete_inner_error(util::forward<E>(error));
164 execution::set_stopped(util::move(*this).base());
165 }
166
167 void set_stopped() && {
168 m_data->complete_inner_stopped();
169 execution::set_stopped(util::move(*this).base());
170 }
171
172 NextData<Seq, Rec, Next, R>* m_next_data;
173 Data<Seq, Rec>* m_data;
174 };
175 };
176
177 template<typename Seq, typename Rec, typename Next, typename R>
179
180 template<typename Seq, typename Rec, typename Next, typename R>
183 public:
185
186 explicit Type(Data<Seq, Rec>* data, Next&& next_sender, R receiver)
187 : m_next_data(util::move(receiver))
188 , m_data(data)
189 , m_operation(connect(util::forward<Next>(next_sender),
190 NextReceiver<Seq, Rec, Next, R>(util::addressof(m_next_data), data))) {}
191
192 private:
193 friend void tag_invoke(types::Tag<start>, Type& self) { start(self.m_operation); }
194
195 NextData<Seq, Rec, Next, R> m_next_data;
196 Data<Seq, Rec>* m_data;
198 };
199 };
200
201 template<typename Seq, typename Rec, typename Next, typename R>
203
204 template<typename Seq, typename Rec, typename Next>
205 struct NextSenderT {
206 struct Type {
207 using is_sender = void;
208
210
211 [[no_unique_address]] Next next;
213
214 template<concepts::ReceiverOf<CompletionSignatures> R>
215 friend auto tag_invoke(Tag<connect>, Type&& self, R receiver) {
216 return NextOperationState<Seq, Rec, Next, R> { self.data, util::move(self.next), util::move(receiver) };
217 }
218
219 friend auto tag_invoke(types::Tag<get_env>, Type const& self) { return make_env(get_env(self.next)); }
220 };
221 };
222
223 template<typename Seq, typename Rec, typename Next>
225
226 template<typename Seq, typename Rec>
227 struct ReceiverT {
228 struct Type {
229 using is_receiver = void;
230
232
233 friend void tag_invoke(Tag<set_value>, Type&& self) { self.data->complete_outer_value(); }
234
235 template<typename E>
236 friend void tag_invoke(Tag<set_error>, Type&& self, E&& error) {
237 self.data->complete_outer_error(util::forward<E>(error));
238 }
239
240 friend void tag_invoke(Tag<set_stopped>, Type&& self) { self.data->complete_outer_stopped(); }
241
242 template<concepts::Sender Next>
243 friend auto tag_invoke(Tag<set_next>, Type& self, Next&& next) {
244 return NextSender<Seq, Rec, Next> { util::forward<Next>(next), self.data };
245 }
246
247 friend auto tag_invoke(Tag<get_env>, Type const& self) { return make_env(get_env(self.data->receiver)); }
248 };
249 };
250
251 template<typename Seq, typename Rec>
253
254 template<typename Seq, typename Rec>
257 public:
259
260 explicit Type(Seq&& sequence, Rec receiver)
261 : m_data(util::move(receiver))
262 , m_operation(subscribe(util::forward<Seq>(sequence), Receiver<Seq, Rec>(util::addressof(m_data)))) {}
263
264 private:
265 friend void tag_invoke(types::Tag<start>, Type& self) { start(self.m_operation); }
266
267 Data<Seq, Rec> m_data;
269 };
270 };
271
272 template<typename Seq, typename Rec>
274
275 template<typename... Values>
277
278 template<typename E>
280
281 template<typename Seq, typename Env>
282 using Sigs =
284
285 template<typename Seq>
286 struct SenderT {
287 struct Type {
288 using is_sender = void;
289
290 [[no_unique_address]] Seq sequence;
291
292 template<concepts::RemoveCVRefSameAs<Type> Self, typename Env>
294 return {};
295 }
296
297 template<concepts::RemoveCVRefSameAs<Type> Self, typename Rec>
299 friend auto tag_invoke(Tag<connect>, Self&& self, Rec receiver) {
300 return OperationState<meta::Like<Self, Seq>, Rec>(util::forward<Self>(self).sequence,
301 util::move(receiver));
302 }
303
304 friend auto tag_invoke(Tag<get_env>, Type const& self) { return make_env(get_env(self.sequence)); }
305 };
306 };
307
308 template<typename Seq>
310
312 template<concepts::Sender Seq>
313 auto operator()(Seq&& sequence) const {
316 "first_value() customizations must return a Sender");
317 return tag_invoke(*this, util::forward<Seq>(sequence));
318 } else {
319 return Sender<Seq>(util::forward<Seq>(sequence));
320 }
321 }
322 };
323}
324
337constexpr inline auto first_value = first_value_ns::Function {};
338}
Definition atomic.h:15
Definition variant_forward_declaration.h:6
#define DI_IMMOVABLE_NO_UNIQUE_ADDRESS
Definition compiler.h:15
Checks if Send is a sequence that is always lockstep.
Definition is_always_lockstep_sequence.h:63
Definition invoke.h:58
Definition receiver_of.h:25
Definition core.h:114
Definition sender.h:11
Definition tag_invoke.h:33
Definition first_value.h:40
meta::Type< OperationStateT< Seq, Rec > > OperationState
Definition first_value.h:273
meta::Type< ReceiverT< Seq, Rec > > Receiver
Definition first_value.h:252
meta::Type< DataT< Seq, Rec > > Data
Definition first_value.h:128
meta::Type< NextSenderT< Seq, Rec, meta::RemoveCVRef< Next > > > NextSender
Definition first_value.h:224
meta::Type< NextReceiverT< Seq, Rec, Next, R > > NextReceiver
Definition first_value.h:178
CompletionSignatures< SetValue(meta::Decay< Values > &&...)> SigSetValue
Definition first_value.h:276
CompletionSignatures< SetError(meta::Decay< E > &&)> SigSetError
Definition first_value.h:279
meta::Type< NextOperationStateT< Seq, Rec, Next, R > > NextOperationState
Definition first_value.h:202
meta::Type< SenderT< meta::RemoveCVRef< Seq > > > Sender
Definition first_value.h:309
meta::Type< NextDataT< Seq, Rec, Next, R > > NextData
Definition first_value.h:138
meta::MakeCompletionSignatures< Seq, MakeEnv< Env >, CompletionSignatures< SetStopped()>, SigSetValue, SigSetError > Sigs
Definition first_value.h:282
Definition bulk.h:30
constexpr auto set_error
Definition set_error.h:14
constexpr auto start
Definition start.h:20
constexpr auto first_value
Transform a sequence into a sender of its first value.
Definition first_value.h:337
constexpr auto make_env
Create an environment with overrides for queries.
Definition make_env.h:147
meta::Type< receiver_interface_ns::ReceiverAdaptor< Self, Base > > ReceiverAdaptor
Definition receiver_adaptor.h:236
constexpr auto set_stopped
Definition set_stopped.h:14
constexpr auto subscribe
Subscribe a receiver to a sequence.
Definition sequence_sender.h:234
constexpr auto next
Get the next value of a async range in a coroutine.
Definition async_range.h:52
constexpr auto get_env
Definition get_env.h:27
constexpr auto connect
Definition connect.h:42
constexpr auto set_value
Definition set_value.h:14
T::Type Type
Definition core.h:26
detail::ComposeHelper< Funs... > Compose
Definition function.h:99
Type< detail::AsTemplateHelper< Template, T > > AsTemplate
Definition algorithm.h:60
Conditional< concepts::LanguageArray< RemoveReference< T > >, RemoveExtent< RemoveReference< T > > *, Conditional< concepts::LanguageFunction< RemoveReference< T > >, AddPointer< RemoveReference< T > >, RemoveCVRef< T > > > Decay
Definition language.h:574
Concat< List< T >, L > PushFront
Definition algorithm.h:83
decltype(execution::subscribe(util::declval< Send >(), util::declval< Rec >())) SubscribeResult
Definition sequence_sender.h:239
Type< detail::ZipHelper< T, U > > Zip
Definition algorithm.h:216
Fold< Lst, List<>, detail::PushBackIfUnique > Unique
Definition algorithm.h:203
vocab::Tuple< meta::Decay< Types >... > DecayedTuple
Definition decayed_tuple.h:8
Type< detail::MakeCompletionSignaturesHelper< ExtraSigs, meta::ValueTypesOf< Send, Env, SetValue, meta::List >, meta::Transform< meta::ErrorTypesOf< Send, Env, meta::List >, meta::Quote< SetError > >, meta::Conditional< meta::sends_stopped< Send, Env >, SetStopped, types::CompletionSignatures<> > > > MakeCompletionSignatures
Definition make_completion_signatures.h:36
detail::TransformHelper< List, Function >::Type Transform
Definition algorithm.h:186
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
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
Definition vocab.h:96
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 tag_invoke_detail::TagInvokeFn tag_invoke
Definition tag_invoke.h:22
constexpr auto sequence
Definition sequence.h:34
constexpr auto data
Definition data.h:51
Defines the sequence sender concepts and related CPOs.
Definition set_error.h:6
Definition set_stopped.h:6
Definition set_value.h:6
void complete_outer_stopped()
Definition first_value.h:119
void complete_inner_value(Args &&... args)
Definition first_value.h:59
meta::PushFront< meta::AsList< meta::CompletionSignaturesOf< Seq, Env > >, SetStopped()> Sigs
Definition first_value.h:47
Storage storage
Definition first_value.h:122
meta::Transform< Sigs, meta::Compose< meta::Quote< meta::List >, meta::Quote< meta::LanguageFunctionReturn > > > Tags
Definition first_value.h:48
meta::EnvOf< Rec > Env
Definition first_value.h:46
void complete_inner_error(E &&error)
Definition first_value.h:67
Rec receiver
Definition first_value.h:121
meta::AsTemplate< vocab::Variant, meta::Unique< meta::Transform< meta::Zip< Tags, DecayedArgs >, meta::Compose< meta::Uncurry< meta::Quote< meta::DecayedTuple > >, meta::Quote< meta::Join > > > > > Storage
Definition first_value.h:52
void complete_outer_error(E &&error)
Definition first_value.h:114
sync::Atomic< bool > got_first_value
Definition first_value.h:123
void complete_inner_stopped()
Definition first_value.h:73
void complete_inner(concepts::Invocable<> auto &&emplace)
Definition first_value.h:79
static constexpr bool is_lockstep
Definition first_value.h:44
meta::Transform< Sigs, meta::Quote< meta::AsList > > DecayedArgs
Definition first_value.h:51
void complete_outer_value()
Definition first_value.h:95
Definition first_value.h:42
Definition first_value.h:311
auto operator()(Seq &&sequence) const
Definition first_value.h:313
R next_receiver
Definition first_value.h:133
Definition first_value.h:131
friend void tag_invoke(types::Tag< start >, Type &self)
Definition first_value.h:193
Type(Data< Seq, Rec > *data, Next &&next_sender, R receiver)
Definition first_value.h:186
meta::ConnectResult< Next, NextReceiver< Seq, Rec, Next, R > > Op
Definition first_value.h:184
auto base() &&-> R &&
Definition first_value.h:152
auto base() const &-> R const &
Definition first_value.h:151
Type(NextData< Seq, Rec, Next, R > *next_data, Data< Seq, Rec > *data)
Definition first_value.h:148
friend auto tag_invoke(Tag< connect >, Type &&self, R receiver)
Definition first_value.h:215
types::CompletionSignatures< SetStopped()> CompletionSignatures
Definition first_value.h:209
Next next
Definition first_value.h:211
Data< Seq, Rec > * data
Definition first_value.h:212
void is_sender
Definition first_value.h:207
friend auto tag_invoke(types::Tag< get_env >, Type const &self)
Definition first_value.h:219
Definition first_value.h:205
friend void tag_invoke(types::Tag< start >, Type &self)
Definition first_value.h:265
Type(Seq &&sequence, Rec receiver)
Definition first_value.h:260
meta::SubscribeResult< Seq, Receiver< Seq, Rec > > Op
Definition first_value.h:258
friend auto tag_invoke(Tag< set_next >, Type &self, Next &&next)
Definition first_value.h:243
friend void tag_invoke(Tag< set_error >, Type &&self, E &&error)
Definition first_value.h:236
Data< Seq, Rec > * data
Definition first_value.h:231
friend void tag_invoke(Tag< set_stopped >, Type &&self)
Definition first_value.h:240
void is_receiver
Definition first_value.h:229
friend void tag_invoke(Tag< set_value >, Type &&self)
Definition first_value.h:233
friend auto tag_invoke(Tag< get_env >, Type const &self)
Definition first_value.h:247
Definition first_value.h:227
Seq sequence
Definition first_value.h:290
void is_sender
Definition first_value.h:288
friend auto tag_invoke(Tag< get_completion_signatures >, Self &&, Env &&) -> Sigs< meta::Like< Self, Seq >, Env >
Definition first_value.h:293
friend auto tag_invoke(Tag< connect >, Self &&self, Rec receiver)
Definition first_value.h:299
friend auto tag_invoke(Tag< get_env >, Type const &self)
Definition first_value.h:304
Definition first_value.h:286
Definition function.h:30
Definition completion_signuatures.h:7
Definition immovable.h:4