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

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