34 constexpr static bool IsVoid =
false;
38 template<
typename U = R>
41 std::lock_guard guard { self };
42 self.Ret_.emplace (std::forward<U> (val));
55 std::lock_guard guard { self };
62 template<
typename Promise>
65 using Handle_t = std::coroutine_handle<Promise>;
74 :
Subtask_ { std::exchange (other.Subtask_, {}) }
85 Subtask_.promise ().Continuation_.exchange ({});
90 const auto& promise =
Subtask_.promise ();
91 std::lock_guard guard { promise };
92 return CheckTaskFinishedUnlocked (promise);
98 std::lock_guard guard { promise };
99 if (CheckTaskFinishedUnlocked (promise))
102 if (promise.Continuation_.exchange (handle))
103 qFatal () <<
"subtask has already been awaited on";
109 const auto& promise =
Subtask_.promise ();
110 std::lock_guard guard { promise };
111 if (promise.Exception_)
114 std::rethrow_exception (promise.Exception_);
120 if constexpr (!Promise::IsVoid)
121 return *promise.Ret_;
124 bool CheckTaskFinishedUnlocked (
const Promise& promise)
const
126 if (promise.Exception_)
129 if constexpr (Promise::IsVoid)
130 return promise.Done_;
132 return static_cast<bool> (promise.Ret_);
153 template<
typename R,
template<
typename>
typename... Extensions>
159 using Handle_t = std::coroutine_handle<promise_type>;
163 , Extensions<promise_type>...
167 if constexpr (
requires { this->DoLock (); })
173 if constexpr (
requires { this->DoUnlock (); })
177 auto GetAddress () {
return Handle_t::from_promise (*this).address (); }
181 return Task { Handle_t::from_promise (*
this) };
190 static_cast<void> (
this);
191 using Base = Extensions<promise_type>;
192 if constexpr (
requires (Base t) { t.FinalSuspend (); })
193 Base::FinalSuspend ();
205 this->
Refs_.fetch_add (1);
210 if (this->
Refs_.fetch_sub (1) == 1)
211 Handle_t::from_promise (*this).destroy ();
217 template<
typename RR>
220 template<
template<
typename>
typename F>
223 explicit Task (
const std::coroutine_handle<promise_type>& handle)
227 handle.promise ().IncRef ();
233 Handle_.promise ().DecRef ();
237 : Handle_ { other.Handle_ }
240 Handle_.promise ().IncRef ();
246 *
this = std::move (task);
252 std::swap (Handle_, other.Handle_);
257 std::swap (Handle_, other.Handle_);
261 auto operator co_await ()
const noexcept
269 template<
typename R,
template<
typename>
typename... Extensions>
Task & operator=(const Task &other)
Task(Task &&other) noexcept
Task< F< RR >, Extensions... > ApplyResult_t
Task< RR, Extensions... > ReplaceResult_t
Task(const std::coroutine_handle< promise_type > &handle)
std::suspend_never initial_suspend() const noexcept
auto final_suspend() noexcept
void unhandled_exception()
bool await_ready() const noexcept
decltype(auto) await_resume() const noexcept
bool await_suspend(std::coroutine_handle< Promise > handle) noexcept
typename Task< R, Extensions... >::promise_type Promise
std::exception_ptr Exception_
std::atomic< size_t > Refs_
std::atomic< std::coroutine_handle<> > Continuation_
static constexpr bool IsVoid
void return_void(this auto &&self) noexcept
static constexpr bool IsVoid
void return_value(this auto &&self, U &&val)
bool await_ready() const noexcept
TaskAwaiter(Handle_t subtask)
std::coroutine_handle< Promise > Handle_t
TaskAwaiter & operator=(const TaskAwaiter &)=delete
TaskAwaiter(TaskAwaiter &&other) noexcept
bool await_suspend(std::coroutine_handle<> handle)
TaskAwaiter(const TaskAwaiter &)=delete