@@ -129,6 +129,15 @@ struct Promise : Promise_Base<R, A> {
129129 friend struct Task <R, A>;
130130};
131131
132+ template <typename T>
133+ concept Is_Task = requires (T t) {
134+ typename T::promise_type;
135+ typename T::return_type;
136+ { t.await_ready () } -> Same<bool >;
137+ { t.await_suspend (std::coroutine_handle<>()) } -> Same<bool >;
138+ { t.await_resume () } -> Same<typename T::return_type>;
139+ };
140+
132141template <typename R, Allocator A>
133142struct Task {
134143
@@ -142,8 +151,13 @@ struct Task {
142151 }
143152
144153 ~Task () noexcept {
145- if (handle && handle.promise ().state .exchange (TASK_ABANDONED) == TASK_DONE) {
146- handle.destroy ();
154+ if (handle) {
155+ auto state = handle.promise ().state .exchange (TASK_ABANDONED);
156+ if (state == TASK_DONE) {
157+ handle.destroy ();
158+ } else if (state != TASK_START) {
159+ die (" Task abandoned while being waited upon." );
160+ }
147161 }
148162 handle = null;
149163 }
@@ -198,6 +212,17 @@ struct Task {
198212 return handle != null;
199213 }
200214
215+ template <typename F>
216+ requires Invocable<F, R> && Is_Task<Invoke_Result<F, R>>
217+ [[nodiscard]] auto then (F&& f) noexcept -> Invoke_Result<F, R> {
218+ if constexpr (Same<R, void >) {
219+ co_await *this ;
220+ co_return (co_await f ());
221+ } else {
222+ co_return (co_await f (co_await *this ));
223+ }
224+ }
225+
201226private:
202227 std::coroutine_handle<Promise<R, A>> handle;
203228};
0 commit comments