AutoCatGnome/coro/Task.h
2022-01-05 22:36:47 +03:00

102 lines
2.5 KiB
C++

//
// Created by selim on 03.01.2022.
//
#ifndef AUTOCAT_GNOME_TASK_H
#define AUTOCAT_GNOME_TASK_H
#include <coroutine>
#include <iostream>
#include <optional>
template<typename T>
class Task {
public:
struct promise_type {
auto initial_suspend() const noexcept {
std::cout << "initial_suspend" << std::endl;
return std::suspend_never();
}
auto final_suspend() const noexcept {
std::cout << "final_suspend" << std::endl;
return std::suspend_never();
}
Task<T> get_return_object() {
std::cout << "get_return_object" << std::endl;
return Task<T>{ std::coroutine_handle<promise_type>::from_promise(*this) };
}
void return_value(const T& value) noexcept(std::is_nothrow_copy_constructible_v<T>) {
std::cout << "return_value: " << value << std::endl;
_value = value;
}
// void return_void() {
// std::cout << "return_void" << std::endl;
// }
void unhandled_exception() {
std::cout << "unhandled_exception" << std::endl;
throw;
}
};
private:
std::optional<T> _value = std::nullopt;
std::coroutine_handle<promise_type> _handle;
//public:
// bool await_ready() const noexcept {
// std::cout << "Awaiter::await_ready" << std::endl;
// return false;
// }
//
// void await_suspend(std::coroutine_handle<promise_type> handle) const {
// std::cout << "Awaiter::await_suspend" << std::endl;
// _handle = handle;
// }
//
// T await_resume() {
// std::cout << "Awaiter::await_resume" << std::endl;
// return _value.value();
// }
public:
void set_result(T result) {
_value = result;
_handle();
}
};
template<typename U> struct Awaiter {
public:
bool await_ready() const noexcept {
std::cout << "Awaiter::await_ready" << std::endl;
return false;
}
void await_suspend(std::coroutine_handle<typename Task<U>::promise_type> cont) const {
std::cout << "Awaiter::await_suspend" << std::endl;
}
U await_resume() {
std::cout << "Awaiter::await_resume" << std::endl;
return _task.value();
}
private:
Task<U> _task;
public:
explicit Awaiter(Task<U> task): _task(task) {}
};
template<typename T>
auto operator co_await(Task<T> task) noexcept /*requires(!std::is_reference_v<T>)*/ {
return Awaiter<T>(task);
}
#endif //AUTOCAT_GNOME_TASK_H