85 lines
1.9 KiB
C++
85 lines
1.9 KiB
C++
#pragma once
|
|
|
|
#include <coroutine>
|
|
#include <optional>
|
|
|
|
namespace bt {
|
|
enum class task_result { failure, success };
|
|
|
|
class node_task {
|
|
public:
|
|
class promise_type;
|
|
|
|
using handle_type = std::coroutine_handle<promise_type>;
|
|
|
|
class promise_type {
|
|
public:
|
|
std::optional<task_result> result;
|
|
handle_type get_return_object() noexcept {
|
|
return handle_type::from_promise(*this);
|
|
}
|
|
|
|
std::suspend_always initial_suspend() noexcept { return {}; }
|
|
|
|
std::suspend_always final_suspend() noexcept { return {}; }
|
|
|
|
void return_value(task_result r) noexcept { result = r; }
|
|
|
|
void unhandled_exception() noexcept {
|
|
// std::terminate(); // TODO: handle exception
|
|
}
|
|
};
|
|
|
|
class awaiter {
|
|
public:
|
|
awaiter(handle_type handle) noexcept : _handle(handle) {}
|
|
|
|
bool await_ready() const noexcept { return false; }
|
|
|
|
auto await_suspend(std::coroutine_handle<>) noexcept { return _handle; }
|
|
|
|
task_result await_resume() noexcept { return *_handle.promise().result; }
|
|
|
|
private:
|
|
handle_type _handle;
|
|
};
|
|
|
|
node_task(handle_type handle) noexcept : _handle(handle) {}
|
|
|
|
node_task(node_task &&other) noexcept : _handle(other._handle) {
|
|
other._handle = nullptr;
|
|
}
|
|
|
|
~node_task() {
|
|
if (_handle) {
|
|
_handle.destroy();
|
|
}
|
|
}
|
|
|
|
node_task &operator=(node_task &&other) noexcept {
|
|
if (&other != this) {
|
|
if (_handle) {
|
|
_handle.destroy();
|
|
}
|
|
_handle = other._handle;
|
|
other._handle = nullptr;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
awaiter operator co_await() noexcept { return awaiter{_handle}; }
|
|
|
|
void resume() noexcept { _handle.resume(); }
|
|
|
|
bool done() const noexcept { return _handle.done(); }
|
|
|
|
task_result result() noexcept { return *_handle.promise().result; }
|
|
|
|
std::optional<task_result> try_result() noexcept {
|
|
return _handle.promise().result;
|
|
}
|
|
|
|
private:
|
|
handle_type _handle;
|
|
};
|
|
} // namespace bt
|