Commit fbbff11a authored by Xavier Thompson's avatar Xavier Thompson

Improve future.hpp

parent bc8e0170
...@@ -102,7 +102,7 @@ namespace typon ...@@ -102,7 +102,7 @@ namespace typon
{ {
continuation.children().insert(_coroutine); continuation.children().insert(_coroutine);
} }
return Future<promise_type>(_coroutine, !stolen); return Future<T>(_coroutine, !stolen);
} }
}; };
......
...@@ -14,50 +14,50 @@ ...@@ -14,50 +14,50 @@
namespace typon namespace typon
{ {
template <typename Promise> template <typename T>
struct Future struct Future
{ {
using value_type = typename Promise::value_type; using value_type = T;
std::coroutine_handle<Promise> _coroutine; Result<T> * _result = nullptr;
union union
{ {
value_type _result; T _value;
}; };
template <typename Promise>
Future(std::coroutine_handle<Promise> coroutine, bool ready) Future(std::coroutine_handle<Promise> coroutine, bool ready)
{ {
if (ready) if (ready)
{ {
fdt::defer defer { [&coroutine]() { coroutine.destroy(); } }; fdt::defer defer { [&coroutine]() { coroutine.destroy(); } };
std::construct_at(std::addressof(_result), coroutine.promise().get()); std::construct_at(std::addressof(_value), coroutine.promise().get());
} }
else else
{ {
_coroutine = coroutine; _result = &(coroutine.promise());
} }
} }
Future(Future && other) Future(Future && other) noexcept(std::is_nothrow_move_constructible_v<T>)
noexcept(std::is_nothrow_move_constructible_v<value_type>)
{ {
_coroutine = other._coroutine; _result = other._result;
if (!_coroutine) if (!_result)
{ {
std::construct_at(std::addressof(_result), std::move(other._result)); std::construct_at(std::addressof(_value), std::move(other._value));
} }
} }
Future& operator=(Future && other) Future& operator=(Future && other)
noexcept(std::is_nothrow_move_constructible_v<value_type>) noexcept(std::is_nothrow_move_constructible_v<T>)
{ {
if (this != &other) if (this != &other)
{ {
Future old { std::move(*this) }; Future old { std::move(*this) };
_coroutine = other._coroutine; _result = other._result;
if (!_coroutine) if (!_result)
{ {
std::construct_at(std::addressof(_result), std::move(other._result)); std::construct_at(std::addressof(_value), std::move(other._value));
} }
} }
return *this; return *this;
...@@ -65,37 +65,39 @@ namespace typon ...@@ -65,37 +65,39 @@ namespace typon
~Future() ~Future()
{ {
if (!_coroutine) if (!_result)
{ {
std::destroy_at(std::addressof(_result)); std::destroy_at(std::addressof(_value));
} }
} }
auto get() T get()
{ {
if (_coroutine) if (_result)
{ {
return _coroutine.promise().get(); return _result->get();
} }
return _result; return _value;
} }
}; };
template <typename Promise> template <typename T>
requires requires { sizeof(typename Promise::value_type); } requires requires { sizeof(T); } && (sizeof(T) > 2 * sizeof(void*))
&& (sizeof(typename Promise::value_type) > 2 * sizeof(void*)) struct Future<T>
struct Future<Promise>
{ {
std::coroutine_handle<Promise> _coroutine; using value_type = T;
bool _owning;
Result<T> * _result = nullptr;
std::coroutine_handle<> _coroutine;
template <typename Promise>
Future(std::coroutine_handle<Promise> coroutine, bool ready) Future(std::coroutine_handle<Promise> coroutine, bool ready)
{ {
_coroutine = coroutine; _result = &(coroutine.promise());
_owning = ready;
if (ready) if (ready)
{ {
_coroutine = coroutine;
if (coroutine.promise()._exception) if (coroutine.promise()._exception)
{ {
std::rethrow_exception(coroutine.promise()._exception); std::rethrow_exception(coroutine.promise()._exception);
...@@ -107,54 +109,55 @@ namespace typon ...@@ -107,54 +109,55 @@ namespace typon
Future& operator=(const Future &) = delete; Future& operator=(const Future &) = delete;
Future(Future && other) noexcept Future(Future && other) noexcept
: _coroutine(other._coroutine) : _result(other._result)
, _owning(std::exchange(other._owning, false)) , _coroutine(std::exchange(other._coroutine, nullptr))
{} {}
Future& operator=(Future && other) noexcept Future& operator=(Future && other) noexcept
{ {
std::swap(_owning, other._owning);
std::swap(_coroutine, other._coroutine); std::swap(_coroutine, other._coroutine);
std::swap(_result, other._result);
return *this; return *this;
} }
~Future() ~Future()
{ {
if (_owning) if (_coroutine)
{ {
_coroutine.destroy(); _coroutine.destroy();
} }
} }
auto get() T get()
{ {
return _coroutine.promise().get(); return _result->get();
} }
}; };
template <typename Promise> template <typename T>
requires std::is_trivially_copyable_v<typename Promise::value_type> requires std::is_trivially_copyable_v<T>
struct Future<Promise> struct Future<T>
{ {
using value_type = typename Promise::value_type; using value_type = T;
std::coroutine_handle<Promise> _coroutine; Result<T> * _result = nullptr;
union union
{ {
value_type _result; value_type _value;
}; };
template <typename Promise>
Future(std::coroutine_handle<Promise> coroutine, bool ready) Future(std::coroutine_handle<Promise> coroutine, bool ready)
{ {
if (ready) if (ready)
{ {
fdt::defer defer { [&coroutine]() { coroutine.destroy(); } }; fdt::defer defer { [&coroutine]() { coroutine.destroy(); } };
std::construct_at(std::addressof(_result), coroutine.promise().get()); std::construct_at(std::addressof(_value), coroutine.promise().get());
} }
else else
{ {
_coroutine = coroutine; _result = &(coroutine.promise());
} }
} }
...@@ -163,64 +166,64 @@ namespace typon ...@@ -163,64 +166,64 @@ namespace typon
~Future() ~Future()
{ {
if (!_coroutine) if (!_result)
{ {
std::destroy_at(std::addressof(_result)); std::destroy_at(std::addressof(_value));
} }
} }
auto get() T get()
{ {
if (_coroutine) if (_result)
{ {
return _coroutine.promise().get(); return _result->get();
} }
return _result; return _value;
} }
}; };
template <typename Promise> template <typename T>
requires std::is_reference_v<typename Promise::value_type> struct Future<T&>
struct Future<Promise>
{ {
using value_type = typename Promise::value_type; using value_type = T&;
std::coroutine_handle<Promise> _coroutine; Result<T> * _result = nullptr;
std::remove_reference<value_type> * _result; T * _value;
template <typename Promise>
Future(std::coroutine_handle<Promise> coroutine, bool ready) Future(std::coroutine_handle<Promise> coroutine, bool ready)
{ {
if (ready) if (ready)
{ {
fdt::defer defer { [&coroutine]() { coroutine.destroy(); } }; fdt::defer defer { [&coroutine]() { coroutine.destroy(); } };
_result = std::addressof(coroutine.promise().get()); _value = std::addressof(coroutine.promise().get());
} }
else else
{ {
_coroutine = coroutine; _result = &(coroutine.promise());
} }
} }
value_type get() T& get()
{ {
if (_coroutine) if (_result)
{ {
return _coroutine.promise().get(); return _result->get();
} }
return *_result; return *_value;
} }
}; };
template <typename Promise> template <>
requires std::is_void_v<typename Promise::value_type> struct Future<void>
struct Future<Promise>
{ {
using value_type = typename Promise::value_type; using value_type = void;
std::coroutine_handle<Promise> _coroutine; Result<void> * _result = nullptr;
template <typename Promise>
Future(std::coroutine_handle<Promise> coroutine, bool ready) Future(std::coroutine_handle<Promise> coroutine, bool ready)
{ {
if (ready) if (ready)
...@@ -230,15 +233,15 @@ namespace typon ...@@ -230,15 +233,15 @@ namespace typon
} }
else else
{ {
_coroutine = coroutine; _result = &(coroutine.promise());
} }
} }
void get() void get()
{ {
if (_coroutine) if (_result)
{ {
_coroutine.promise().get(); _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