Coroutines mostly working, although not nearly as fancy as cppcoro. I'll try them out in my code and if I like it I'll probably just go use cppcoro.
parent
daf9a3cc07
commit
8f7235ade1
@ -0,0 +1,104 @@ |
||||
#pragma once |
||||
#include <concepts> |
||||
#include <coroutine> |
||||
#include <exception> |
||||
#include <assert.h> |
||||
|
||||
using namespace std; |
||||
|
||||
enum TaskStates { |
||||
STARTED, AWAIT, YIELD, |
||||
EXCEPTION, RETURN, |
||||
RETURN_VOID, DEAD |
||||
}; |
||||
|
||||
template<typename T> |
||||
struct Task { |
||||
struct promise_type; |
||||
|
||||
using handle_type = std::coroutine_handle<promise_type>; |
||||
|
||||
struct promise_type { |
||||
T value_; |
||||
std::exception_ptr exception_; |
||||
TaskStates state_{STARTED}; |
||||
|
||||
Task get_return_object() { |
||||
return Task(handle_type::from_promise(*this)); |
||||
} |
||||
|
||||
std::suspend_always initial_suspend() { |
||||
state_ = AWAIT; |
||||
return {}; |
||||
} |
||||
|
||||
std::suspend_always final_suspend() noexcept { |
||||
return {}; |
||||
} |
||||
|
||||
void unhandled_exception() { |
||||
state_ = EXCEPTION; |
||||
exception_ = std::current_exception(); |
||||
} |
||||
|
||||
template<std::convertible_to<T> From> // C++20 concept
|
||||
void return_value(From &&from) { |
||||
state_ = RETURN; |
||||
value_ = std::forward<From>(from); |
||||
} |
||||
|
||||
template<std::convertible_to<T> From> // C++20 concept
|
||||
std::suspend_always yield_value(From &&from) { |
||||
state_ = YIELD; |
||||
value_ = std::forward<From>(from); |
||||
return {}; |
||||
} |
||||
|
||||
void return_void() { |
||||
state_ = RETURN_VOID; |
||||
} |
||||
}; |
||||
|
||||
handle_type h_; |
||||
|
||||
Task() { |
||||
} |
||||
|
||||
Task(handle_type h) : h_(h) { |
||||
} |
||||
|
||||
Task(const Task &t) : h_(t.h_) { |
||||
} |
||||
|
||||
void destroy() { |
||||
// this should make it safe to clal repeatedly
|
||||
if(h_.promise().state_ != DEAD) { |
||||
h_.destroy(); |
||||
h_.promise().state_ = DEAD; |
||||
} |
||||
} |
||||
|
||||
T operator()() { |
||||
assert(!h_.done()); |
||||
call(); |
||||
return std::move(h_.promise().value_); |
||||
} |
||||
|
||||
bool done() { |
||||
return h_.done(); |
||||
} |
||||
|
||||
TaskStates state() { |
||||
return h_.promise().state_; |
||||
} |
||||
|
||||
private: |
||||
|
||||
void call() { |
||||
h_(); |
||||
|
||||
if (h_.promise().exception_) { |
||||
std::rethrow_exception(h_.promise().exception_); |
||||
} |
||||
} |
||||
}; |
Loading…
Reference in new issue