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 const_iterator &operator++()
187 { index = advanceIndex(idx: index, n: 1); return *this; }
188 inline const_iterator &operator--()
189 { index = advanceIndex(idx: index, n: -1); return *this; }
190 inline const_iterator operator++(int)
191 {
192 const_iterator r = *this;
193 index = advanceIndex(idx: index, n: 1);
194 return r;
195 }
196 inline const_iterator operator--(int)
197 {
198 const_iterator r = *this;
199 index = advanceIndex(idx: index, n: -1);
200 return r;
201 }
202 inline const_iterator operator+(int j) const
203 { return const_iterator(future, advanceIndex(idx: index, n: j)); }
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)
207 { index = advanceIndex(idx: index, n: j); return *this; }
208 inline const_iterator &operator-=(int j)
209 { index = advanceIndex(idx: index, n: -j); return *this; }
210 friend inline const_iterator operator+(int j, const_iterator k)
211 { return const_iterator(k.future, k.advanceIndex(k.index, j)); }
212
213 private:
214 friend bool comparesEqual(const const_iterator &lhs, const const_iterator &rhs) noexcept
215 {
216 return lhs.index == rhs.index;
217 }
218 Q_DECLARE_EQUALITY_COMPARABLE(const_iterator)
219
220 /*! \internal
221
222 Advances the iterator index \a idx \a n steps, waits for the
223 result at the target index, and returns the target index.
224
225 The index may be -1, indicating the end iterator, either
226 as the argument or as the return value. The end iterator
227 may be decremented.
228
229 The caller is responsible for not advancing the iterator
230 before begin() or past end(), with the exception that
231 attempting to advance a non-end iterator past end() for
232 a running future is allowed and will return the end iterator.
233
234 Note that n == 0 is valid and will wait for the result
235 at the given index.
236 */
237 int advanceIndex(int idx, int n) const
238 {
239 // The end iterator can be decremented, leave as-is for other cases
240 if (idx == -1 && n >= 0)
241 return idx;
242
243 // Special case for decrementing the end iterator: wait for
244 // finished to get the total result count.
245 if (idx == -1 && future->isRunning())
246 future->d.waitForFinished();
247
248 // Wait for result at target index
249 const int targetIndex = (idx == -1) ? future->resultCount() + n : idx + n;
250 future->d.waitForResult(targetIndex);
251
252 // After waiting there is either a result or the end was reached
253 return (targetIndex < future->resultCount()) ? targetIndex : -1;
254 }
255
256 QFuture const * future;
257 int index;
258 };
259 friend class const_iterator;
260 typedef const_iterator ConstIterator;
261
262 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
263 const_iterator begin() const { return const_iterator(this, 0); }
264
265 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
266 const_iterator constBegin() const { return const_iterator(this, 0); }
267
268 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
269 const_iterator end() const { return const_iterator(this, -1); }
270
271 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
272 const_iterator constEnd() const { return const_iterator(this, -1); }
273
274private:
275 friend class QFutureWatcher<T>;
276
277 template<class U>
278 friend class QFuture;
279
280 friend class QFutureInterfaceBase;
281
282 template<class Function, class ResultType, class ParentResultType>
283 friend class QtPrivate::Continuation;
284
285 template<class Function, class ResultType>
286 friend class QtPrivate::CanceledHandler;
287
288#ifndef QT_NO_EXCEPTIONS
289 template<class Function, class ResultType>
290 friend class QtPrivate::FailureHandler;
291#endif
292
293 template<typename ResultType>
294 friend struct QtPrivate::WhenAnyContext;
295
296 friend struct QtPrivate::UnwrapHandler;
297
298 using QFuturePrivate =
299 std::conditional_t<std::is_same_v<T, void>, QFutureInterfaceBase, QFutureInterface<T>>;
300
301#ifdef QFUTURE_TEST
302public:
303#endif
304 mutable QFuturePrivate d;
305};
306
307template<typename T>
308template<typename U, typename>
309inline T QFuture<T>::result() const
310{
311 d.waitForResult(0);
312 return d.resultReference(0);
313}
314
315template<typename T>
316template<typename U, typename>
317inline T QFuture<T>::resultAt(int index) const
318{
319 d.waitForResult(index);
320 return d.resultReference(index);
321}
322
323template <typename T>
324inline QFuture<T> QFutureInterface<T>::future()
325{
326 return QFuture<T>(this);
327}
328
329template<class T>
330template<class Function>
331QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(Function &&function)
332{
333 return then(QtFuture::Launch::Sync, std::forward<Function>(function));
334}
335
336template<class T>
337template<class Function>
338QFuture<typename QFuture<T>::template ResultType<Function>>
339QFuture<T>::then(QtFuture::Launch policy, Function &&function)
340{
341 QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
342 QtPrivate::Continuation<std::decay_t<Function>, ResultType<Function>, T>::create(
343 std::forward<Function>(function), this, promise, policy);
344 return promise.future();
345}
346
347template<class T>
348template<class Function>
349QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QThreadPool *pool,
350 Function &&function)
351{
352 QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
353 QtPrivate::Continuation<std::decay_t<Function>, ResultType<Function>, T>::create(
354 std::forward<Function>(function), this, promise, pool);
355 return promise.future();
356}
357
358template<class T>
359template<class Function>
360QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QObject *context,
361 Function &&function)
362{
363 QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
364 QtPrivate::Continuation<std::decay_t<Function>, ResultType<Function>, T>::create(
365 std::forward<Function>(function), this, promise, context);
366 return promise.future();
367}
368
369#ifndef QT_NO_EXCEPTIONS
370template<class T>
371template<class Function, typename>
372QFuture<T> QFuture<T>::onFailed(Function &&handler)
373{
374 QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
375 QtPrivate::FailureHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
376 this, promise);
377 return promise.future();
378}
379
380template<class T>
381template<class Function, typename>
382QFuture<T> QFuture<T>::onFailed(QObject *context, Function &&handler)
383{
384 QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
385 QtPrivate::FailureHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
386 this, promise, context);
387 return promise.future();
388}
389
390#endif
391
392template<class T>
393template<class Function, typename>
394QFuture<T> QFuture<T>::onCanceled(Function &&handler)
395{
396 QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
397 QtPrivate::CanceledHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
398 this, promise);
399 return promise.future();
400}
401
402template<class T>
403template<class Function, typename>
404QFuture<T> QFuture<T>::onCanceled(QObject *context, Function &&handler)
405{
406 QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
407 QtPrivate::CanceledHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
408 this, promise, context);
409 return promise.future();
410}
411
412template<class T>
413template<class U, typename>
414auto QFuture<T>::unwrap()
415{
416 if constexpr (QtPrivate::isQFutureV<typename QtPrivate::Future<T>::type>)
417 return QtPrivate::UnwrapHandler::unwrapImpl(this).unwrap();
418 else
419 return QtPrivate::UnwrapHandler::unwrapImpl(this);
420}
421
422inline QFuture<void> QFutureInterface<void>::future()
423{
424 return QFuture<void>(this);
425}
426
427template<typename T>
428QFutureInterfaceBase QFutureInterfaceBase::get(const QFuture<T> &future)
429{
430 return future.d;
431}
432
433namespace QtPrivate
434{
435
436template<typename T>
437struct MetaTypeQFutureHelper<QFuture<T>>
438{
439 static bool registerConverter() {
440 if constexpr (std::is_same_v<T, void>)
441 return false;
442
443 return QMetaType::registerConverter<QFuture<T>, QFuture<void>>(
444 [](const QFuture<T> &future) { return QFuture<void>(future); });
445 }
446};
447
448} // namespace QtPrivate
449
450namespace QtFuture {
451
452#ifndef Q_QDOC
453
454template<typename OutputSequence, typename InputIt,
455 typename ValueType = typename std::iterator_traits<InputIt>::value_type,
456 std::enable_if_t<std::conjunction_v<QtPrivate::IsForwardIterable<InputIt>,
457 QtPrivate::IsRandomAccessible<OutputSequence>,
458 QtPrivate::isQFuture<ValueType>>,
459 int> = 0>
460QFuture<OutputSequence> whenAll(InputIt first, InputIt last)
461{
462 return QtPrivate::whenAllImpl<OutputSequence, InputIt, ValueType>(first, last);
463}
464
465template<typename InputIt, typename ValueType = typename std::iterator_traits<InputIt>::value_type,
466 std::enable_if_t<std::conjunction_v<QtPrivate::IsForwardIterable<InputIt>,
467 QtPrivate::isQFuture<ValueType>>,
468 int> = 0>
469QFuture<QList<ValueType>> whenAll(InputIt first, InputIt last)
470{
471 return QtPrivate::whenAllImpl<QList<ValueType>, InputIt, ValueType>(first, last);
472}
473
474template<typename OutputSequence, typename... Futures,
475 std::enable_if_t<std::conjunction_v<QtPrivate::IsRandomAccessible<OutputSequence>,
476 QtPrivate::NotEmpty<Futures...>,
477 QtPrivate::isQFuture<std::decay_t<Futures>>...>,
478 int> = 0>
479QFuture<OutputSequence> whenAll(Futures &&... futures)
480{
481 return QtPrivate::whenAllImpl<OutputSequence, Futures...>(std::forward<Futures>(futures)...);
482}
483
484template<typename... Futures,
485 std::enable_if_t<std::conjunction_v<QtPrivate::NotEmpty<Futures...>,
486 QtPrivate::isQFuture<std::decay_t<Futures>>...>,
487 int> = 0>
488QFuture<QList<std::variant<std::decay_t<Futures>...>>> whenAll(Futures &&... futures)
489{
490 return QtPrivate::whenAllImpl<QList<std::variant<std::decay_t<Futures>...>>, Futures...>(
491 std::forward<Futures>(futures)...);
492}
493
494template<typename InputIt, typename ValueType = typename std::iterator_traits<InputIt>::value_type,
495 std::enable_if_t<std::conjunction_v<QtPrivate::IsForwardIterable<InputIt>,
496 QtPrivate::isQFuture<ValueType>>,
497 int> = 0>
498QFuture<WhenAnyResult<typename QtPrivate::Future<ValueType>::type>> whenAny(InputIt first,
499 InputIt last)
500{
501 return QtPrivate::whenAnyImpl<InputIt, ValueType>(first, last);
502}
503
504template<typename... Futures,
505 std::enable_if_t<std::conjunction_v<QtPrivate::NotEmpty<Futures...>,
506 QtPrivate::isQFuture<std::decay_t<Futures>>...>,
507 int> = 0>
508QFuture<std::variant<std::decay_t<Futures>...>> whenAny(Futures &&... futures)
509{
510 return QtPrivate::whenAnyImpl(std::forward<Futures>(futures)...);
511}
512
513#else
514
515template<typename OutputSequence, typename InputIt>
516QFuture<OutputSequence> whenAll(InputIt first, InputIt last);
517
518template<typename OutputSequence, typename... Futures>
519QFuture<OutputSequence> whenAll(Futures &&... futures);
520
521template<typename T, typename InputIt>
522QFuture<QtFuture::WhenAnyResult<T>> whenAny(InputIt first, InputIt last);
523
524template<typename... Futures>
525QFuture<std::variant<std::decay_t<Futures>...>> whenAny(Futures &&... futures);
526
527#endif // Q_QDOC
528
529#if QT_DEPRECATED_SINCE(6, 10)
530#if defined(Q_QDOC)
531static QFuture<void> makeReadyFuture()
532#else
533template<typename T = void>
534QT_DEPRECATED_VERSION_X(6, 10, "Use makeReadyVoidFuture() instead.")
535static QFuture<T> makeReadyFuture()
536#endif
537{
538 return makeReadyVoidFuture();
539}
540#endif // QT_DEPRECATED_SINCE(6, 10)
541
542} // namespace QtFuture
543
544Q_DECLARE_SEQUENTIAL_ITERATOR(Future)
545
546QT_END_NAMESPACE
547
548Q_DECLARE_METATYPE_TEMPLATE_1ARG(QFuture)
549
550#endif // QFUTURE_H
551

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

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