blob: 05ce08567b2a65dc0858bc4e4694001b4ffedf90 [file] [log] [blame]
#include <optional>
#include <utility>
#include <coroutine>
template <typename T>
struct [[nodiscard]] task {
struct promise_type {
std::suspend_always initial_suspend() {
return {};
}
auto final_suspend() noexcept {
struct awaiter {
#if 1
std::false_type await_ready() noexcept {
return {};
}
#else
bool await_ready() noexcept {
return false;
}
#endif
std::coroutine_handle<> await_suspend(std::coroutine_handle<>) noexcept {
return next;
}
void await_resume() noexcept {
}
std::coroutine_handle<> next;
};
return awaiter{next};
}
void unhandled_exception() noexcept {
std::terminate();
}
auto get_return_object() {
return task(this);
}
auto coro() {
return std::coroutine_handle<promise_type>::from_promise(*this);
}
void return_value(T val) {
result.emplace(std::move(val));
}
std::coroutine_handle<> next;
std::optional<T> result;
};
task(task&& source) : p(std::exchange(source.p, nullptr)) {}
explicit task(promise_type* p) : p(p) {}
~task() {
if (p)
p->coro().destroy();
}
bool await_ready() noexcept {
return p->coro().done();
}
std::coroutine_handle<> await_suspend(std::coroutine_handle<> next) noexcept {
p->next = next;
return p->coro();
}
const T& await_resume() const& noexcept {
return *p->result;
}
promise_type* p;
};
task<int> five() {
co_return 5;
}
task<int> six() {
co_return co_await five() + 1;
}
int main() {
auto task = six();
task.p->next = std::noop_coroutine();
task.p->coro().resume();
return *task.p->result;
}