2#include <asyncpp/detail/promise_allocator_base.h>
9 template<
class T, ByteAllocator Allocator>
13 template<
class TVal, ByteAllocator Allocator,
class TPromise>
14 class task_promise_base :
public promise_allocator_base<Allocator> {
16 task_promise_base() noexcept = default;
17 ~task_promise_base() = default;
18 task_promise_base(const task_promise_base&) = delete;
19 task_promise_base(task_promise_base&&) = delete;
20 task_promise_base& operator=(const task_promise_base&) = delete;
21 task_promise_base& operator=(task_promise_base&&) = delete;
23 coroutine_handle<TPromise> get_return_object() noexcept {
24 return coroutine_handle<TPromise>::from_promise(*
static_cast<TPromise*
>(
this));
27 suspend_always initial_suspend() {
return {}; }
28 auto final_suspend() noexcept {
30 constexpr bool await_ready() noexcept {
return false; }
31 auto await_suspend(coroutine_handle<TPromise> hndl)
noexcept {
33 assert(hndl.promise().m_continuation);
34 return hndl.promise().m_continuation;
36 constexpr void await_resume() noexcept {}
41 void unhandled_exception() noexcept {
42 m_value.template emplace<std::exception_ptr>(std::current_exception());
45 TVal rethrow_if_exception() {
46 if (std::holds_alternative<std::exception_ptr>(m_value))
47 std::rethrow_exception(std::get<std::exception_ptr>(m_value));
48 return std::get<TVal>(std::move(this->m_value));
51 coroutine_handle<> m_continuation{};
52 std::variant<std::monostate, TVal, std::exception_ptr> m_value{};
55 template<
class T, ByteAllocator Allocator>
56 class task_promise :
public task_promise_base<T, Allocator, task_promise<T, Allocator>> {
59 void return_value(U&& value)
60 requires(std::is_convertible_v<U, T>)
62 this->m_value.template emplace<T>(std::forward<U>(value));
65 void return_value(U
const& value)
66 requires(!std::is_reference_v<U>)
68 this->m_value.template emplace<T>(value);
70 T get() {
return this->rethrow_if_exception(); }
74 template<ByteAllocator Allocator>
75 class task_promise<void, Allocator>
76 :
public task_promise_base<returned, Allocator, task_promise<void, Allocator>> {
78 void return_void() { this->m_value.template emplace<returned>(); }
79 void get() { this->rethrow_if_exception(); }
87 template<
class T =
void, ByteAllocator Allocator = default_allocator_type>
93 using handle_t = coroutine_handle<promise_type>;
99 assert(!this->m_coro.done());
103 explicit task(std::nullptr_t) noexcept : m_coro{} {}
106 task(
task&& other) noexcept : m_coro{std::exchange(other.m_coro, {})} {}
109 m_coro = std::exchange(other.m_coro, m_coro);
113 task& operator=(
const task&) =
delete;
117 if (m_coro) m_coro.destroy();
122 explicit operator bool() const noexcept {
return m_coro !=
nullptr; }
124 bool operator!() const noexcept {
return m_coro ==
nullptr; }
127 auto operator co_await()
noexcept {
129 constexpr explicit awaiter(
handle_t coro) : m_coro(coro) {}
130 constexpr bool await_ready()
noexcept {
return false; }
131 auto await_suspend(coroutine_handle<void> hndl)
noexcept {
132 assert(this->m_coro);
134 m_coro.promise().m_continuation = hndl;
138 assert(this->m_coro);
139 return this->m_coro.promise().get();
145 assert(this->m_coro);
146 return awaiter{m_coro};
Generic task type.
Definition task.h:88
~task()
Destructor.
Definition task.h:116
task(std::nullptr_t) noexcept
Construct from nullptr. The resulting task is invalid.
Definition task.h:103
task(task &&other) noexcept
Move constructor.
Definition task.h:106
detail::task_promise< T, Allocator > promise_type
Promise type.
Definition task.h:91
coroutine_handle< promise_type > handle_t
Handle type.
Definition task.h:93
bool operator!() const noexcept
Check if the task does not hold a valid coroutine.
Definition task.h:124
task & operator=(task &&other) noexcept
Move assignment.
Definition task.h:108
task(handle_t hndl) noexcept
Construct from handle.
Definition task.h:97
Provides a consistent import interface for coroutine, experimental/coroutine or a best effort fallbac...