bt/include/bt/node_task.hpp

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