Commit 522f9cf2 authored by Xavier Thompson's avatar Xavier Thompson

Improve future.hpp

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