Loading [MathJax]/extensions/tex2jax.js
Iros
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
Loading...
Searching...
No Matches
counting_scope.h
Go to the documentation of this file.
1#pragma once
2
31#include "di/meta/core.h"
32#include "di/meta/util.h"
34#include "di/sync/atomic.h"
38#include "di/types/prelude.h"
39#include "di/util/addressof.h"
40#include "di/util/declval.h"
42#include "di/util/immovable.h"
45
46namespace di::execution {
48 template<typename Alloc>
49 struct DataT {
50 struct Type {
51 [[no_unique_address]] Alloc alloc;
55
56 template<typename Env = EmptyEnv>
57 auto get_env(Env const& env = {}) const {
59 }
60
61 void start_one() { count.fetch_add(1, sync::MemoryOrder::Relaxed); }
62
63 void complete_one() {
64 // The count variable starts at 1, because the cleanup action must start before we call the did_complete
65 // function.
66 auto old_count = count.fetch_sub(1, sync::MemoryOrder::AcquireRelease);
67 if (old_count == 1) {
69 }
70 }
71 };
72 };
73
74 template<typename Alloc>
76
77 template<typename Alloc, typename E = EmptyEnv>
78 using Env = decltype(util::declval<Data<Alloc> const&>().get_env(util::declval<E const&>()));
79
80 template<typename Alloc, typename Rec>
81 struct NestDataT {
82 struct Type {
84 [[no_unique_address]] Rec receiver;
85 };
86 };
87
88 template<typename Alloc, typename Rec>
90
91 template<typename Alloc, typename Rec>
93 struct Type : ReceiverAdaptor<Type> {
94 private:
95 using Base = ReceiverAdaptor<Type>;
96 friend Base;
97
98 public:
99 explicit Type(NestData<Alloc, Rec>* data) : m_data(data) {}
100
101 auto base() const& -> Rec const& { return m_data->receiver; }
102 auto base() && -> Rec&& { return util::move(m_data->receiver); }
103
104 private:
105 template<typename... Vs>
106 auto set_value(Vs&&... values) && {
107 m_data->data->complete_one();
108 execution::set_value(util::move(*this).base(), util::forward<Vs>(values)...);
109 }
110
111 template<typename E>
112 auto set_error(E&& error) && {
113 m_data->data->complete_one();
114 execution::set_error(util::move(*this).base(), util::forward<E>(error));
115 }
116
117 auto set_stopped() && {
118 m_data->data->complete_one();
119 execution::set_stopped(util::move(*this).base());
120 }
121
122 auto get_env() const& { return m_data->data->get_env(execution::get_env(base())); }
123
124 NestData<Alloc, Rec>* m_data;
125 };
126 };
127
128 template<typename Alloc, typename Rec>
130
131 template<typename Alloc, typename Send, typename Rec>
134 public:
136
137 explicit Type(Data<Alloc>* data, Send&& sender, Rec receiver)
138 : m_data(data, util::move(receiver))
139 , m_op(connect(util::forward<Send>(sender), NestReceiver<Alloc, Rec>(util::addressof(m_data)))) {}
140
141 private:
142 friend void tag_invoke(Tag<start>, Type& self) {
143 self.m_data.data->start_one();
144 start(self.m_op);
145 }
146
149 };
150 };
151
152 template<typename Alloc, typename Send, typename Rec>
154
155 template<typename Alloc, typename Send>
156 struct NestSenderT {
157 struct Type {
158 using is_sender = void;
159
160 [[no_unique_address]] Send sender;
162
163 private:
164 template<concepts::RemoveCVRefSameAs<Type> Self, typename E>
169
170 template<concepts::RemoveCVRefSameAs<Type> Self, typename Rec>
171 requires(concepts::ReceiverOf<
173 friend auto tag_invoke(Tag<connect>, Self&& self, Rec receiver) {
175 self.data, util::forward_like<Self>(self.sender), util::move(receiver));
176 }
177
178 friend auto tag_invoke(Tag<get_env>, Type const& self) { return make_env(self.sender); }
179 };
180 };
181
182 template<typename Alloc, typename Send>
184
185 template<typename Alloc>
187 struct Type;
188
189 static auto get_data(Type&) -> Data<Alloc>*;
190 };
191
192 template<typename Op, typename Data>
194 struct Type {
195 using is_receiver = void;
196
197 Op* op;
199
200 friend void tag_invoke(Tag<set_value>, Type&& self) { self.op->cleanup(); }
201 friend void tag_invoke(Tag<set_stopped>, Type&& self) { self.op->cleanup(); }
202
203 friend auto tag_invoke(Tag<get_env>, Type const& self) { return self.data->get_env(); }
204 };
205 };
206
207 template<typename Op, typename Data>
209
210 template<typename Alloc, typename Rec>
213 public:
215
216 explicit Type(util::ReferenceWrapper<Scope> scope, Rec receiver)
217 : m_scope(scope), m_receiver(util::move(receiver)) {}
218
219 void cleanup() {
220 auto* data = CountingScopeT<Alloc>::get_data(m_scope);
221 data->did_complete = [this] {
222 execution::set_value(util::move(m_receiver));
223 };
224 data->complete_one();
225 }
226
227 private:
228 using TokenSender = decltype(just(util::declval<util::ReferenceWrapper<Scope>>()));
229 using NextSender = meta::NextSenderOf<Rec, TokenSender>;
231
232 friend void tag_invoke(Tag<start>, Type& self) {
233 auto& op = self.m_op.emplace(util::DeferConstruct([&] {
234 return connect(set_next(self.m_receiver, just(self.m_scope)),
235 RunReceiver<Type, Data<Alloc>>(util::addressof(self),
236 CountingScopeT<Alloc>::get_data(self.m_scope)));
237 }));
238 start(op);
239 }
240
242 [[no_unique_address]] Rec m_receiver;
244 };
245 };
246
247 template<typename Alloc, typename Rec>
249
250 template<typename Alloc>
252 struct Type {
254
256
258
261
262 template<typename Rec>
264 friend auto tag_invoke(Tag<subscribe>, Type&& self, Rec receiver) {
265 return RunOperation<Alloc, Rec>(self.scope, util::move(receiver));
266 }
267
268 friend auto tag_invoke(Tag<get_env>, Type const& self) {
269 return make_env(CountingScopeT<Alloc>::get_data(self.scope)->get_env(),
271 }
272 };
273 };
274
275 template<typename Alloc>
277
278 template<typename Alloc>
280 public:
281 auto data() -> Data<Alloc>* { return util::addressof(m_data); }
282
283 private:
284 template<concepts::SenderIn<Env<Alloc>> Send>
285 friend auto tag_invoke(Tag<nest>, Type& self, Send&& sender) {
286 return NestSender<Alloc, Send>(util::forward<Send>(sender), self.data());
287 }
288
289 friend auto tag_invoke(Tag<run>, Type& self) { return RunSequence<Alloc>(self); }
290
291 friend auto tag_invoke(Tag<get_env>, Type const& self) { return self.m_data.get_env(); }
292
293 Data<Alloc> m_data;
294 };
295
296 template<typename Alloc>
298 return self.data();
299 }
300}
301
320template<concepts::Allocator Alloc = platform::DefaultAllocator>
322}
323
324namespace di {
326}
Definition function.h:365
Definition atomic.h:15
Definition in_place_stop_source.h:11
auto get_stop_token() const -> InPlaceStopToken
Definition in_place_stop_token.h:31
Definition defer_construct.h:8
Definition reference_wrapper.h:14
Definition optional_forward_declaration.h:5
#define DI_IMMOVABLE_NO_UNIQUE_ADDRESS
Definition compiler.h:15
Definition receiver_of.h:25
Definition sequence_sender.h:128
A type which models an async scope.
Definition scope.h:180
Definition counting_scope.h:47
meta::Type< DataT< Alloc > > Data
Definition counting_scope.h:75
decltype(util::declval< Data< Alloc > const & >().get_env(util::declval< E const & >())) Env
Definition counting_scope.h:78
meta::Type< RunReceiverT< Op, Data > > RunReceiver
Definition counting_scope.h:208
meta::Type< NestOperationStateT< Alloc, Send, Rec > > NestOperationState
Definition counting_scope.h:153
meta::Type< RunSequenceT< Alloc > > RunSequence
Definition counting_scope.h:276
meta::Type< RunOperationT< Alloc, Rec > > RunOperation
Definition counting_scope.h:248
meta::Type< NestSenderT< Alloc, meta::RemoveCVRef< Send > > > NestSender
Definition counting_scope.h:183
meta::Type< NestReceiverT< Alloc, Rec > > NestReceiver
Definition counting_scope.h:129
meta::Type< NestDataT< Alloc, Rec > > NestData
Definition counting_scope.h:89
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 start
Definition start.h:20
meta::Type< counting_scope_ns::CountingScopeT< Alloc > > CountingScope
A scope that waits for all spawned senders to complete.
Definition counting_scope.h:321
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 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 get_stop_token
Definition get_stop_token.h:25
constexpr auto get_env
Definition get_env.h:27
constexpr auto get_allocator
Definition get_allocator.h:27
constexpr auto connect
Definition connect.h:42
constexpr auto set_value
Definition set_value.h:14
constexpr auto just
Definition just.h:86
T::Type Type
Definition core.h:26
decltype(execution::get_completion_signatures(util::declval< Sender >(), util::declval< Env >())) CompletionSignaturesOf
Definition completion_signatures_of.h:12
decltype(execution::set_next(util::declval< meta::RemoveCVRef< Rec > & >(), util::declval< Send >())) NextSenderOf
Definition sequence_sender.h:82
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
auto declval() -> meta::AddRValueReference< T >
Definition declval.h:8
constexpr auto forward_like(U &&value) -> decltype(auto)
Definition forward_like.h:8
Definition zstring_parser.h:9
constexpr auto c_
A value of type Constexpr<val>.
Definition constexpr.h:252
constexpr auto data
Definition data.h:51
Defines the sequence sender concepts and related CPOs.
Definition sequence_sender.h:86
Definition set_stopped.h:6
Definition set_value.h:6
static auto get_data(Type &) -> Data< Alloc > *
Definition counting_scope.h:297
auto data() -> Data< Alloc > *
Definition counting_scope.h:281
friend auto tag_invoke(Tag< nest >, Type &self, Send &&sender)
Definition counting_scope.h:285
friend auto tag_invoke(Tag< run >, Type &self)
Definition counting_scope.h:289
friend auto tag_invoke(Tag< get_env >, Type const &self)
Definition counting_scope.h:291
Definition counting_scope.h:50
void start_one()
Definition counting_scope.h:61
sync::InPlaceStopSource stop_source
Definition counting_scope.h:52
sync::Atomic< usize > count
Definition counting_scope.h:53
void complete_one()
Definition counting_scope.h:63
Alloc alloc
Definition counting_scope.h:51
auto get_env(Env const &env={}) const
Definition counting_scope.h:57
function::Function< void()> did_complete
Definition counting_scope.h:54
Definition counting_scope.h:49
Data< Alloc > * data
Definition counting_scope.h:83
Rec receiver
Definition counting_scope.h:84
Definition counting_scope.h:81
friend void tag_invoke(Tag< start >, Type &self)
Definition counting_scope.h:142
Type(Data< Alloc > *data, Send &&sender, Rec receiver)
Definition counting_scope.h:137
meta::ConnectResult< Send, NestReceiver< Alloc, Rec > > Op
Definition counting_scope.h:135
Type(NestData< Alloc, Rec > *data)
Definition counting_scope.h:99
auto base() &&-> Rec &&
Definition counting_scope.h:102
auto base() const &-> Rec const &
Definition counting_scope.h:101
void is_sender
Definition counting_scope.h:158
Send sender
Definition counting_scope.h:160
Data< Alloc > * data
Definition counting_scope.h:161
friend auto tag_invoke(Tag< connect >, Self &&self, Rec receiver)
Definition counting_scope.h:173
friend auto tag_invoke(Tag< get_completion_signatures >, Self &&, E &&) -> meta::CompletionSignaturesOf< meta::Like< Self, Send >, Env< Alloc, E > >
Definition counting_scope.h:165
friend auto tag_invoke(Tag< get_env >, Type const &self)
Definition counting_scope.h:178
Definition counting_scope.h:156
Type(util::ReferenceWrapper< Scope > scope, Rec receiver)
Definition counting_scope.h:216
void cleanup()
Definition counting_scope.h:219
friend void tag_invoke(Tag< start >, Type &self)
Definition counting_scope.h:232
Op * op
Definition counting_scope.h:197
Data * data
Definition counting_scope.h:198
friend void tag_invoke(Tag< set_stopped >, Type &&self)
Definition counting_scope.h:201
void is_receiver
Definition counting_scope.h:195
friend void tag_invoke(Tag< set_value >, Type &&self)
Definition counting_scope.h:200
friend auto tag_invoke(Tag< get_env >, Type const &self)
Definition counting_scope.h:203
Definition counting_scope.h:193
util::ReferenceWrapper< Scope > scope
Definition counting_scope.h:257
SequenceTag is_sender
Definition counting_scope.h:255
friend auto tag_invoke(Tag< subscribe >, Type &&self, Rec receiver)
Definition counting_scope.h:264
di::CompletionSignatures< SetValue(util::ReferenceWrapper< Scope >), SetStopped()> CompletionSignatures
Definition counting_scope.h:259
friend auto tag_invoke(Tag< get_env >, Type const &self)
Definition counting_scope.h:268
Definition counting_scope.h:251
Definition completion_signuatures.h:7
Definition immovable.h:4