@@ -23,9 +23,12 @@ namespace pot::coroutines::detail
2323 {
2424 bool await_ready () const noexcept { return false ; }
2525 template <typename PROMISE>
26- std::coroutine_handle<> await_suspend (std::coroutine_handle<PROMISE> h ) const noexcept
26+ std::coroutine_handle<> await_suspend (std::coroutine_handle<PROMISE> handle ) const noexcept
2727 {
28- return h.promise ().m_continuation ? h.promise ().m_continuation : std::noop_coroutine ();
28+ handle.promise ().m_ready .store (true , std::memory_order_release);
29+ if (handle.promise ().m_continuation )
30+ return handle.promise ().m_continuation ;
31+ return std::noop_coroutine ();
2932 }
3033 void await_resume () const noexcept {}
3134 };
@@ -40,23 +43,17 @@ namespace pot::coroutines::detail
4043 void set_value (U &&value)
4144 {
4245 m_data.template emplace <T>(std::forward<U>(value));
43- if (m_ready.exchange (true , std::memory_order_release))
44- throw std::runtime_error (" Value already set in promise_type." );
4546 }
4647
4748 void set_value ()
4849 requires(std::is_void_v<T>)
4950 {
5051 m_data.template emplace <std::monostate>();
51- if (m_ready.exchange (true , std::memory_order_release))
52- throw std::runtime_error (" Void value already set in promise_type." );
5352 }
5453
5554 void set_exception (std::exception_ptr exception)
5655 {
5756 m_data.template emplace <std::exception_ptr>(exception);
58- if (m_ready.exchange (true , std::memory_order_release))
59- throw std::runtime_error (" Exception already set in promise_type." );
6057 }
6158
6259 bool is_ready () const noexcept { return m_ready.load (std::memory_order_acquire); }
@@ -99,9 +96,9 @@ namespace pot::coroutines
9996 * @tparam T The result type (may be `void`).
10097 *
10198 * @return
102- * - `co_await lazy_task<T>`: Suspends caller until the coroutine completes.
99+ * - `co_await lazy_task<T>`: Suspends caller until the coroutine completes.
103100 * Returns the stored value (or nothing for `void`).
104- * - `get()`: Runs to completion synchronously and returns the result.
101+ * - `get()`: Runs to completion synchronously and returns the result.
105102 * - `sync_wait()`: Busy-waits until ready and then returns the result.
106103 */
107104 template <typename T>
@@ -113,7 +110,7 @@ namespace pot::coroutines
113110 using value_type = T;
114111
115112 lazy_task () = default ;
116- explicit lazy_task (handle_type h ) noexcept : m_handle(h ) {}
113+ explicit lazy_task (handle_type handle ) noexcept : m_handle(handle ) {}
117114
118115 lazy_task (lazy_task const &) = delete ;
119116 lazy_task &operator =(lazy_task const &) = delete ;
@@ -131,55 +128,70 @@ namespace pot::coroutines
131128 return *this ;
132129 }
133130
134- explicit operator bool () const noexcept { return m_handle && m_handle. done () ; }
131+ explicit operator bool () const noexcept { return m_handle != nullptr ; }
135132
136- bool await_ready () const noexcept
133+ auto operator co_await () && noexcept
137134 {
138- return !m_handle || m_handle.promise ().is_ready ();
135+ struct awaiter
136+ {
137+ handle_type handle;
138+
139+ bool await_ready () const noexcept
140+ {
141+ return !handle || handle.promise ().is_ready ();
142+ }
143+
144+ void await_suspend (std::coroutine_handle<> awaiting) noexcept
145+ {
146+ handle.promise ().m_continuation = awaiting;
147+
148+ if (!handle || handle.promise ().is_ready ())
149+ awaiting.resume ();
150+
151+ if (handle && !handle.done ())
152+ handle.resume ();
153+ }
154+
155+ auto await_resume ()
156+ {
157+ if constexpr (std::is_void_v<T>)
158+ {
159+ handle.promise ().get ();
160+ handle.destroy ();
161+ return ;
162+ }
163+ else
164+ {
165+ auto result = handle.promise ().get ();
166+ handle.destroy ();
167+ return result;
168+ }
169+ }
170+ };
171+
172+ return awaiter{std::exchange (m_handle, {})};
139173 }
140174
141- template <typename PROMISE>
142- void await_suspend (std::coroutine_handle<PROMISE> awaiting)
175+ auto get ()
143176 {
144- m_handle.promise ().m_continuation = awaiting;
145- if (!m_handle.done ())
146- m_handle.resume ();
147- }
177+ auto handle = std::exchange (m_handle, {});
178+ if (handle && !handle.promise ().is_ready ())
179+ handle.resume ();
148180
149- auto await_resume ()
150- {
151181 if constexpr (std::is_void_v<T>)
152182 {
153- m_handle.promise ().get ();
183+ handle.promise ().get ();
184+ handle.destroy ();
154185 return ;
155186 }
156187 else
157188 {
158- return m_handle.promise ().get ();
189+ auto result = handle.promise ().get ();
190+ handle.destroy ();
191+ return result;
159192 }
160193 }
161194
162- auto get ()
163- {
164- if (m_handle && !m_handle.promise ().is_ready ())
165- m_handle.resume ();
166-
167- if constexpr (std::is_void_v<T>)
168- m_handle.promise ().get ();
169- else
170- return m_handle.promise ().get ();
171- }
172-
173- auto sync_wait ()
174- {
175- m_handle.promise ().wait ();
176-
177- if constexpr (std::is_void_v<T>)
178- m_handle.promise ().get ();
179- else
180- return m_handle.promise ().get ();
181- }
182-
183195 ~lazy_task ()
184196 {
185197 if (m_handle)
@@ -233,51 +245,65 @@ namespace pot::coroutines
233245 return *this ;
234246 }
235247
236- explicit operator bool () const noexcept { return m_handle && m_handle. done () ; }
248+ explicit operator bool () const noexcept { return m_handle != nullptr ; }
237249
238- bool await_ready () const noexcept { return !m_handle || m_handle.promise ().is_ready (); }
239-
240- template <typename PROMISE>
241- void await_suspend (std::coroutine_handle<PROMISE> awaiting)
250+ auto operator co_await () && noexcept
242251 {
243- m_handle.promise ().m_continuation = awaiting;
244- if (!m_handle.done ())
245- m_handle.resume ();
252+ struct awaiter
253+ {
254+ handle_type handle;
255+
256+ bool await_ready () const noexcept
257+ {
258+ return !handle || handle.promise ().is_ready ();
259+ }
260+
261+ void await_suspend (std::coroutine_handle<> awaiting) noexcept
262+ {
263+ awaiting.resume ();
264+ }
265+
266+ auto await_resume ()
267+ {
268+ if constexpr (std::is_void_v<T>)
269+ {
270+ handle.promise ().get ();
271+ handle.destroy ();
272+ return ;
273+ }
274+ else
275+ {
276+ auto res = handle.promise ().get ();
277+ handle.destroy ();
278+ return res;
279+ }
280+ }
281+ };
282+
283+ return awaiter{std::exchange (m_handle, {})};
246284 }
247285
248- auto await_resume ()
286+ auto get ()
249287 {
288+ auto handle = std::exchange (m_handle, {});
289+ if (!handle)
290+ throw std::runtime_error (" get() on empty lazy_task" );
291+
250292 if constexpr (std::is_void_v<T>)
251293 {
252- m_handle.promise ().get ();
294+ handle.promise ().get ();
295+ handle.destroy ();
253296 return ;
254297 }
255298 else
256299 {
257- return m_handle.promise ().get ();
300+ auto result = handle.promise ().get ();
301+ handle.destroy ();
302+ return result;
258303 }
259304 }
260305
261- auto get ()
262- {
263- if (m_handle && !m_handle.promise ().is_ready ())
264- m_handle.resume ();
265-
266- if constexpr (std::is_void_v<T>)
267- m_handle.promise ().get ();
268- else
269- return m_handle.promise ().get ();
270- }
271-
272- auto sync_wait ()
273- {
274- m_handle.promise ().wait ();
275-
276- if constexpr (std::is_void_v<T>)
277- m_handle.promise ().get ();
278- else
279- return m_handle.promise ().get ();
280- }
306+ void sync_wait () {}
281307
282308 ~task ()
283309 {
@@ -410,4 +436,4 @@ namespace pot::traits
410436 };
411437 template <typename T>
412438 using awaitable_value_t = typename awaitable_value<T>::type;
413- } // namespace pot
439+ } // namespace pot
0 commit comments