LeechCraft 0.6.70-17609-g3dde4097dd
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 <exception>
13#include <utility>
14#include <QVector>
15#include "finalsuspender.h"
16#include "taskfwd.h"
17
18namespace LC::Util
19{
20 namespace detail
21 {
22 template<typename R>
24 {
25 using ReturnType_t = R;
26
27 constexpr static bool IsVoid = false;
28
29 std::optional<R> Ret_;
30
31 template<typename U = R>
32 void return_value (U&& val)
33 {
34 Ret_.emplace (std::forward<U> (val));
35 }
36 };
37
38 template<>
39 struct PromiseRet<void>
40 {
41 constexpr static bool IsVoid = true;
42
43 bool Done_ = false;
44
45 void return_void () noexcept
46 {
47 Done_ = true;
48 }
49 };
50
51 struct EitherFailureAbort final : std::exception {};
52
53 template<typename Promise>
55 {
56 using Handle_t = std::coroutine_handle<Promise>;
58
59 bool await_ready () const noexcept
60 {
61 const auto& promise = Handle_.promise ();
62 if (promise.Exception_)
63 return true;
64
65 if constexpr (Promise::IsVoid)
66 return promise.Done_;
67 else
68 return static_cast<bool> (promise.Ret_);
69 }
70
71 void await_suspend (std::coroutine_handle<> handle)
72 {
73 Handle_.promise ().WaitingHandles_.push_back (handle);
74 }
75
76 auto await_resume () const
77 {
78 const auto& promise = Handle_.promise ();
79 if (promise.Exception_)
80 try
81 {
82 std::rethrow_exception (promise.Exception_);
83 }
84 catch (const EitherFailureAbort&)
85 {
86 }
87
88 if constexpr (!Promise::IsVoid)
89 return *promise.Ret_;
90 }
91 };
92 }
93
94 template<typename R, template<typename> typename... Extensions>
95 class Task
96 {
97 public:
98 struct promise_type;
99 private:
100 using Handle_t = std::coroutine_handle<promise_type>;
101 Handle_t Handle_;
102 public:
104 , Extensions<promise_type>...
105 {
106 size_t Refs_ = 1; // TODO make thread-safe
107 QVector<std::coroutine_handle<>> WaitingHandles_ {};
108 std::exception_ptr Exception_ {};
109
110 auto GetAddress () { return Handle_t::from_promise (*this).address (); }
111
113 {
114 return Task { Handle_t::from_promise (*this) };
115 }
116
117 std::suspend_never initial_suspend () const noexcept { return {}; }
118
119 auto final_suspend () noexcept
120 {
121 ([this]
122 {
123 using Base = Extensions<promise_type>;
124 if constexpr (requires (Base t) { t.FinalSuspend (); })
125 Base::FinalSuspend ();
126 } (), ...);
128 }
129
131 {
132 Exception_ = std::current_exception ();
133 }
134
135 void IncRef ()
136 {
137 ++Refs_;
138 }
139
140 void DecRef ()
141 {
142 if (!--Refs_)
143 Handle_t::from_promise (*this).destroy ();
144 }
145 };
146
147 using ResultType_t = R;
148
149 template<typename RR>
150 using ReplaceResult_t = Task<RR, Extensions...>;
151
152 explicit Task (const std::coroutine_handle<promise_type>& handle)
153 : Handle_ { handle }
154 {
155 if (handle)
156 handle.promise ().IncRef ();
157 }
158
159 ~Task () noexcept
160 {
161 if (Handle_)
162 Handle_.promise ().DecRef ();
163 }
164
165 Task (const Task& other)
166 : Handle_ { other.Handle_ }
167 {
168 if (Handle_)
169 Handle_.promise ().IncRef ();
170 }
171
172 Task& operator= (const Task& other)
173 {
174 Task task { other };
175 *this = std::move (task);
176 return *this;
177 }
178
179 Task (Task&& other) noexcept
180 {
181 std::swap (Handle_, other.Handle_);
182 }
183
184 Task& operator= (Task&& other) noexcept
185 {
186 std::swap (Handle_, other.Handle_);
187 return *this;
188 }
189
190 auto operator co_await () const noexcept
191 {
192 return detail::TaskAwaiter<promise_type> { Handle_ };
193 }
194 };
195
196 namespace detail
197 {
198 template<typename R, template<typename> typename... Extensions>
200 {
201 using Promise = typename Task<R, Extensions...>::promise_type;
202 Promise *Promise_ = nullptr;
203
204 bool await_ready () const noexcept { return false; }
205
206 bool await_suspend (std::coroutine_handle<Promise> handle) const noexcept
207 {
208 Promise_ = &handle.promise ();
209 return false;
210 }
211
212 decltype (auto) await_resume () const noexcept
213 {
214 return *Promise_;
215 }
216 };
217 }
218}
Task & operator=(const Task &other)
Definition task.h:172
Task(Task &&other) noexcept
Definition task.h:179
~Task() noexcept
Definition task.h:159
Task< RR, Extensions... > ReplaceResult_t
Definition task.h:150
Task(const Task &other)
Definition task.h:165
Task(const std::coroutine_handle< promise_type > &handle)
Definition task.h:152
std::suspend_never initial_suspend() const noexcept
Definition task.h:117
auto final_suspend() noexcept
Definition task.h:119
QVector< std::coroutine_handle<> > WaitingHandles_
Definition task.h:107
std::exception_ptr Exception_
Definition task.h:108
bool await_ready() const noexcept
Definition task.h:204
decltype(auto) await_resume() const noexcept
Definition task.h:212
bool await_suspend(std::coroutine_handle< Promise > handle) const noexcept
Definition task.h:206
typename Task< R, Extensions... >::promise_type Promise
Definition task.h:201
static constexpr bool IsVoid
Definition task.h:41
std::optional< R > Ret_
Definition task.h:29
static constexpr bool IsVoid
Definition task.h:27
void return_value(U &&val)
Definition task.h:32
bool await_ready() const noexcept
Definition task.h:59
std::coroutine_handle< Promise > Handle_t
Definition task.h:56
void await_suspend(std::coroutine_handle<> handle)
Definition task.h:71
auto await_resume() const
Definition task.h:76