Skip to content

Instantly share code, notes, and snippets.

@HappyCerberus
Created November 30, 2021 09:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HappyCerberus/5b48d7bd4849be4879368add643ce522 to your computer and use it in GitHub Desktop.
Save HappyCerberus/5b48d7bd4849be4879368add643ce522 to your computer and use it in GitHub Desktop.
[Article] C++20 Practical Coroutines - chainable
struct awaitable_final_continuation {
constexpr bool await_ready() const noexcept { return false; }
std::coroutine_handle<>
await_suspend(HandleWithContinuation auto caller) const noexcept {
return caller.promise().continuation;
}
constexpr void await_resume() const noexcept {}
};
struct chainable_task {
struct chainable_promise {
using handle_t = std::coroutine_handle<chainable_promise>;
chainable_task get_return_object() {
return chainable_task{handle_t::from_promise(*this)};
}
std::suspend_always initial_suspend() noexcept { return {}; }
awaitable_final_continuation final_suspend() noexcept { return {}; }
void unhandled_exception() { std::terminate(); }
void return_value(utils::AwaitResult result) { result_ = result; }
private:
std::coroutine_handle<> continuation = std::noop_coroutine();
utils::AwaitResult result_;
friend struct chainable_task;
friend struct awaitable_final_continuation;
};
using promise_type = chainable_promise;
explicit chainable_task(promise_type::handle_t handle) : handle_(handle) {}
chainable_task(const chainable_task &) = delete;
chainable_task(chainable_task &&task)
: handle_(std::exchange(task.handle_, nullptr)) {}
chainable_task &operator=(const chainable_task &) = delete;
chainable_task &operator=(chainable_task &&task) {
handle_ = std::exchange(task.handle_, nullptr);
return *this;
}
~chainable_task() {
if (handle_)
handle_.destroy();
}
bool await_ready() noexcept { return false; }
std::coroutine_handle<> await_suspend(std::coroutine_handle<> caller) {
handle_.promise().continuation = caller;
return handle_;
}
utils::AwaitResult await_resume() { return handle_.promise().result_; }
private:
promise_type::handle_t handle_;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment