LeechCraft  0.6.70-16373-g319c272718
Modular cross-platform feature rich live environment.
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 
16 namespace LC::Util
17 {
18  namespace detail
19  {
20  template<typename R>
21  struct PromiseRet
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 
44  {
45  Done_ = true;
46  }
47  };
48 
49  struct EitherFailureAbort : std::exception {};
50 
51  template<typename Promise>
52  struct TaskAwaiter
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 
118  {
119  ([this]
120  {
121  using Base = Extensions<promise_type>;
122  if constexpr (requires (Base t) { t.FinalSuspend (); })
123  Base::FinalSuspend ();
124  } (), ...);
125  return detail::FinalSuspender<promise_type> { *this };
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 
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 
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>
197  struct GetPromise
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 }
bool await_suspend(std::coroutine_handle< Promise > handle) const noexcept
Definition: task.h:204
~Task() noexcept
Definition: task.h:157
decltype(auto) await_resume() const noexcept
Definition: task.h:210
void swap(FDGuard &g1, FDGuard &g2)
Definition: fdguard.cpp:51
Task(const std::coroutine_handle< promise_type > &handle)
Definition: task.h:150
void return_void() noexcept
Definition: task.h:43
Task & operator=(const Task &other)
Definition: task.h:170
std::coroutine_handle< Promise > Handle_t
Definition: task.h:54
auto final_suspend() noexcept
Definition: task.h:117
std::optional< R > Ret_
Definition: task.h:27
Task(const Task &other)
Definition: task.h:163
Task(Task &&other) noexcept
Definition: task.h:177
std::exception_ptr Exception_
Definition: task.h:106
QVector< std::coroutine_handle<> > WaitingHandles_
Definition: task.h:105
requires(Tup1Size==Tup2Size) const expr auto ZipWith(Tup1 &&tup1
bool await_ready() const noexcept
Definition: task.h:57
auto await_resume() const
Definition: task.h:74
void return_value(U &&val)
Definition: task.h:30
void await_suspend(std::coroutine_handle<> handle)
Definition: task.h:69
R ResultType_t
Definition: task.h:145
static constexpr bool IsVoid
Definition: task.h:25
auto Tup2 &&tup2 noexcept
Definition: ctstringutils.h:41
bool await_ready() const noexcept
Definition: task.h:202
typename Task< R, Extensions... >::promise_type Promise
Definition: task.h:199
std::suspend_never initial_suspend() const noexcept
Definition: task.h:115