File indexing completed on 2025-01-18 10:07:24
0001
0002
0003
0004 #ifndef QFUTURE_H
0005 #define QFUTURE_H
0006
0007 #include <QtCore/qglobal.h>
0008
0009 #include <QtCore/qfutureinterface.h>
0010 #include <QtCore/qmetatype.h>
0011 #include <QtCore/qstring.h>
0012
0013 #include <QtCore/qfuture_impl.h>
0014
0015 #include <type_traits>
0016
0017 QT_REQUIRE_CONFIG(future);
0018
0019 QT_BEGIN_NAMESPACE
0020
0021 template <typename T>
0022 class QFutureWatcher;
0023
0024 template <typename T>
0025 class QFuture
0026 {
0027 static_assert (std::is_move_constructible_v<T>
0028 || std::is_same_v<T, void>,
0029 "A move-constructible type or type void is required");
0030 public:
0031 QFuture()
0032 : d(QFutureInterface<T>::canceledResult())
0033 { }
0034
0035 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
0036 explicit QFuture(QFutureInterface<T> *p)
0037 : d(*p)
0038 { }
0039
0040 template<typename U = T, typename = QtPrivate::EnableForVoid<U>>
0041 explicit QFuture(QFutureInterfaceBase *p)
0042 : d(*p)
0043 {
0044 }
0045
0046 template<typename U, typename V = T, typename = QtPrivate::EnableForVoid<V>>
0047 explicit QFuture(const QFuture<U> &other) : d(other.d)
0048 {
0049 }
0050
0051 template<typename U, typename V = T, typename = QtPrivate::EnableForVoid<V>>
0052 QFuture<void> &operator=(const QFuture<U> &other)
0053 {
0054 d = other.d;
0055 return *this;
0056 }
0057
0058 #if defined(Q_QDOC)
0059 ~QFuture() { }
0060 QFuture(const QFuture<T> &) { }
0061 QFuture<T> & operator=(const QFuture<T> &) { }
0062 #endif
0063
0064 void cancel() { d.cancel(); }
0065 bool isCanceled() const { return d.isCanceled(); }
0066
0067 #if QT_DEPRECATED_SINCE(6, 0)
0068 QT_DEPRECATED_VERSION_X_6_0("Use setSuspended() instead.")
0069 void setPaused(bool paused) { d.setSuspended(paused); }
0070
0071 QT_DEPRECATED_VERSION_X_6_0("Use isSuspending() or isSuspended() instead.")
0072 bool isPaused() const
0073 {
0074 QT_WARNING_PUSH
0075 QT_WARNING_DISABLE_DEPRECATED
0076 return d.isPaused();
0077 QT_WARNING_POP
0078 }
0079
0080 QT_DEPRECATED_VERSION_X_6_0("Use toggleSuspended() instead.")
0081 void togglePaused() { d.toggleSuspended(); }
0082
0083 QT_DEPRECATED_VERSION_X_6_0("Use suspend() instead.")
0084 void pause() { suspend(); }
0085 #endif
0086 bool isSuspending() const { return d.isSuspending(); }
0087 bool isSuspended() const { return d.isSuspended(); }
0088 void setSuspended(bool suspend) { d.setSuspended(suspend); }
0089 void suspend() { setSuspended(true); }
0090 void resume() { setSuspended(false); }
0091 void toggleSuspended() { d.toggleSuspended(); }
0092
0093 bool isStarted() const { return d.isStarted(); }
0094 bool isFinished() const { return d.isFinished(); }
0095 bool isRunning() const { return d.isRunning(); }
0096
0097 int resultCount() const { return d.resultCount(); }
0098 int progressValue() const { return d.progressValue(); }
0099 int progressMinimum() const { return d.progressMinimum(); }
0100 int progressMaximum() const { return d.progressMaximum(); }
0101 QString progressText() const { return d.progressText(); }
0102 void waitForFinished() { d.waitForFinished(); }
0103
0104 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
0105 inline T result() const;
0106
0107 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
0108 inline T resultAt(int index) const;
0109
0110 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
0111 bool isResultReadyAt(int resultIndex) const { return d.isResultReadyAt(resultIndex); }
0112
0113 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
0114 QList<T> results() const { return d.results(); }
0115
0116 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
0117 T takeResult() { return d.takeResult(); }
0118
0119 #if 0
0120
0121 template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
0122 std::vector<T> takeResults() { return d.takeResults(); }
0123 #endif
0124
0125 bool isValid() const { return d.isValid(); }
0126
0127 template<class Function>
0128 using ResultType = typename QtPrivate::ResultTypeHelper<Function, T>::ResultType;
0129
0130 template<class Function>
0131 QFuture<ResultType<Function>> then(Function &&function);
0132
0133 template<class Function>
0134 QFuture<ResultType<Function>> then(QtFuture::Launch policy, Function &&function);
0135
0136 template<class Function>
0137 QFuture<ResultType<Function>> then(QThreadPool *pool, Function &&function);
0138
0139 template<class Function>
0140 QFuture<ResultType<Function>> then(QObject *context, Function &&function);
0141
0142 #ifndef QT_NO_EXCEPTIONS
0143 template<class Function,
0144 typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>>
0145 QFuture<T> onFailed(Function &&handler);
0146
0147 template<class Function,
0148 typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>>
0149 QFuture<T> onFailed(QObject *context, Function &&handler);
0150 #endif
0151
0152 template<class Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>>
0153 QFuture<T> onCanceled(Function &&handler);
0154
0155 template<class Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>>
0156 QFuture<T> onCanceled(QObject *context, Function &&handler);
0157
0158 #if !defined(Q_QDOC)
0159 template<class U = T, typename = std::enable_if_t<QtPrivate::isQFutureV<U>>>
0160 auto unwrap();
0161 #else
0162 template<class U>
0163 QFuture<U> unwrap();
0164 #endif
0165
0166 class const_iterator
0167 {
0168 public:
0169 static_assert(!std::is_same_v<T, void>,
0170 "It isn't possible to define QFuture<void>::const_iterator");
0171
0172 typedef std::bidirectional_iterator_tag iterator_category;
0173 typedef qptrdiff difference_type;
0174 typedef T value_type;
0175 typedef const T *pointer;
0176 typedef const T &reference;
0177
0178 inline const_iterator() {}
0179 inline const_iterator(QFuture const * const _future, int _index)
0180 : future(_future), index(advanceIndex(_index, 0)) { }
0181 inline const_iterator(const const_iterator &o) : future(o.future), index(o.index) {}
0182 inline const_iterator &operator=(const const_iterator &o)
0183 { future = o.future; index = o.index; return *this; }
0184 inline const T &operator*() const { return future->d.resultReference(index); }
0185 inline const T *operator->() const { return future->d.resultPointer(index); }
0186 inline bool operator!=(const const_iterator &other) const { return index != other.index; }
0187 inline bool operator==(const const_iterator &o) const { return !operator!=(o); }
0188 inline const_iterator &operator++()
0189 { index = advanceIndex(index, 1); return *this; }
0190 inline const_iterator &operator--()
0191 { index = advanceIndex(index, -1); return *this; }
0192 inline const_iterator operator++(int)
0193 {
0194 const_iterator r = *this;
0195 index = advanceIndex(index, 1);
0196 return r;
0197 }
0198 inline const_iterator operator--(int)
0199 {
0200 const_iterator r = *this;
0201 index = advanceIndex(index, -1);
0202 return r;
0203 }
0204 inline const_iterator operator+(int j) const
0205 { return const_iterator(future, advanceIndex(index, j)); }
0206 inline const_iterator operator-(int j) const
0207 { return const_iterator(future, advanceIndex(index, -j)); }
0208 inline const_iterator &operator+=(int j)
0209 { index = advanceIndex(index, j); return *this; }
0210 inline const_iterator &operator-=(int j)
0211 { index = advanceIndex(index, -j); return *this; }
0212 friend inline const_iterator operator+(int j, const_iterator k)
0213 { return const_iterator(k.future, k.advanceIndex(k.index, j)); }
0214
0215 private:
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233 int advanceIndex(int idx, int n) const
0234 {
0235
0236 if (idx == -1 && n >= 0)
0237 return idx;
0238
0239
0240
0241 if (idx == -1 && future->isRunning())
0242 future->d.waitForFinished();
0243
0244
0245 const int targetIndex = (idx == -1) ? future->resultCount() + n : idx + n;
0246 future->d.waitForResult(targetIndex);
0247
0248
0249 return (targetIndex < future->resultCount()) ? targetIndex : -1;
0250 }
0251
0252 QFuture const * future;
0253 int index;
0254 };
0255 friend class const_iterator;
0256 typedef const_iterator ConstIterator;
0257
0258 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
0259 const_iterator begin() const { return const_iterator(this, 0); }
0260
0261 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
0262 const_iterator constBegin() const { return const_iterator(this, 0); }
0263
0264 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
0265 const_iterator end() const { return const_iterator(this, -1); }
0266
0267 template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
0268 const_iterator constEnd() const { return const_iterator(this, -1); }
0269
0270 private:
0271 friend class QFutureWatcher<T>;
0272
0273 template<class U>
0274 friend class QFuture;
0275
0276 friend class QFutureInterfaceBase;
0277
0278 template<class Function, class ResultType, class ParentResultType>
0279 friend class QtPrivate::Continuation;
0280
0281 template<class Function, class ResultType>
0282 friend class QtPrivate::CanceledHandler;
0283
0284 #ifndef QT_NO_EXCEPTIONS
0285 template<class Function, class ResultType>
0286 friend class QtPrivate::FailureHandler;
0287 #endif
0288
0289 template<typename ResultType>
0290 friend struct QtPrivate::WhenAnyContext;
0291
0292 friend struct QtPrivate::UnwrapHandler;
0293
0294 using QFuturePrivate =
0295 std::conditional_t<std::is_same_v<T, void>, QFutureInterfaceBase, QFutureInterface<T>>;
0296
0297 #ifdef QFUTURE_TEST
0298 public:
0299 #endif
0300 mutable QFuturePrivate d;
0301 };
0302
0303 template<typename T>
0304 template<typename U, typename>
0305 inline T QFuture<T>::result() const
0306 {
0307 d.waitForResult(0);
0308 return d.resultReference(0);
0309 }
0310
0311 template<typename T>
0312 template<typename U, typename>
0313 inline T QFuture<T>::resultAt(int index) const
0314 {
0315 d.waitForResult(index);
0316 return d.resultReference(index);
0317 }
0318
0319 template <typename T>
0320 inline QFuture<T> QFutureInterface<T>::future()
0321 {
0322 return QFuture<T>(this);
0323 }
0324
0325 template<class T>
0326 template<class Function>
0327 QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(Function &&function)
0328 {
0329 return then(QtFuture::Launch::Sync, std::forward<Function>(function));
0330 }
0331
0332 template<class T>
0333 template<class Function>
0334 QFuture<typename QFuture<T>::template ResultType<Function>>
0335 QFuture<T>::then(QtFuture::Launch policy, Function &&function)
0336 {
0337 QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
0338 QtPrivate::Continuation<std::decay_t<Function>, ResultType<Function>, T>::create(
0339 std::forward<Function>(function), this, promise, policy);
0340 return promise.future();
0341 }
0342
0343 template<class T>
0344 template<class Function>
0345 QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QThreadPool *pool,
0346 Function &&function)
0347 {
0348 QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
0349 QtPrivate::Continuation<std::decay_t<Function>, ResultType<Function>, T>::create(
0350 std::forward<Function>(function), this, promise, pool);
0351 return promise.future();
0352 }
0353
0354 template<class T>
0355 template<class Function>
0356 QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QObject *context,
0357 Function &&function)
0358 {
0359 QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
0360 QtPrivate::Continuation<std::decay_t<Function>, ResultType<Function>, T>::create(
0361 std::forward<Function>(function), this, promise, context);
0362 return promise.future();
0363 }
0364
0365 #ifndef QT_NO_EXCEPTIONS
0366 template<class T>
0367 template<class Function, typename>
0368 QFuture<T> QFuture<T>::onFailed(Function &&handler)
0369 {
0370 QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
0371 QtPrivate::FailureHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
0372 this, promise);
0373 return promise.future();
0374 }
0375
0376 template<class T>
0377 template<class Function, typename>
0378 QFuture<T> QFuture<T>::onFailed(QObject *context, Function &&handler)
0379 {
0380 QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
0381 QtPrivate::FailureHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
0382 this, promise, context);
0383 return promise.future();
0384 }
0385
0386 #endif
0387
0388 template<class T>
0389 template<class Function, typename>
0390 QFuture<T> QFuture<T>::onCanceled(Function &&handler)
0391 {
0392 QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
0393 QtPrivate::CanceledHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
0394 this, promise);
0395 return promise.future();
0396 }
0397
0398 template<class T>
0399 template<class Function, typename>
0400 QFuture<T> QFuture<T>::onCanceled(QObject *context, Function &&handler)
0401 {
0402 QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
0403 QtPrivate::CanceledHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
0404 this, promise, context);
0405 return promise.future();
0406 }
0407
0408 template<class T>
0409 template<class U, typename>
0410 auto QFuture<T>::unwrap()
0411 {
0412 if constexpr (QtPrivate::isQFutureV<typename QtPrivate::Future<T>::type>)
0413 return QtPrivate::UnwrapHandler::unwrapImpl(this).unwrap();
0414 else
0415 return QtPrivate::UnwrapHandler::unwrapImpl(this);
0416 }
0417
0418 inline QFuture<void> QFutureInterface<void>::future()
0419 {
0420 return QFuture<void>(this);
0421 }
0422
0423 template<typename T>
0424 QFutureInterfaceBase QFutureInterfaceBase::get(const QFuture<T> &future)
0425 {
0426 return future.d;
0427 }
0428
0429 namespace QtPrivate
0430 {
0431
0432 template<typename T>
0433 struct MetaTypeQFutureHelper<QFuture<T>>
0434 {
0435 static bool registerConverter() {
0436 if constexpr (std::is_same_v<T, void>)
0437 return false;
0438
0439 return QMetaType::registerConverter<QFuture<T>, QFuture<void>>(
0440 [](const QFuture<T> &future) { return QFuture<void>(future); });
0441 }
0442 };
0443
0444 }
0445
0446 namespace QtFuture {
0447
0448 #ifndef Q_QDOC
0449
0450 template<typename OutputSequence, typename InputIt,
0451 typename ValueType = typename std::iterator_traits<InputIt>::value_type,
0452 std::enable_if_t<std::conjunction_v<QtPrivate::IsForwardIterable<InputIt>,
0453 QtPrivate::IsRandomAccessible<OutputSequence>,
0454 QtPrivate::isQFuture<ValueType>>,
0455 int> = 0>
0456 QFuture<OutputSequence> whenAll(InputIt first, InputIt last)
0457 {
0458 return QtPrivate::whenAllImpl<OutputSequence, InputIt, ValueType>(first, last);
0459 }
0460
0461 template<typename InputIt, typename ValueType = typename std::iterator_traits<InputIt>::value_type,
0462 std::enable_if_t<std::conjunction_v<QtPrivate::IsForwardIterable<InputIt>,
0463 QtPrivate::isQFuture<ValueType>>,
0464 int> = 0>
0465 QFuture<QList<ValueType>> whenAll(InputIt first, InputIt last)
0466 {
0467 return QtPrivate::whenAllImpl<QList<ValueType>, InputIt, ValueType>(first, last);
0468 }
0469
0470 template<typename OutputSequence, typename... Futures,
0471 std::enable_if_t<std::conjunction_v<QtPrivate::IsRandomAccessible<OutputSequence>,
0472 QtPrivate::NotEmpty<Futures...>,
0473 QtPrivate::isQFuture<std::decay_t<Futures>>...>,
0474 int> = 0>
0475 QFuture<OutputSequence> whenAll(Futures &&... futures)
0476 {
0477 return QtPrivate::whenAllImpl<OutputSequence, Futures...>(std::forward<Futures>(futures)...);
0478 }
0479
0480 template<typename... Futures,
0481 std::enable_if_t<std::conjunction_v<QtPrivate::NotEmpty<Futures...>,
0482 QtPrivate::isQFuture<std::decay_t<Futures>>...>,
0483 int> = 0>
0484 QFuture<QList<std::variant<std::decay_t<Futures>...>>> whenAll(Futures &&... futures)
0485 {
0486 return QtPrivate::whenAllImpl<QList<std::variant<std::decay_t<Futures>...>>, Futures...>(
0487 std::forward<Futures>(futures)...);
0488 }
0489
0490 template<typename InputIt, typename ValueType = typename std::iterator_traits<InputIt>::value_type,
0491 std::enable_if_t<std::conjunction_v<QtPrivate::IsForwardIterable<InputIt>,
0492 QtPrivate::isQFuture<ValueType>>,
0493 int> = 0>
0494 QFuture<WhenAnyResult<typename QtPrivate::Future<ValueType>::type>> whenAny(InputIt first,
0495 InputIt last)
0496 {
0497 return QtPrivate::whenAnyImpl<InputIt, ValueType>(first, last);
0498 }
0499
0500 template<typename... Futures,
0501 std::enable_if_t<std::conjunction_v<QtPrivate::NotEmpty<Futures...>,
0502 QtPrivate::isQFuture<std::decay_t<Futures>>...>,
0503 int> = 0>
0504 QFuture<std::variant<std::decay_t<Futures>...>> whenAny(Futures &&... futures)
0505 {
0506 return QtPrivate::whenAnyImpl(std::forward<Futures>(futures)...);
0507 }
0508
0509 #else
0510
0511 template<typename OutputSequence, typename InputIt>
0512 QFuture<OutputSequence> whenAll(InputIt first, InputIt last);
0513
0514 template<typename OutputSequence, typename... Futures>
0515 QFuture<OutputSequence> whenAll(Futures &&... futures);
0516
0517 template<typename T, typename InputIt>
0518 QFuture<QtFuture::WhenAnyResult<T>> whenAny(InputIt first, InputIt last);
0519
0520 template<typename... Futures>
0521 QFuture<std::variant<std::decay_t<Futures>...>> whenAny(Futures &&... futures);
0522
0523 #endif
0524
0525 #if QT_DEPRECATED_SINCE(6, 10)
0526 #if defined(Q_QDOC)
0527 static QFuture<void> makeReadyFuture()
0528 #else
0529 template<typename T = void>
0530 QT_DEPRECATED_VERSION_X(6, 10, "Use makeReadyVoidFuture() instead.")
0531 static QFuture<T> makeReadyFuture()
0532 #endif
0533 {
0534 return makeReadyVoidFuture();
0535 }
0536 #endif
0537
0538 }
0539
0540 Q_DECLARE_SEQUENTIAL_ITERATOR(Future)
0541
0542 QT_END_NAMESPACE
0543
0544 Q_DECLARE_METATYPE_TEMPLATE_1ARG(QFuture)
0545
0546 #endif