1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QFUTURE_H
41#define QFUTURE_H
42
43#include <QtCore/qglobal.h>
44
45#include <QtCore/qfutureinterface.h>
46#include <QtCore/qstring.h>
47
48#include <QtCore/qfuture_impl.h>
49
50#include <type_traits>
51#include <vector>
52
53QT_REQUIRE_CONFIG(future);
54
55QT_BEGIN_NAMESPACE
56
57template <typename T>
58class QFutureWatcher;
59
60template <typename T>
61class QFuture
62{
63 static_assert (std::is_copy_constructible_v<T>
64 || std::is_move_constructible_v<T>
65 || std::is_same_v<T, void>,
66 "Type with copy or move constructors or type void is required");
67public:
68 QFuture()
69 : d(QFutureInterface<T>::canceledResult())
70 { }
71
72 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
73 explicit QFuture(QFutureInterface<T> *p) // internal
74 : d(*p)
75 { }
76
77 template<typename U = T, typename = QtPrivate::EnableForVoid<U>>
78 explicit QFuture(QFutureInterfaceBase *p) // internal
79 : d(*p)
80 {
81 }
82
83 template<typename U, typename V = T, typename = QtPrivate::EnableForVoid<V>>
84 QFuture(const QFuture<U> &other) : d(other.d)
85 {
86 }
87
88 template<typename U, typename V = T, typename = QtPrivate::EnableForVoid<V>>
89 QFuture<void> &operator=(const QFuture<U> &other)
90 {
91 d = other.d;
92 return *this;
93 }
94
95#if defined(Q_CLANG_QDOC)
96 ~QFuture() { }
97 QFuture(const QFuture<T> &) { }
98 QFuture<T> & operator=(const QFuture<T> &) { }
99
100 // This is required to allow QDoc to find the declaration of operator T().
101 operator T() const;
102#endif
103
104 bool operator==(const QFuture &other) const { return (d == other.d); }
105 bool operator!=(const QFuture &other) const { return (d != other.d); }
106
107 void cancel() { d.cancel(); }
108 bool isCanceled() const { return d.isCanceled(); }
109
110#if QT_DEPRECATED_SINCE(6, 0)
111 QT_DEPRECATED_VERSION_X_6_0("Use setSuspended() instead.")
112 void setPaused(bool paused) { d.setSuspended(paused); }
113
114 QT_DEPRECATED_VERSION_X_6_0("Use isSuspending() or isSuspended() instead.")
115 bool isPaused() const
116 {
117QT_WARNING_PUSH
118QT_WARNING_DISABLE_DEPRECATED
119 return d.isPaused();
120QT_WARNING_POP
121 }
122
123 QT_DEPRECATED_VERSION_X_6_0("Use toggleSuspended() instead.")
124 void togglePaused() { d.toggleSuspended(); }
125
126 QT_DEPRECATED_VERSION_X_6_0("Use suspend() instead.")
127 void pause() { suspend(); }
128#endif
129 bool isSuspending() const { return d.isSuspending(); }
130 bool isSuspended() const { return d.isSuspended(); }
131 void setSuspended(bool suspend) { d.setSuspended(suspend); }
132 void suspend() { setSuspended(true); }
133 void resume() { setSuspended(false); }
134 void toggleSuspended() { d.toggleSuspended(); }
135
136 bool isStarted() const { return d.isStarted(); }
137 bool isFinished() const { return d.isFinished(); }
138 bool isRunning() const { return d.isRunning(); }
139
140 int resultCount() const { return d.resultCount(); }
141 int progressValue() const { return d.progressValue(); }
142 int progressMinimum() const { return d.progressMinimum(); }
143 int progressMaximum() const { return d.progressMaximum(); }
144 QString progressText() const { return d.progressText(); }
145 void waitForFinished() { d.waitForFinished(); }
146
147 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
148 inline T result() const;
149
150 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
151 inline T resultAt(int index) const;
152
153 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
154 bool isResultReadyAt(int resultIndex) const { return d.isResultReadyAt(resultIndex); }
155
156 // operator T()
157 template<typename U = T>
158 operator typename std::enable_if_t<!std::is_same_v<U, void>, U>() const { return result(); }
159
160 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
161 QList<T> results() const { return d.results(); }
162
163 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
164 T takeResult() { return d.takeResult(); }
165
166#if 0
167 // TODO: Enable and make it return a QList, when QList is fixed to support move-only types
168 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
169 std::vector<T> takeResults() { return d.takeResults(); }
170#endif
171
172 bool isValid() const { return d.isValid(); }
173
174 template<class Function>
175 using ResultType = typename QtPrivate::ResultTypeHelper<Function, T>::ResultType;
176
177 template<class Function>
178 QFuture<ResultType<Function>> then(Function &&function);
179
180 template<class Function>
181 QFuture<ResultType<Function>> then(QtFuture::Launch policy, Function &&function);
182
183 template<class Function>
184 QFuture<ResultType<Function>> then(QThreadPool *pool, Function &&function);
185
186#ifndef QT_NO_EXCEPTIONS
187 template<class Function,
188 typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>>
189 QFuture<T> onFailed(Function &&handler);
190#endif
191
192 template<class Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>>
193 QFuture<T> onCanceled(Function &&handler);
194
195 class const_iterator
196 {
197 public:
198 static_assert(!std::is_same_v<T, void>,
199 "It isn't possible to define QFuture<void>::const_iterator");
200
201 typedef std::bidirectional_iterator_tag iterator_category;
202 typedef qptrdiff difference_type;
203 typedef T value_type;
204 typedef const T *pointer;
205 typedef const T &reference;
206
207 inline const_iterator() {}
208 inline const_iterator(QFuture const * const _future, int _index)
209 : future(_future), index(advanceIndex(_index, 0)) { }
210 inline const_iterator(const const_iterator &o) : future(o.future), index(o.index) {}
211 inline const_iterator &operator=(const const_iterator &o)
212 { future = o.future; index = o.index; return *this; }
213 inline const T &operator*() const { return future->d.resultReference(index); }
214 inline const T *operator->() const { return future->d.resultPointer(index); }
215 inline bool operator!=(const const_iterator &other) const { return index != other.index; }
216 inline bool operator==(const const_iterator &o) const { return !operator!=(o); }
217 inline const_iterator &operator++()
218 { index = advanceIndex(index, 1); return *this; }
219 inline const_iterator &operator--()
220 { index = advanceIndex(index, -1); return *this; }
221 inline const_iterator operator++(int)
222 {
223 const_iterator r = *this;
224 index = advanceIndex(index, 1);
225 return r;
226 }
227 inline const_iterator operator--(int)
228 {
229 const_iterator r = *this;
230 index = advanceIndex(index, -1);
231 return r;
232 }
233 inline const_iterator operator+(int j) const
234 { return const_iterator(future, advanceIndex(index, j)); }
235 inline const_iterator operator-(int j) const
236 { return const_iterator(future, advanceIndex(index, -j)); }
237 inline const_iterator &operator+=(int j)
238 { index = advanceIndex(index, j); return *this; }
239 inline const_iterator &operator-=(int j)
240 { index = advanceIndex(index, -j); return *this; }
241 friend inline const_iterator operator+(int j, const_iterator k)
242 { return const_iterator(k.future, k.advanceIndex(k.index, j)); }
243
244 private:
245 /*! \internal
246
247 Advances the iterator index \a idx \a n steps, waits for the
248 result at the target index, and returns the target index.
249
250 The index may be -1, indicating the end iterator, either
251 as the argument or as the return value. The end iterator
252 may be decremented.
253
254 The caller is responsible for not advancing the iterator
255 before begin() or past end(), with the exception that
256 attempting to advance a non-end iterator past end() for
257 a running future is allowed and will return the end iterator.
258
259 Note that n == 0 is valid and will wait for the result
260 at the given index.
261 */
262 int advanceIndex(int idx, int n) const
263 {
264 // The end iterator can be decremented, leave as-is for other cases
265 if (idx == -1 && n >= 0)
266 return idx;
267
268 // Special case for decrementing the end iterator: wait for
269 // finished to get the total result count.
270 if (idx == -1 && future->isRunning())
271 future->d.waitForFinished();
272
273 // Wait for result at target index
274 const int targetIndex = (idx == -1) ? future->resultCount() + n : idx + n;
275 future->d.waitForResult(targetIndex);
276
277 // After waiting there is either a result or the end was reached
278 return (targetIndex < future->resultCount()) ? targetIndex : -1;
279 }
280
281 QFuture const * future;
282 int index;
283 };
284 friend class const_iterator;
285 typedef const_iterator ConstIterator;
286
287 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
288 const_iterator begin() const { return const_iterator(this, 0); }
289
290 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
291 const_iterator constBegin() const { return const_iterator(this, 0); }
292
293 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
294 const_iterator end() const { return const_iterator(this, -1); }
295
296 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
297 const_iterator constEnd() const { return const_iterator(this, -1); }
298
299private:
300 friend class QFutureWatcher<T>;
301
302 template<class U>
303 friend class QFuture;
304
305 template<class Function, class ResultType, class ParentResultType>
306 friend class QtPrivate::Continuation;
307
308 template<class Function, class ResultType>
309 friend class QtPrivate::CanceledHandler;
310
311#ifndef QT_NO_EXCEPTIONS
312 template<class Function, class ResultType>
313 friend class QtPrivate::FailureHandler;
314#endif
315
316 using QFuturePrivate =
317 std::conditional_t<std::is_same_v<T, void>, QFutureInterfaceBase, QFutureInterface<T>>;
318
319#ifdef QFUTURE_TEST
320public:
321#endif
322 mutable QFuturePrivate d;
323};
324
325template<typename T>
326template<typename U, typename>
327inline T QFuture<T>::result() const
328{
329 d.waitForResult(0);
330 return d.resultReference(0);
331}
332
333template<typename T>
334template<typename U, typename>
335inline T QFuture<T>::resultAt(int index) const
336{
337 d.waitForResult(index);
338 return d.resultReference(index);
339}
340
341template <typename T>
342inline QFuture<T> QFutureInterface<T>::future()
343{
344 return QFuture<T>(this);
345}
346
347template<class T>
348template<class Function>
349QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(Function &&function)
350{
351 return then(QtFuture::Launch::Sync, std::forward<Function>(function));
352}
353
354template<class T>
355template<class Function>
356QFuture<typename QFuture<T>::template ResultType<Function>>
357QFuture<T>::then(QtFuture::Launch policy, Function &&function)
358{
359 QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
360 QtPrivate::Continuation<Function, ResultType<Function>, T>::create(
361 std::forward<Function>(function), this, promise, policy);
362 return promise.future();
363}
364
365template<class T>
366template<class Function>
367QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QThreadPool *pool,
368 Function &&function)
369{
370 QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
371 QtPrivate::Continuation<Function, ResultType<Function>, T>::create(
372 std::forward<Function>(function), this, promise, pool);
373 return promise.future();
374}
375
376#ifndef QT_NO_EXCEPTIONS
377
378template<class T>
379template<class Function, typename>
380QFuture<T> QFuture<T>::onFailed(Function &&handler)
381{
382 QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
383 QtPrivate::FailureHandler<Function, T>::create(std::forward<Function>(handler), this, promise);
384 return promise.future();
385}
386
387#endif
388
389template<class T>
390template<class Function, typename>
391QFuture<T> QFuture<T>::onCanceled(Function &&handler)
392{
393 QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
394 QtPrivate::CanceledHandler<Function, T>::create(std::forward<Function>(handler), this, promise);
395 return promise.future();
396}
397
398inline QFuture<void> QFutureInterface<void>::future()
399{
400 return QFuture<void>(this);
401}
402
403template <typename T>
404QFuture<void> qToVoidFuture(const QFuture<T> &future)
405{
406 return QFuture<void>(future.d);
407}
408
409Q_DECLARE_SEQUENTIAL_ITERATOR(Future)
410
411QT_END_NAMESPACE
412
413#endif // QFUTURE_H
414