1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QFUTURE_H
5#define QFUTURE_H
6
7#include <QtCore/qglobal.h>
8
9#include <QtCore/qfutureinterface.h>
10#include <QtCore/qmetatype.h>
11#include <QtCore/qstring.h>
12
13#include <QtCore/qfuture_impl.h>
14
15#include <type_traits>
16
17QT_REQUIRE_CONFIG(future);
18
19QT_BEGIN_NAMESPACE
20
21template <typename T>
22class QFutureWatcher;
23
24template <typename T>
25class QFuture
26{
27 static_assert (std::is_move_constructible_v<T>
28 || std::is_same_v<T, void>,
29 "A move-constructible type or type void is required");
30public:
31 QFuture()
32 : d(QFutureInterface<T>::canceledResult())
33 { }
34
35 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
36 explicit QFuture(QFutureInterface<T> *p) // internal
37 : d(*p)
38 { }
39
40 template<typename U = T, typename = QtPrivate::EnableForVoid<U>>
41 explicit QFuture(QFutureInterfaceBase *p) // internal
42 : d(*p)
43 {
44 }
45
46 template<typename U, typename V = T, typename = QtPrivate::EnableForVoid<V>>
47 explicit QFuture(const QFuture<U> &other) : d(other.d)
48 {
49 }
50
51 template<typename U, typename V = T, typename = QtPrivate::EnableForVoid<V>>
52 QFuture<void> &operator=(const QFuture<U> &other)
53 {
54 d = other.d;
55 return *this;
56 }
57
58#if defined(Q_QDOC)
59 ~QFuture() { }
60 QFuture(const QFuture<T> &) { }
61 QFuture<T> & operator=(const QFuture<T> &) { }
62#endif
63
64 void cancel() { d.cancel(); }
65 bool isCanceled() const { return d.isCanceled(); }
66
67#if QT_DEPRECATED_SINCE(6, 0)
68 QT_DEPRECATED_VERSION_X_6_0("Use setSuspended() instead.")
69 void setPaused(bool paused) { d.setSuspended(paused); }
70
71 QT_DEPRECATED_VERSION_X_6_0("Use isSuspending() or isSuspended() instead.")
72 bool isPaused() const
73 {
74QT_WARNING_PUSH
75QT_WARNING_DISABLE_DEPRECATED
76 return d.isPaused();
77QT_WARNING_POP
78 }
79
80 QT_DEPRECATED_VERSION_X_6_0("Use toggleSuspended() instead.")
81 void togglePaused() { d.toggleSuspended(); }
82
83 QT_DEPRECATED_VERSION_X_6_0("Use suspend() instead.")
84 void pause() { suspend(); }
85#endif
86 bool isSuspending() const { return d.isSuspending(); }
87 bool isSuspended() const { return d.isSuspended(); }
88 void setSuspended(bool suspend) { d.setSuspended(suspend); }
89 void suspend() { setSuspended(true); }
90 void resume() { setSuspended(false); }
91 void toggleSuspended() { d.toggleSuspended(); }
92
93 bool isStarted() const { return d.isStarted(); }
94 bool isFinished() const { return d.isFinished(); }
95 bool isRunning() const { return d.isRunning(); }
96
97 int resultCount() const { return d.resultCount(); }
98 int progressValue() const { return d.progressValue(); }
99 int progressMinimum() const { return d.progressMinimum(); }
100 int progressMaximum() const { return d.progressMaximum(); }
101 QString progressText() const { return d.progressText(); }
102 void waitForFinished() { d.waitForFinished(); }
103
104 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
105 inline T result() const;
106
107 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
108 inline T resultAt(int index) const;
109
110 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
111 bool isResultReadyAt(int resultIndex) const { return d.isResultReadyAt(resultIndex); }
112
113 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
114 QList<T> results() const { return d.results(); }
115
116 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
117 T takeResult() { return d.takeResult(); }
118
119#if 0
120 // TODO: Enable and make it return a QList, when QList is fixed to support move-only types
121 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
122 std::vector<T> takeResults() { return d.takeResults(); }
123#endif
124
125 bool isValid() const { return d.isValid(); }
126
127 template<class Function>
128 using ResultType = typename QtPrivate::ResultTypeHelper<Function, T>::ResultType;
129
130 template<class Function>
131 QFuture<ResultType<Function>> then(Function &&function);
132
133 template<class Function>
134 QFuture<ResultType<Function>> then(QtFuture::Launch policy, Function &&function);
135
136 template<class Function>
137 QFuture<ResultType<Function>> then(QThreadPool *pool, Function &&function);
138
139 template<class Function>
140 QFuture<ResultType<Function>> then(QObject *context, Function &&function);
141
142#ifndef QT_NO_EXCEPTIONS
143 template<class Function,
144 typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>>
145 QFuture<T> onFailed(Function &&handler);
146
147 template<class Function,
148 typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>>
149 QFuture<T> onFailed(QObject *context, Function &&handler);
150#endif
151
152 template<class Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>>
153 QFuture<T> onCanceled(Function &&handler);
154
155 template<class Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>>
156 QFuture<T> onCanceled(QObject *context, Function &&handler);
157
158#if !defined(Q_QDOC)
159 template<class U = T, typename = std::enable_if_t<QtPrivate::isQFutureV<U>>>
160 auto unwrap();
161#else
162 template<class U>
163 QFuture<U> unwrap();
164#endif
165
166 class const_iterator
167 {
168 public:
169 static_assert(!std::is_same_v<T, void>,
170 "It isn't possible to define QFuture<void>::const_iterator");
171
172 typedef std::bidirectional_iterator_tag iterator_category;
173 typedef qptrdiff difference_type;
174 typedef T value_type;
175 typedef const T *pointer;
176 typedef const T &reference;
177
178 inline const_iterator() {}
179 inline const_iterator(QFuture const * const _future, int _index)
180 : future(_future), index(advanceIndex(idx: _index, n: 0)) { }
181 inline const_iterator(const const_iterator &o) : future(o.future), index(o.index) {}
182 inline const_iterator &operator=(const const_iterator &o)
183 { future = o.future; index = o.index; return *this; }
184 inline const T &operator*() const { return future->d.resultReference(index); }
185 inline const T *operator->() const { return future->d.resultPointer(index); }
186 inline bool operator!=(const const_iterator &other) const { return index != other.index; }
187 inline bool operator==(const const_iterator &o) const { return !operator!=(other: o); }
188 inline const_iterator &operator++()
189 { index = advanceIndex(idx: index, n: 1); return *this; }
190 inline const_iterator &operator--()
191 { index = advanceIndex(idx: index, n: -1); return *this; }
192 inline const_iterator operator++(int)
193 {
194 const_iterator r = *this;
195 index = advanceIndex(idx: index, n: 1);
196 return r;
197 }
198 inline const_iterator operator--(int)
199 {
200 const_iterator r = *this;
201 index = advanceIndex(idx: index, n: -1);
202 return r;
203 }
204 inline const_iterator operator+(int j) const
205 { return const_iterator(future, advanceIndex(idx: index, n: j)); }
206 inline const_iterator operator-(int j) const
207 { return const_iterator(future, advanceIndex(idx: index, n: -j)); }
208 inline const_iterator &operator+=(int j)
209 { index = advanceIndex(idx: index, n: j); return *this; }
210 inline const_iterator &operator-=(int j)
211 { index = advanceIndex(idx: index, n: -j); return *this; }
212 friend inline const_iterator operator+(int j, const_iterator k)
213 { return const_iterator(k.future, k.advanceIndex(k.index, j)); }
214
215 private:
216 /*! \internal
217
218 Advances the iterator index \a idx \a n steps, waits for the
219 result at the target index, and returns the target index.
220
221 The index may be -1, indicating the end iterator, either
222 as the argument or as the return value. The end iterator
223 may be decremented.
224
225 The caller is responsible for not advancing the iterator
226 before begin() or past end(), with the exception that
227 attempting to advance a non-end iterator past end() for
228 a running future is allowed and will return the end iterator.
229
230 Note that n == 0 is valid and will wait for the result
231 at the given index.
232 */
233 int advanceIndex(int idx, int n) const
234 {
235 // The end iterator can be decremented, leave as-is for other cases
236 if (idx == -1 && n >= 0)
237 return idx;
238
239 // Special case for decrementing the end iterator: wait for
240 // finished to get the total result count.
241 if (idx == -1 && future->isRunning())
242 future->d.waitForFinished();
243
244 // Wait for result at target index
245 const int targetIndex = (idx == -1) ? future->resultCount() + n : idx + n;
246 future->d.waitForResult(targetIndex);
247
248 // After waiting there is either a result or the end was reached
249 return (targetIndex < future->resultCount()) ? targetIndex : -1;
250 }
251
252 QFuture const * future;
253 int index;
254 };
255 friend class const_iterator;
256 typedef const_iterator ConstIterator;
257
258 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
259 const_iterator begin() const { return const_iterator(this, 0); }
260
261 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
262 const_iterator constBegin() const { return const_iterator(this, 0); }
263
264 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
265 const_iterator end() const { return const_iterator(this, -1); }
266
267 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
268 const_iterator constEnd() const { return const_iterator(this, -1); }
269
270private:
271 friend class QFutureWatcher<T>;
272
273 template<class U>
274 friend class QFuture;
275
276 friend class QFutureInterfaceBase;
277
278 template<class Function, class ResultType, class ParentResultType>
279 friend class QtPrivate::Continuation;
280
281 template<class Function, class ResultType>
282 friend class QtPrivate::CanceledHandler;
283
284#ifndef QT_NO_EXCEPTIONS
285 template<class Function, class ResultType>
286 friend class QtPrivate::FailureHandler;
287#endif
288
289 template<typename ResultType>
290 friend struct QtPrivate::WhenAnyContext;
291
292 friend struct QtPrivate::UnwrapHandler;
293
294 using QFuturePrivate =
295 std::conditional_t<std::is_same_v<T, void>, QFutureInterfaceBase, QFutureInterface<T>>;
296
297#ifdef QFUTURE_TEST
298public:
299#endif
300 mutable QFuturePrivate d;
301};
302
303template<typename T>
304template<typename U, typename>
305inline T QFuture<T>::result() const
306{
307 d.waitForResult(0);
308 return d.resultReference(0);
309}
310
311template<typename T>
312template<typename U, typename>
313inline T QFuture<T>::resultAt(int index) const
314{
315 d.waitForResult(index);
316 return d.resultReference(index);
317}
318
319template <typename T>
320inline QFuture<T> QFutureInterface<T>::future()
321{
322 return QFuture<T>(this);
323}
324
325template<class T>
326template<class Function>
327QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(Function &&function)
328{
329 return then(QtFuture::Launch::Sync, std::forward<Function>(function));
330}
331
332template<class T>
333template<class Function>
334QFuture<typename QFuture<T>::template ResultType<Function>>
335QFuture<T>::then(QtFuture::Launch policy, Function &&function)
336{
337 QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
338 QtPrivate::Continuation<std::decay_t<Function>, ResultType<Function>, T>::create(
339 std::forward<Function>(function), this, promise, policy);
340 return promise.future();
341}
342
343template<class T>
344template<class Function>
345QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QThreadPool *pool,
346 Function &&function)
347{
348 QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
349 QtPrivate::Continuation<std::decay_t<Function>, ResultType<Function>, T>::create(
350 std::forward<Function>(function), this, promise, pool);
351 return promise.future();
352}
353
354template<class T>
355template<class Function>
356QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QObject *context,
357 Function &&function)
358{
359 QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
360 QtPrivate::Continuation<std::decay_t<Function>, ResultType<Function>, T>::create(
361 std::forward<Function>(function), this, promise, context);
362 return promise.future();
363}
364
365#ifndef QT_NO_EXCEPTIONS
366template<class T>
367template<class Function, typename>
368QFuture<T> QFuture<T>::onFailed(Function &&handler)
369{
370 QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
371 QtPrivate::FailureHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
372 this, promise);
373 return promise.future();
374}
375
376template<class T>
377template<class Function, typename>
378QFuture<T> QFuture<T>::onFailed(QObject *context, Function &&handler)
379{
380 QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
381 QtPrivate::FailureHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
382 this, promise, context);
383 return promise.future();
384}
385
386#endif
387
388template<class T>
389template<class Function, typename>
390QFuture<T> QFuture<T>::onCanceled(Function &&handler)
391{
392 QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
393 QtPrivate::CanceledHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
394 this, promise);
395 return promise.future();
396}
397
398template<class T>
399template<class Function, typename>
400QFuture<T> QFuture<T>::onCanceled(QObject *context, Function &&handler)
401{
402 QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
403 QtPrivate::CanceledHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
404 this, promise, context);
405 return promise.future();
406}
407
408template<class T>
409template<class U, typename>
410auto QFuture<T>::unwrap()
411{
412 if constexpr (QtPrivate::isQFutureV<typename QtPrivate::Future<T>::type>)
413 return QtPrivate::UnwrapHandler::unwrapImpl(this).unwrap();
414 else
415 return QtPrivate::UnwrapHandler::unwrapImpl(this);
416}
417
418inline QFuture<void> QFutureInterface<void>::future()
419{
420 return QFuture<void>(this);
421}
422
423template<typename T>
424QFutureInterfaceBase QFutureInterfaceBase::get(const QFuture<T> &future)
425{
426 return future.d;
427}
428
429namespace QtPrivate
430{
431
432template<typename T>
433struct MetaTypeQFutureHelper<QFuture<T>>
434{
435 static bool registerConverter() {
436 if constexpr (std::is_same_v<T, void>)
437 return false;
438
439 return QMetaType::registerConverter<QFuture<T>, QFuture<void>>(
440 [](const QFuture<T> &future) { return QFuture<void>(future); });
441 }
442};
443
444} // namespace QtPrivate
445
446namespace QtFuture {
447
448#ifndef Q_QDOC
449
450template<typename OutputSequence, typename InputIt,
451 typename ValueType = typename std::iterator_traits<InputIt>::value_type,
452 std::enable_if_t<std::conjunction_v<QtPrivate::IsForwardIterable<InputIt>,
453 QtPrivate::IsRandomAccessible<OutputSequence>,
454 QtPrivate::isQFuture<ValueType>>,
455 int> = 0>
456QFuture<OutputSequence> whenAll(InputIt first, InputIt last)
457{
458 return QtPrivate::whenAllImpl<OutputSequence, InputIt, ValueType>(first, last);
459}
460
461template<typename InputIt, typename ValueType = typename std::iterator_traits<InputIt>::value_type,
462 std::enable_if_t<std::conjunction_v<QtPrivate::IsForwardIterable<InputIt>,
463 QtPrivate::isQFuture<ValueType>>,
464 int> = 0>
465QFuture<QList<ValueType>> whenAll(InputIt first, InputIt last)
466{
467 return QtPrivate::whenAllImpl<QList<ValueType>, InputIt, ValueType>(first, last);
468}
469
470template<typename OutputSequence, typename... Futures,
471 std::enable_if_t<std::conjunction_v<QtPrivate::IsRandomAccessible<OutputSequence>,
472 QtPrivate::NotEmpty<Futures...>,
473 QtPrivate::isQFuture<std::decay_t<Futures>>...>,
474 int> = 0>
475QFuture<OutputSequence> whenAll(Futures &&... futures)
476{
477 return QtPrivate::whenAllImpl<OutputSequence, Futures...>(std::forward<Futures>(futures)...);
478}
479
480template<typename... Futures,
481 std::enable_if_t<std::conjunction_v<QtPrivate::NotEmpty<Futures...>,
482 QtPrivate::isQFuture<std::decay_t<Futures>>...>,
483 int> = 0>
484QFuture<QList<std::variant<std::decay_t<Futures>...>>> whenAll(Futures &&... futures)
485{
486 return QtPrivate::whenAllImpl<QList<std::variant<std::decay_t<Futures>...>>, Futures...>(
487 std::forward<Futures>(futures)...);
488}
489
490template<typename InputIt, typename ValueType = typename std::iterator_traits<InputIt>::value_type,
491 std::enable_if_t<std::conjunction_v<QtPrivate::IsForwardIterable<InputIt>,
492 QtPrivate::isQFuture<ValueType>>,
493 int> = 0>
494QFuture<WhenAnyResult<typename QtPrivate::Future<ValueType>::type>> whenAny(InputIt first,
495 InputIt last)
496{
497 return QtPrivate::whenAnyImpl<InputIt, ValueType>(first, last);
498}
499
500template<typename... Futures,
501 std::enable_if_t<std::conjunction_v<QtPrivate::NotEmpty<Futures...>,
502 QtPrivate::isQFuture<std::decay_t<Futures>>...>,
503 int> = 0>
504QFuture<std::variant<std::decay_t<Futures>...>> whenAny(Futures &&... futures)
505{
506 return QtPrivate::whenAnyImpl(std::forward<Futures>(futures)...);
507}
508
509#else
510
511template<typename OutputSequence, typename InputIt>
512QFuture<OutputSequence> whenAll(InputIt first, InputIt last);
513
514template<typename OutputSequence, typename... Futures>
515QFuture<OutputSequence> whenAll(Futures &&... futures);
516
517template<typename T, typename InputIt>
518QFuture<QtFuture::WhenAnyResult<T>> whenAny(InputIt first, InputIt last);
519
520template<typename... Futures>
521QFuture<std::variant<std::decay_t<Futures>...>> whenAny(Futures &&... futures);
522
523#endif // Q_QDOC
524
525#if QT_DEPRECATED_SINCE(6, 10)
526#if defined(Q_QDOC)
527static QFuture<void> makeReadyFuture()
528#else
529template<typename T = void>
530QT_DEPRECATED_VERSION_X(6, 10, "Use makeReadyVoidFuture() instead")
531static QFuture<T> makeReadyFuture()
532#endif
533{
534 return makeReadyVoidFuture();
535}
536#endif // QT_DEPRECATED_SINCE(6, 10)
537
538} // namespace QtFuture
539
540Q_DECLARE_SEQUENTIAL_ITERATOR(Future)
541
542QT_END_NAMESPACE
543
544Q_DECLARE_METATYPE_TEMPLATE_1ARG(QFuture)
545
546#endif // QFUTURE_H
547

source code of qtbase/src/corelib/thread/qfuture.h