2222#include < cassert>
2323#include < coroutine>
2424#include < exception>
25- #include < memory>
2625#include < print>
26+ #include < stop_token>
2727#include < type_traits>
2828#include < utility>
29- #include < variant>
3029#include " received.hxx"
31- #include " visitor.hxx"
3230
3331namespace fastipc ::co {
3432
33+ template <class T >
34+ class Receiver {
35+ public:
36+ Receiver () = default ;
37+
38+ Receiver (Receiver&&) noexcept = default ;
39+ Receiver& operator =(Receiver&&) noexcept = default ;
40+
41+ Receiver (const Receiver&) noexcept = default ;
42+ Receiver& operator =(const Receiver&) noexcept = default ;
43+
44+ virtual ~Receiver () = default ;
45+
46+ virtual void set_value (T value) noexcept = 0;
47+ virtual void set_exception (std::exception_ptr error) noexcept = 0;
48+ virtual void set_stopped () noexcept = 0;
49+ };
50+
51+ template <>
52+ class Receiver <void > {
53+ public:
54+ Receiver () = default ;
55+
56+ Receiver (Receiver&&) noexcept = default ;
57+ Receiver& operator =(Receiver&&) noexcept = default ;
58+
59+ Receiver (const Receiver&) noexcept = default ;
60+ Receiver& operator =(const Receiver&) noexcept = default ;
61+
62+ virtual ~Receiver () = default ;
63+
64+ virtual void set_value () noexcept = 0;
65+ virtual void set_exception (std::exception_ptr error) noexcept = 0;
66+ virtual void set_stopped () noexcept = 0;
67+ };
68+
69+ class Handler {
70+ public:
71+ Handler () = default ;
72+
73+ Handler (Handler&&) noexcept = delete ;
74+ Handler& operator =(Handler&&) noexcept = delete ;
75+
76+ Handler (const Handler&) noexcept = delete ;
77+ Handler& operator =(const Handler&) noexcept = delete ;
78+
79+ virtual ~Handler () = default ;
80+
81+ virtual void unhandled_exception () noexcept = 0;
82+ virtual void unhandled_stopped () noexcept = 0;
83+ };
84+
3585template <class T >
3686concept valueless = std::is_void_v<T>;
3787
@@ -45,7 +95,7 @@ template <class T, class Env>
4595class Task ;
4696
4797template <class Env >
48- class EnvAwaiter final {
98+ class EnvAwaiter {
4999 public:
50100 bool await_ready () noexcept { return false ; }
51101
@@ -62,12 +112,12 @@ class EnvAwaiter final {
62112 const Env* m_env = nullptr ;
63113};
64114
65- struct GetEnv final {};
115+ struct GetEnv {};
66116
67117constexpr GetEnv getEnv () noexcept { return {}; }
68118
69119template <class T , class Env >
70- class [[nodiscard]] Co final {
120+ class [[nodiscard]] Co {
71121 public:
72122 using promise_type = Promise<T, Env>;
73123 using handle_type = std::coroutine_handle<promise_type>;
@@ -104,63 +154,25 @@ class [[nodiscard]] Co final {
104154 handle_type m_handle;
105155};
106156
107- template <class T >
108- class Receiver {
109- public:
110- Receiver () = default ;
111-
112- Receiver (Receiver&&) noexcept = default ;
113- Receiver& operator =(Receiver&&) noexcept = default ;
114-
115- Receiver (const Receiver&) noexcept = default ;
116- Receiver& operator =(const Receiver&) noexcept = default ;
117-
118- virtual ~Receiver () = default ;
119-
120- virtual void set_value (T value) noexcept = 0;
121- virtual void set_exception (std::exception_ptr error) noexcept = 0;
122- };
123-
124- template <>
125- class Receiver <void > {
126- public:
127- Receiver () = default ;
128-
129- Receiver (Receiver&&) noexcept = default ;
130- Receiver& operator =(Receiver&&) noexcept = default ;
131-
132- Receiver (const Receiver&) noexcept = default ;
133- Receiver& operator =(const Receiver&) noexcept = default ;
134-
135- virtual ~Receiver () = default ;
136-
137- virtual void set_value () noexcept = 0;
138- virtual void set_exception (std::exception_ptr error) noexcept = 0;
139- };
140-
141157template <class T , class Env >
142- class FinalAwaiter final {
158+ class FinalAwaiter {
143159 public:
144160 bool await_ready () noexcept { return false ; }
145161
146162 std::coroutine_handle<> await_suspend (std::coroutine_handle<Promise<T, Env>> completed) {
147163 assert (completed.promise ().m_received .has_value ());
148164 auto & promise = completed.promise ();
149165
150- return match (
151- std::move (promise.m_cont ), [](std::coroutine_handle<> cont) -> std::coroutine_handle<> { return cont; },
152- [&promise](std::shared_ptr<Receiver<T>> receiver) -> std::coroutine_handle<> {
153- std::move (promise.m_received ).forward (*receiver);
166+ std::move (promise.m_received ).forward (*promise.m_cont );
154167
155- return std::noop_coroutine ();
156- });
168+ return std::noop_coroutine ();
157169 }
158170
159171 void await_resume () noexcept {}
160172};
161173
162174template <class T , class Env >
163- class Promise final {
175+ class Promise : public Handler {
164176 public:
165177 Promise () = default ;
166178
@@ -170,7 +182,7 @@ class Promise final {
170182 Promise (const Promise&) noexcept = delete ;
171183 Promise& operator =(const Promise&) noexcept = delete ;
172184
173- ~Promise () noexcept = default ;
185+ ~Promise () noexcept override = default ;
174186
175187 Co<T, Env> get_return_object () { return Co<T, Env>{std::coroutine_handle<Promise>::from_promise (*this )}; }
176188
@@ -182,7 +194,8 @@ class Promise final {
182194 }
183195
184196 void return_value (T value) noexcept { m_received.set_value (std::move (value)); }
185- void unhandled_exception () noexcept { m_received.set_exception (std::current_exception ()); }
197+ void unhandled_exception () noexcept override { m_received.set_exception (std::current_exception ()); }
198+ void unhandled_stopped () noexcept override { m_received.set_stopped (); }
186199
187200 template <class A >
188201 decltype (auto ) await_transform(A&& awaitable) noexcept {
@@ -192,6 +205,7 @@ class Promise final {
192205 EnvAwaiter<Env> await_transform (GetEnv) { return EnvAwaiter<Env>{}; }
193206
194207 const Env& env () const { return *m_env; }
208+ std::stop_token stop_token () { return m_env->stop_token ; }
195209
196210 private:
197211 friend class Co <T, Env>;
@@ -201,13 +215,13 @@ class Promise final {
201215
202216 Received<T> m_received;
203217
204- std::variant<std::coroutine_handle<>, std::shared_ptr< Receiver<T>>> m_cont = std::noop_coroutine() ;
218+ Receiver<T>* m_cont = nullptr ;
205219
206220 const Env* m_env;
207221};
208222
209223template <class Env >
210- class Promise <void , Env> final {
224+ class Promise <void , Env> : public Handler {
211225 public:
212226 Promise () = default ;
213227
@@ -217,7 +231,7 @@ class Promise<void, Env> final {
217231 Promise (const Promise&) noexcept = delete ;
218232 Promise& operator =(const Promise&) noexcept = delete ;
219233
220- ~Promise () noexcept = default ;
234+ ~Promise () noexcept override = default ;
221235
222236 Co<void , Env> get_return_object () { return Co<void , Env>{std::coroutine_handle<Promise>::from_promise (*this )}; }
223237
@@ -229,8 +243,8 @@ class Promise<void, Env> final {
229243 }
230244
231245 void return_void () noexcept { m_received.set_value (); }
232-
233- void unhandled_exception () noexcept { m_received.set_exception ( std::current_exception () ); }
246+ void unhandled_exception () noexcept override { m_received. set_exception ( std::current_exception ()); }
247+ void unhandled_stopped () noexcept override { m_received.set_stopped ( ); }
234248
235249 template <class A >
236250 decltype (auto ) await_transform(A&& awaitable) noexcept {
@@ -240,6 +254,7 @@ class Promise<void, Env> final {
240254 EnvAwaiter<Env> await_transform (GetEnv) { return EnvAwaiter<Env>{}; }
241255
242256 const Env& env () const { return *m_env; }
257+ std::stop_token stop_token () { return m_env->stop_token ; }
243258
244259 private:
245260 friend class Co <void , Env>;
@@ -248,13 +263,78 @@ class Promise<void, Env> final {
248263 friend class Task <void , Env>;
249264
250265 Received<void > m_received;
251- std::variant<std::coroutine_handle<>, std::shared_ptr<Receiver<void >>> m_cont = std::noop_coroutine();
266+ Receiver<void >* m_cont = nullptr ;
267+
268+ const Env* m_env;
269+ };
270+
271+ template <class T , class Env >
272+ class CoReceiver : public Receiver <T> {
273+ public:
274+ CoReceiver () : Receiver<T>{} {}
275+ CoReceiver (std::coroutine_handle<> cont, const Env* env) : m_cont{cont}, m_env{env} {}
276+
277+ void set_value (T value) noexcept override {
278+ m_received.set_value (std::move (value));
279+
280+ m_env->scheduler ->schedule ([cont = m_cont]() { cont.resume (); });
281+ };
252282
283+ void set_exception (std::exception_ptr error) noexcept override {
284+ m_received.set_exception (error);
285+
286+ m_env->scheduler ->schedule ([cont = m_cont]() { cont.resume (); });
287+ };
288+
289+ // these also need to be scheduled...
290+ void set_stopped () noexcept override { m_received.set_stopped (); };
291+
292+ T resume () {
293+ assert (m_received.has_value ());
294+
295+ return std::move (m_received).consume ();
296+ }
297+
298+ private:
299+ Received<T> m_received;
300+ std::coroutine_handle<> m_cont;
301+ const Env* m_env;
302+ };
303+
304+ template <class Env >
305+ class CoReceiver <void , Env> : public Receiver<void > {
306+ public:
307+ CoReceiver () : Receiver<void >{} {}
308+ CoReceiver (std::coroutine_handle<> cont, const Env* env) : m_cont{cont}, m_env{env} {}
309+
310+ void set_value () noexcept override {
311+ m_received.set_value ();
312+
313+ m_env->scheduler ->schedule ([cont = m_cont]() { cont.resume (); });
314+ };
315+
316+ void set_exception (std::exception_ptr error) noexcept override {
317+ m_received.set_exception (error);
318+
319+ m_env->scheduler ->schedule ([cont = m_cont]() { cont.resume (); });
320+ };
321+
322+ // these also need to be scheduled...
323+ void set_stopped () noexcept override { m_received.set_stopped (); };
324+
325+ void resume () {
326+ assert (m_received.has_value ());
327+ std::move (m_received).consume ();
328+ }
329+
330+ private:
331+ Received<void > m_received;
332+ std::coroutine_handle<> m_cont;
253333 const Env* m_env;
254334};
255335
256336template <class T , class Env >
257- class [[nodiscard]] CoAwaiter final {
337+ class [[nodiscard]] CoAwaiter {
258338 public:
259339 explicit CoAwaiter (Co<T, Env> co) noexcept : m_co{std::move (co)} {}
260340
@@ -270,23 +350,26 @@ class [[nodiscard]] CoAwaiter final {
270350
271351 template <class S >
272352 std::coroutine_handle<> await_suspend (std::coroutine_handle<Promise<S, Env>> cont) {
273- m_co.m_handle .promise ().m_env = &cont.promise ().env ();
274- m_co.m_handle .promise ().m_cont = cont;
353+ const auto env = &cont.promise ().env ();
275354
355+ m_co.env (env);
356+
357+ m_receiver = {cont, env};
358+ m_co.m_handle .promise ().m_cont = &m_receiver;
359+
360+ // TODO: move to scheduler
276361 return m_co.m_handle ;
277362 }
278363
279364 T await_resume () {
280- auto co = std::move (m_co);
281-
282- auto & promise = co.m_handle .promise ();
365+ auto _ = std::move (m_co);
283366
284- assert (promise.m_received .has_value ());
285- return std::move (promise.m_received ).consume ();
367+ return m_receiver.resume ();
286368 }
287369
288370 private:
289371 Co<T, Env> m_co;
372+ CoReceiver<T, Env> m_receiver;
290373};
291374
292375template <class T , class Env >
0 commit comments