Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qfuture.h
Go to the documentation of this file.
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
19
20QT_BEGIN_NAMESPACE
21
22template <typename T>
23class QFutureWatcher;
24
25template <typename T>
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:
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>>
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(); }
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 {
78 return d.isPaused();
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(); }
91 void suspend() { setSuspended(true); }
92 void resume() { setSuspended(false); }
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(); }
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>
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,
148
149 template<class Function,
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
169 {
170 public:
171 static_assert(!std::is_void_v<T>,
172 "It isn't possible to define QFuture<void>::const_iterator");
173
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(_index, 0)) { }
183 inline const_iterator(const const_iterator &o) : future(o.future), index(o.index) {}
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); }
189 { index = advanceIndex(index, 1); return *this; }
191 { index = advanceIndex(index, -1); return *this; }
193 {
194 const_iterator r = *this;
195 index = advanceIndex(index, 1);
196 return r;
197 }
199 {
200 const_iterator r = *this;
201 index = advanceIndex(index, -1);
202 return r;
203 }
204 inline const_iterator operator+(int j) const
205 { return const_iterator(future, advanceIndex(index, j)); }
206 inline const_iterator operator-(int j) const
207 { return const_iterator(future, advanceIndex(index, -j)); }
208 inline const_iterator &operator+=(int j)
209 { index = advanceIndex(index, j); return *this; }
210 inline const_iterator &operator-=(int j)
211 { index = advanceIndex(index, -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 }
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())
249
250 // Wait for result at target index
251 const int targetIndex = (idx == -1) ? future->resultCount() + n : idx + n;
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;
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>
286
287 template<class Function, class ResultType>
289
290#ifndef QT_NO_EXCEPTIONS
291 template<class Function, class ResultType>
293#endif
294
295 template<typename ResultType>
296 friend struct QtPrivate::WhenAnyContext;
297
298 friend struct QtPrivate::UnwrapHandler;
299
300 using QFuturePrivate =
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>
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,
462 int> = 0>
467
468template<typename InputIt, typename ValueType = typename std::iterator_traits<InputIt>::value_type,
471 int> = 0>
476
477template<typename OutputSequence, typename... Futures,
481 int> = 0>
486
487template<typename... Futures,
490 int> = 0>
496
497template<typename InputIt, typename ValueType = typename std::iterator_traits<InputIt>::value_type,
500 int> = 0>
506
507template<typename... Futures,
510 int> = 0>
515
516#else
517
518template<typename OutputSequence, typename InputIt>
520
521template<typename OutputSequence, typename... Futures>
523
524template<typename T, typename InputIt>
526
527template<typename... 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
bool internal_updateProgress(int progress, const QString &progressText=QString())
void sendCallOuts(const QFutureCallOutEvent &callOut1, const QFutureCallOutEvent &callOut2)
void sendCallOut(const QFutureCallOutEvent &callOut)
void setState(QFutureInterfaceBase::State state)
bool internal_updateProgressValue(int progress)
bool internal_isResultReadyAt(int index) const
void internal_setThrottled(bool enable)
QFutureInterfaceBasePrivate * continuationData
QFutureInterfaceBasePrivate(QFutureInterfaceBase::State initialState)
const_iterator & operator-=(int j)
Definition qfuture.h:210
const_iterator operator-(int j) const
Definition qfuture.h:206
std::bidirectional_iterator_tag iterator_category
Definition qfuture.h:174
const_iterator operator++(int)
Definition qfuture.h:192
const_iterator operator--(int)
Definition qfuture.h:198
const_iterator & operator++()
Definition qfuture.h:188
const_iterator(const const_iterator &o)
Definition qfuture.h:183
friend const_iterator operator+(int j, const_iterator k)
Definition qfuture.h:212
const_iterator & operator--()
Definition qfuture.h:190
const_iterator & operator+=(int j)
Definition qfuture.h:208
const_iterator operator+(int j) const
Definition qfuture.h:204
friend bool comparesEqual(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition qfuture.h:216
const T * operator->() const
Definition qfuture.h:187
const_iterator(QFuture const *const _future, int _index)
Definition qfuture.h:181
const T & operator*() const
Definition qfuture.h:186
const_iterator & operator=(const const_iterator &o)
Definition qfuture.h:184
QFuture< ResultType< Function > > then(Function &&function)
typename QtPrivate::ResultTypeHelper< Function, T >::ResultType ResultType
Definition qfuture.h:130
friend struct QtPrivate::WhenAnyContext
Definition qfuture.h:296
friend class QtPrivate::CanceledHandler
Definition qfuture.h:288
bool isValid() const
Definition qfuture.h:127
QList< T > results() const
Definition qfuture.h:116
friend class QtPrivate::CompactContinuation
Definition qfuture.h:285
QFuture< ResultType< Function > > then(QThreadPool *pool, Function &&function)
T resultAt(int index) const
Definition qfuture.h:319
const_iterator end() const
Definition qfuture.h:271
const_iterator begin() const
Definition qfuture.h:265
const_iterator ConstIterator
Definition qfuture.h:262
QFuture()
Definition qfuture.h:32
QFuture< typename QFuture< T >::template ResultType< Function > > then(Function &&function)
Definition qfuture.h:333
QFuture< T > onCanceled(Function &&handler)
Definition qfuture.h:396
QFuture< typename QFuture< T >::template ResultType< Function > > then(QtFuture::Launch policy, Function &&function)
Definition qfuture.h:341
QFuture< typename QFuture< T >::template ResultType< Function > > then(QThreadPool *pool, Function &&function)
Definition qfuture.h:351
QFuture< T > onCanceled(QObject *context, Function &&handler)
Definition qfuture.h:406
const_iterator constEnd() const
Definition qfuture.h:274
friend class QtPrivate::FailureHandler
Definition qfuture.h:292
bool isResultReadyAt(int resultIndex) const
Definition qfuture.h:113
T takeResult()
Definition qfuture.h:119
const_iterator constBegin() const
Definition qfuture.h:268
QFuture< ResultType< Function > > then(QtFuture::Launch policy, Function &&function)
QFuture< void > makeReadyVoidFuture()
void qfutureWarnIfUnusedResults(qsizetype numResults)
static int switch_from_to(QAtomicInt &a, int from, int to)
static int switch_off(QAtomicInt &a, int which)
static int switch_on(QAtomicInt &a, int which)
QFuture< void > future
[5]