LeechCraft 0.6.70-16373-g319c272718
Modular cross-platform feature rich live environment.
Loading...
Searching...
No Matches
task.h
Go to the documentation of this file.
1/**********************************************************************
2 * LeechCraft - modular cross-platform feature rich internet client.
3 * Copyright (C) 2006-2014 Georg Rudoy
4 *
5 * Distributed under the Boost Software License, Version 1.0.
6 * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7 **********************************************************************/
8
9#pragma once
10
11#include <coroutine>
12#include <utility>
13#include "finalsuspender.h"
14#include "taskfwd.h"
15
16namespace LC::Util
17{
18 namespace detail
19 {
20 template<typename R>
22 {
23 using ReturnType_t = R;
24
25 constexpr static bool IsVoid = false;
26
27 std::optional<R> Ret_;
28
29 template<typename U>
30 void return_value (U&& val)
31 {
32 Ret_.emplace (std::forward<U> (val));
33 }
34 };
35
36 template<>
37 struct PromiseRet<void>
38 {
39 constexpr static bool IsVoid = true;
40
41 bool Done_ = false;
42
43 void return_void () noexcept
44 {
45 Done_ = true;
46 }
47 };
48
49 struct EitherFailureAbort : std::exception {};
50
51 template<typename Promise>
53 {
54 using Handle_t = std::coroutine_handle<Promise>;
56
57 bool await_ready () const noexcept
58 {
59 const auto& promise = Handle_.promise ();
60 if (promise.Exception_)
61 return true;
62
63 if constexpr (Promise::IsVoid)
64 return promise.Done_;
65 else
66 return static_cast<bool> (promise.Ret_);
67 }
68
69 void await_suspend (std::coroutine_handle<> handle)
70 {
71 Handle_.promise ().WaitingHandles_.push_back (handle);
72 }
73
74 auto await_resume () const
75 {
76 const auto& promise = Handle_.promise ();
77 if (promise.Exception_)
78 try
79 {
80 std::rethrow_exception (promise.Exception_);
81 }
82 catch (EitherFailureAbort)
83 {
84 }
85
86 if constexpr (!Promise::IsVoid)
87 return *promise.Ret_;
88 }
89 };
90 }
91
92 template<typename R, template<typename> typename... Extensions>
93 class Task
94 {
95 public:
96 struct promise_type;
97 private:
98 using Handle_t = std::coroutine_handle<promise_type>;
99 Handle_t Handle_;
100 public:
102 , Extensions<promise_type>...
103 {
104 size_t Refs_ = 1; // TODO make thread-safe
105 QVector<std::coroutine_handle<>> WaitingHandles_ {};
106 std::exception_ptr Exception_ {};
107
108 auto GetAddress () { return Handle_t::from_promise (*this).address (); }
109
111 {
112 return Task { Handle_t::from_promise (*this) };
113 }
114
115 std::suspend_never initial_suspend () const noexcept { return {}; }
116
117 auto final_suspend () noexcept
118 {
119 ([this]
120 {
121 using Base = Extensions<promise_type>;
122 if constexpr (requires (Base t) { t.FinalSuspend (); })
123 Base::FinalSuspend ();
124 } (), ...);
126 }
127
129 {
130 Exception_ = std::current_exception ();
131 }
132
133 void IncRef ()
134 {
135 ++Refs_;
136 }
137
138 void DecRef ()
139 {
140 if (!--Refs_)
141 Handle_t::from_promise (*this).destroy ();
142 }
143 };
144
145 using ResultType_t = R;
146
147 template<typename RR>
148 using ReplaceResult_t = Task<RR, Extensions...>;
149
150 explicit Task (const std::coroutine_handle<promise_type>& handle)
151 : Handle_ { handle }
152 {
153 if (handle)
154 handle.promise ().IncRef ();
155 }
156
157 ~Task () noexcept
158 {
159 if (Handle_)
160 Handle_.promise ().DecRef ();
161 }
162
163 Task (const Task& other)
164 : Handle_ { other.Handle_ }
165 {
166 if (Handle_)
167 Handle_.promise ().IncRef ();
168 }
169
170 Task& operator= (const Task& other)
171 {
172 Task task { other };
173 *this = std::move (task);
174 return *this;
175 }
176
177 Task (Task&& other) noexcept
178 {
179 std::swap (Handle_, other.Handle_);
180 }
181
182 Task& operator= (Task&& other) noexcept
183 {
184 std::swap (Handle_, other.Handle_);
185 return *this;
186 }
187
188 auto operator co_await () const noexcept
189 {
190 return detail::TaskAwaiter<promise_type> { Handle_ };
191 }
192 };
193
194 namespace detail
195 {
196 template<typename R, template<typename> typename... Extensions>
198 {
199 using Promise = typename Task<R, Extensions...>::promise_type;
200 Promise *Promise_ = nullptr;
201
202 bool await_ready () const noexcept { return false; }
203
204 bool await_suspend (std::coroutine_handle<Promise> handle) const noexcept
205 {
206 Promise_ = &handle.promise ();
207 return false;
208 }
209
210 decltype (auto) await_resume () const noexcept
211 {
212 return *Promise_;
213 }
214 };
215 }
216}
Task & operator=(const Task &other)
Definition task.h:170
Task(Task &&other) noexcept
Definition task.h:177
~Task() noexcept
Definition task.h:157
Task< RR, Extensions... > ReplaceResult_t
Definition task.h:148
Task(const Task &other)
Definition task.h:163
Task(const std::coroutine_handle< promise_type > &handle)
Definition task.h:150
std::suspend_never initial_suspend() const noexcept
Definition task.h:115
auto final_suspend() noexcept
Definition task.h:117
QVector< std::coroutine_handle<> > WaitingHandles_
Definition task.h:105
std::exception_ptr Exception_
Definition task.h:106
bool await_ready() const noexcept
Definition task.h:202
decltype(auto) await_resume() const noexcept
Definition task.h:210
bool await_suspend(std::coroutine_handle< Promise > handle) const noexcept
Definition task.h:204
typename Task< R, Extensions... >::promise_type Promise
Definition task.h:199
std::optional< R > Ret_
Definition task.h:27
static constexpr bool IsVoid
Definition task.h:39
static constexpr bool IsVoid
Definition task.h:25
void return_value(U &&val)
Definition task.h:30
bool await_ready() const noexcept
Definition task.h:57
std::coroutine_handle< Promise > Handle_t
Definition task.h:54
void await_suspend(std::coroutine_handle<> handle)
Definition task.h:69
auto await_resume() const
Definition task.h:74