9namespace Lightweight::Async
12template <
typename T =
void>
23 struct TaskFinalAwaiter
25 [[nodiscard]]
bool await_ready() const noexcept
30 template <
typename Promise>
31 [[nodiscard]] std::coroutine_handle<> await_suspend(std::coroutine_handle<Promise> coro)
const noexcept
33 return coro.promise().Continuation();
36 void await_resume() const noexcept {}
44 [[nodiscard]] std::suspend_always initial_suspend() noexcept
49 [[nodiscard]] TaskFinalAwaiter final_suspend() noexcept
55 void SetContinuation(std::coroutine_handle<> continuation)
noexcept
57 _continuation = continuation;
61 [[nodiscard]] std::coroutine_handle<> Continuation() const noexcept
63 return _continuation ? _continuation : std::noop_coroutine();
67 std::coroutine_handle<> _continuation {};
83 void SetException() noexcept
85 _result.template emplace<2>(std::current_exception());
89 void SetValue(T
const& value)
91 _result.template emplace<1>(value);
95 void SetValue(T&& value)
noexcept(std::is_nothrow_move_constructible_v<T>)
97 _result.template emplace<1>(std::move(value));
101 [[nodiscard]] T Take()
103 if (_result.index() == 2)
104 std::rethrow_exception(std::get<2>(_result));
105 return std::move(std::get<1>(_result));
109 std::variant<std::monostate, T, std::exception_ptr> _result;
114 class CoroutineResult<void>
118 void SetException() noexcept
120 _exception = std::current_exception();
127 std::rethrow_exception(_exception);
131 std::exception_ptr _exception {};
137 template <
typename T>
138 class TaskPromise final:
public TaskPromiseBase
141 Task<T> get_return_object() noexcept;
143 void unhandled_exception() noexcept
145 _result.SetException();
148 void return_value(T
const& value)
150 _result.SetValue(value);
153 void return_value(T&& value)
noexcept(std::is_nothrow_move_constructible_v<T>)
155 _result.SetValue(std::move(value));
159 [[nodiscard]] T Take()
161 return _result.Take();
165 CoroutineResult<T> _result;
170 class TaskPromise<void> final:
public TaskPromiseBase
173 Task<void> get_return_object() noexcept;
175 void unhandled_exception() noexcept
177 _result.SetException();
180 void return_void() noexcept {}
189 CoroutineResult<void> _result;
212 using Handle = std::coroutine_handle<promise_type>;
227 _handle { std::exchange(other._handle, {}) }
240 _handle = std::exchange(other._handle, {});
246 Task& operator=(
Task const&) =
delete;
257 return static_cast<bool>(_handle);
263 return !_handle || _handle.done();
275 auto operator co_await() &&
noexcept
281 [[nodiscard]]
bool await_ready()
const noexcept
283 return !coro || coro.done();
286 [[nodiscard]] std::coroutine_handle<> await_suspend(std::coroutine_handle<> awaiting)
noexcept
288 coro.promise().SetContinuation(awaiting);
292 decltype(
auto) await_resume()
294 return coro.promise().Take();
297 return Awaiter { _handle };
306 template <
typename T>
307 Task<T> TaskPromise<T>::get_return_object() noexcept
309 return Task<T> { std::coroutine_handle<TaskPromise<T>>::from_promise(*
this) };
312 inline Task<void> TaskPromise<void>::get_return_object() noexcept
314 return Task<void> { std::coroutine_handle<TaskPromise<void>>::from_promise(*
this) };
detail::TaskPromise< T > promise_type
The coroutine promise type required by the C++ coroutine machinery.
Handle GetHandle() const noexcept
bool IsReady() const noexcept
Task() noexcept=default
Constructs an empty Task that owns no coroutine.
bool IsValid() const noexcept
Task & operator=(Task &&other) noexcept
std::coroutine_handle< promise_type > Handle
The typed coroutine handle owned by this Task.
Task(Task &&other) noexcept