Skip to content

Commit ee03159

Browse files
committed
task.then
1 parent 52c3a60 commit ee03159

File tree

1 file changed

+27
-2
lines changed

1 file changed

+27
-2
lines changed

rpp/async.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
132141
template<typename R, Allocator A>
133142
struct 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+
201226
private:
202227
std::coroutine_handle<Promise<R, A>> handle;
203228
};

0 commit comments

Comments
 (0)