Commit bb84968a authored by Xavier Thompson's avatar Xavier Thompson

WIP Minimise suspension coroutines

parent 9171a165
#ifndef __PROMISE_HPP__
#define __PROMISE_HPP__
#include <type_traits>
#include <result.hpp>
namespace typon
{
template <typename T>
struct promise
{
result<T>* _result;
template <typename U>
void return_value(U&& expr) noexcept(std::is_nothrow_constructible_v<T, U&&>)
{
_result->return_value(std::forward<U>(expr));
}
void unhandled_exception() noexcept
{
_result->unhandled_exception();
}
};
template <>
struct promise<void>
{
result<void>* _result;
void return_void() noexcept {}
void unhandled_exception() noexcept
{
_result->unhandled_exception();
}
};
}
#endif // __PROMISE_HPP__
......@@ -18,6 +18,7 @@ namespace typon
{
T _value;
};
bool _ready;
~result()
{
......@@ -31,11 +32,18 @@ namespace typon
void return_value(U&& expr) noexcept(std::is_nothrow_constructible_v<T, U&&>)
{
std::construct_at(std::addressof(_value), std::forward<U>(expr));
_ready = true;
}
void unhandled_exception() noexcept
{
_exception = std::current_exception();
_ready = true;
}
bool ready() const noexcept
{
return _ready;
}
T& get() &
......@@ -63,15 +71,18 @@ namespace typon
{
T* _value;
std::exception_ptr _exception;
bool _ready;
void return_value(T& expr) noexcept
{
_value = std::addressof(expr);
_ready = true;
}
void unhandled_exception() noexcept
{
_exception = std::current_exception();
_ready = true;
}
T& get() &
......@@ -89,12 +100,17 @@ namespace typon
struct result<void>
{
std::exception_ptr _exception;
bool _ready;
void return_void() noexcept {}
void return_void() noexcept
{
_ready = true;
}
void unhandled_exception() noexcept
{
_exception = std::current_exception();
_ready = true;
}
void get()
......
......@@ -4,6 +4,7 @@
#include <coroutine>
#include <result.hpp>
#include <promise.hpp>
namespace typon
......@@ -15,19 +16,19 @@ namespace typon
struct promise_type;
std::coroutine_handle<promise_type> _coroutine;
result<T> _result;
~task()
{
_coroutine.destroy();
}
struct promise_type : result<T>
struct promise_type : promise<T>
{
std::coroutine_handle<> _continuation;
task get_return_object() noexcept
{
return { std::coroutine_handle<promise_type>::from_promise(*this) };
task t {};
auto h = std::coroutine_handle<promise_type>::from_promise(*this);
t._coroutine = h;
h.promise()._result = std::addressof(t._result);
return t;
}
std::suspend_never initial_suspend() noexcept
......@@ -37,31 +38,43 @@ namespace typon
auto final_suspend() noexcept
{
struct awaitable : std::suspend_always
struct awaitable
{
bool _ready;
bool await_ready() noexcept
{
return _ready;
}
std::coroutine_handle<> await_suspend(std::coroutine_handle<promise_type> coroutine) noexcept
{
if (coroutine.promise()._continuation)
{
return coroutine.promise()._continuation;
}
return std::noop_coroutine();
return coroutine.promise()._continuation;
}
void await_resume() noexcept {}
};
return awaitable {};
return awaitable { !_continuation };
}
};
auto operator co_await() const&& noexcept
auto operator co_await() && noexcept
{
struct awaitable
{
std::coroutine_handle<promise_type> _coroutine;
result<T> * _result;
bool _destroy;
bool await_ready() noexcept
{
return _coroutine.done();
if (_result->ready())
{
return true;
}
_destroy = true;
return false;
}
std::coroutine_handle<> await_suspend(std::coroutine_handle<> awaiting_coroutine) noexcept
......@@ -72,16 +85,20 @@ namespace typon
decltype(auto) await_resume()
{
return _coroutine.promise().get();
if (_destroy)
{
_coroutine.destroy();
}
return _result->get();
}
};
return awaitable { _coroutine };
return awaitable { _coroutine, std::addressof(_result), false };
}
decltype(auto) call() const&&
decltype(auto) call() &&
{
return _coroutine.promise().get();
return _result.get();
}
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment