File indexing completed on 2026-09-17 09:24:55
0001
0002
0003
0004
0005 #ifndef QFUTUREINTERFACE_H
0006 #define QFUTUREINTERFACE_H
0007
0008 #include <QtCore/qmutex.h>
0009 #include <QtCore/qresultstore.h>
0010 #include <QtCore/qtcoreexports.h>
0011 #ifndef QT_NO_EXCEPTIONS
0012 #include <exception>
0013 #endif
0014
0015 #include <utility>
0016
0017 QT_REQUIRE_CONFIG(future);
0018
0019 QT_FORWARD_DECLARE_CLASS(QRunnable)
0020 QT_FORWARD_DECLARE_CLASS(QException)
0021 QT_BEGIN_NAMESPACE
0022
0023
0024 template <typename T> class QFuture;
0025 class QThreadPool;
0026 class QFutureInterfaceBase;
0027 class QFutureInterfaceBasePrivate;
0028 class QFutureWatcherBase;
0029 class QFutureWatcherBasePrivate;
0030
0031 namespace QtPrivate {
0032 template<typename Function, typename ResultType, typename ParentResultType>
0033 class CompactContinuation;
0034
0035 class ExceptionStore;
0036
0037 template<class Function, class ResultType>
0038 class CanceledHandler;
0039
0040 #ifndef QT_NO_EXCEPTIONS
0041 template<class Function, class ResultType>
0042 class FailureHandler;
0043 #endif
0044
0045 struct UnwrapHandler;
0046
0047 #if QT_CORE_REMOVED_SINCE(6, 10)
0048 void Q_CORE_EXPORT watchContinuationImpl(const QObject *context,
0049 QtPrivate::QSlotObjectBase *slotObj,
0050 QFutureInterfaceBase &fi);
0051 #endif
0052 }
0053
0054 class Q_CORE_EXPORT QFutureInterfaceBase
0055 {
0056 public:
0057 enum State {
0058 NoState = 0x00,
0059 Running = 0x01,
0060 Started = 0x02,
0061 Finished = 0x04,
0062 Canceled = 0x08,
0063 Suspending = 0x10,
0064 Suspended = 0x20,
0065 Throttled = 0x40,
0066
0067 Pending = 0x80,
0068 };
0069
0070 QFutureInterfaceBase(State initialState = NoState);
0071 QFutureInterfaceBase(const QFutureInterfaceBase &other);
0072 QFutureInterfaceBase(QFutureInterfaceBase &&other) noexcept
0073 : d(std::exchange(other.d, nullptr)) {}
0074 QFutureInterfaceBase &operator=(const QFutureInterfaceBase &other);
0075 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QFutureInterfaceBase)
0076 virtual ~QFutureInterfaceBase();
0077
0078
0079 void reportStarted();
0080 void reportFinished();
0081 void reportCanceled();
0082 #ifndef QT_NO_EXCEPTIONS
0083 void reportException(const QException &e);
0084 #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
0085 void reportException(std::exception_ptr e);
0086 #else
0087 void reportException(const std::exception_ptr &e);
0088 #endif
0089 #endif
0090 void reportResultsReady(int beginIndex, int endIndex);
0091
0092 void setRunnable(QRunnable *runnable);
0093 void setThreadPool(QThreadPool *pool);
0094 QThreadPool *threadPool() const;
0095 void setFilterMode(bool enable);
0096 void setProgressRange(int minimum, int maximum);
0097 int progressMinimum() const;
0098 int progressMaximum() const;
0099 bool isProgressUpdateNeeded() const;
0100 void setProgressValue(int progressValue);
0101 int progressValue() const;
0102 void setProgressValueAndText(int progressValue, const QString &progressText);
0103 QString progressText() const;
0104
0105 void setExpectedResultCount(int resultCount);
0106 int expectedResultCount();
0107 int resultCount() const;
0108
0109 bool queryState(State state) const;
0110 bool isRunning() const;
0111 bool isStarted() const;
0112 bool isCanceled() const;
0113 bool isFinished() const;
0114 #if QT_DEPRECATED_SINCE(6, 0)
0115 QT_DEPRECATED_VERSION_X_6_0("Use isSuspending() or isSuspended() instead.")
0116 bool isPaused() const;
0117
0118 QT_DEPRECATED_VERSION_X_6_0("Use setSuspended() instead.")
0119 void setPaused(bool paused) { setSuspended(paused); }
0120
0121 QT_DEPRECATED_VERSION_X_6_0("Use toggleSuspended() instead.")
0122 void togglePaused() { toggleSuspended(); }
0123 #endif
0124 bool isSuspending() const;
0125 bool isSuspended() const;
0126 bool isThrottled() const;
0127 bool isResultReadyAt(int index) const;
0128 bool isValid() const;
0129 int loadState() const;
0130
0131 void cancel();
0132 void cancelAndFinish() { cancel(CancelMode::CancelAndFinish); }
0133 void cancelChain();
0134 void setAddResultsIfCanceledEnabled(bool enable);
0135 bool isAddResultsIfCanceledEnabled() const;
0136
0137 void setSuspended(bool suspend);
0138 void toggleSuspended();
0139 void reportSuspended() const;
0140 void setThrottled(bool enable);
0141
0142 void waitForFinished();
0143 bool waitForNextResult();
0144 void waitForResult(int resultIndex);
0145 void waitForResume();
0146 void suspendIfRequested();
0147
0148 QMutex &mutex() const;
0149 bool hasException() const;
0150 QtPrivate::ExceptionStore &exceptionStore();
0151 QtPrivate::ResultStoreBase &resultStoreBase();
0152 const QtPrivate::ResultStoreBase &resultStoreBase() const;
0153
0154 inline bool operator==(const QFutureInterfaceBase &other) const { return d == other.d; }
0155 inline bool operator!=(const QFutureInterfaceBase &other) const { return d != other.d; }
0156
0157
0158 void swap(QFutureInterfaceBase &other) noexcept;
0159
0160 template<typename T>
0161 static QFutureInterfaceBase get(const QFuture<T> &future);
0162
0163 bool isChainCanceled() const;
0164
0165 protected:
0166
0167 bool refT() const noexcept;
0168 bool derefT() const noexcept;
0169 void reset();
0170 void rethrowPossibleException();
0171 public:
0172
0173 #ifndef QFUTURE_TEST
0174 private:
0175 #endif
0176 friend class QFutureInterfaceBasePrivate;
0177 QFutureInterfaceBasePrivate *d;
0178
0179 private:
0180 friend class QFutureWatcherBase;
0181 friend class QFutureWatcherBasePrivate;
0182
0183 template<typename Function, typename ResultType, typename ParentResultType>
0184 friend class QtPrivate::CompactContinuation;
0185
0186 template<class Function, class ResultType>
0187 friend class QtPrivate::CanceledHandler;
0188
0189 #ifndef QT_NO_EXCEPTIONS
0190 template<class Function, class ResultType>
0191 friend class QtPrivate::FailureHandler;
0192 #endif
0193
0194 friend struct QtPrivate::UnwrapHandler;
0195
0196 #if QT_CORE_REMOVED_SINCE(6, 10)
0197 friend Q_CORE_EXPORT void QtPrivate::watchContinuationImpl(
0198 const QObject *context, QtPrivate::QSlotObjectBase *slotObj, QFutureInterfaceBase &fi);
0199 #endif
0200
0201 template<class T>
0202 friend class QPromise;
0203
0204 protected:
0205 enum class ContinuationType : quint8
0206 {
0207 Unknown,
0208 Then,
0209 OnFailed,
0210 OnCanceled,
0211 };
0212
0213 #if QT_CORE_REMOVED_SINCE(6, 10)
0214 void setContinuation(std::function<void(const QFutureInterfaceBase &)> func);
0215 void setContinuation(std::function<void(const QFutureInterfaceBase &)> func,
0216 QFutureInterfaceBasePrivate *continuationFutureData);
0217 #endif
0218 void setContinuation(std::function<void(const QFutureInterfaceBase &)> func,
0219 void *continuationFutureData, ContinuationType type);
0220 void setContinuation(const QObject *context, std::function<void()> func,
0221 const QVariant &continuationFuture, ContinuationType type);
0222 void cleanContinuation();
0223 void runContinuation() const;
0224
0225 void setLaunchAsync(bool value);
0226 bool launchAsync() const;
0227
0228 bool isRunningOrPending() const;
0229
0230 enum class CancelMode { CancelOnly, CancelAndFinish };
0231 void cancel(CancelMode mode);
0232 void cancelChain(CancelMode mode);
0233 };
0234
0235 inline void swap(QFutureInterfaceBase &lhs, QFutureInterfaceBase &rhs) noexcept
0236 {
0237 lhs.swap(rhs);
0238 }
0239
0240 template <typename T>
0241 class QFutureInterface : public QFutureInterfaceBase
0242 {
0243 public:
0244 QFutureInterface(State initialState = NoState)
0245 : QFutureInterfaceBase(initialState)
0246 {
0247 refT();
0248 }
0249 QFutureInterface(const QFutureInterface &other)
0250 : QFutureInterfaceBase(other)
0251 {
0252 refT();
0253 }
0254 QFutureInterface(const QFutureInterfaceBase &dd) : QFutureInterfaceBase(dd) { refT(); }
0255 QFutureInterface(QFutureInterfaceBase &&dd) noexcept : QFutureInterfaceBase(std::move(dd)) { refT(); }
0256 QFutureInterface &operator=(const QFutureInterface &other)
0257 {
0258 QFutureInterface copy(other);
0259 swap(copy);
0260 return *this;
0261 }
0262 QFutureInterface(QFutureInterface &&other) = default;
0263 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QFutureInterface)
0264
0265 ~QFutureInterface()
0266 {
0267 if (!derefT() && !hasException())
0268 resultStoreBase().template clear<T>();
0269 }
0270
0271 static QFutureInterface canceledResult()
0272 { return QFutureInterface(State(Started | Finished | Canceled)); }
0273
0274 inline QFuture<T> future();
0275
0276 template <typename...Args, std::enable_if_t<std::is_constructible_v<T, Args...>, bool> = true>
0277 inline bool reportAndEmplaceResult(int index, Args&&...args);
0278 inline bool reportResult(const T *result, int index = -1);
0279 inline bool reportAndMoveResult(T &&result, int index = -1);
0280 inline bool reportResult(T &&result, int index = -1);
0281 inline bool reportResult(const T &result, int index = -1);
0282 inline bool reportResults(const QList<T> &results, int beginIndex = -1, int count = -1);
0283 inline bool reportFinished(const T *result);
0284 void reportFinished()
0285 {
0286 QFutureInterfaceBase::reportFinished();
0287 QFutureInterfaceBase::runContinuation();
0288 }
0289
0290 inline const T &resultReference(int index) const;
0291 inline const T *resultPointer(int index) const;
0292 inline QList<T> results();
0293
0294 T takeResult();
0295 #if 0
0296
0297 std::vector<T> takeResults();
0298 #endif
0299
0300 #ifndef QT_NO_EXCEPTIONS
0301 void reportException(const std::exception_ptr &e)
0302 {
0303 if (hasException())
0304 return;
0305
0306 resultStoreBase().template clear<T>();
0307 QFutureInterfaceBase::reportException(e);
0308 }
0309 void reportException(const QException &e)
0310 {
0311 if (hasException())
0312 return;
0313
0314 resultStoreBase().template clear<T>();
0315 QFutureInterfaceBase::reportException(e);
0316 }
0317 #endif
0318 };
0319
0320 template <typename T>
0321 inline bool QFutureInterface<T>::reportResult(const T *result, int index)
0322 {
0323 QMutexLocker<QMutex> locker{&mutex()};
0324 if ((this->queryState(Canceled) && !this->isAddResultsIfCanceledEnabled()) || this->queryState(Finished))
0325 return false;
0326
0327 Q_ASSERT(!hasException());
0328 QtPrivate::ResultStoreBase &store = resultStoreBase();
0329
0330 const int resultCountBefore = store.count();
0331 const int insertIndex = store.addResult<T>(index, result);
0332 if (insertIndex == -1)
0333 return false;
0334 if (store.filterMode()) {
0335 this->reportResultsReady(resultCountBefore, store.count());
0336 } else {
0337 this->reportResultsReady(insertIndex, insertIndex + 1);
0338 }
0339 return true;
0340 }
0341
0342 template<typename T>
0343 template<typename...Args, std::enable_if_t<std::is_constructible_v<T, Args...>, bool>>
0344 bool QFutureInterface<T>::reportAndEmplaceResult(int index, Args&&...args)
0345 {
0346 QMutexLocker<QMutex> locker{&mutex()};
0347 if ((queryState(Canceled) && !isAddResultsIfCanceledEnabled()) || queryState(Finished))
0348 return false;
0349
0350 Q_ASSERT(!hasException());
0351 QtPrivate::ResultStoreBase &store = resultStoreBase();
0352
0353 const int oldResultCount = store.count();
0354 const int insertIndex = store.emplaceResult<T>(index, std::forward<Args>(args)...);
0355
0356 if (insertIndex != -1 && (!store.filterMode() || oldResultCount < store.count()))
0357 reportResultsReady(insertIndex, store.count());
0358 return insertIndex != -1;
0359 }
0360
0361 template<typename T>
0362 bool QFutureInterface<T>::reportAndMoveResult(T &&result, int index)
0363 {
0364 return reportAndEmplaceResult(index, std::move(result));
0365 }
0366
0367 template<typename T>
0368 bool QFutureInterface<T>::reportResult(T &&result, int index)
0369 {
0370 return reportAndMoveResult(std::move(result), index);
0371 }
0372
0373 template <typename T>
0374 inline bool QFutureInterface<T>::reportResult(const T &result, int index)
0375 {
0376 return reportResult(&result, index);
0377 }
0378
0379 template<typename T>
0380 inline bool QFutureInterface<T>::reportResults(const QList<T> &_results, int beginIndex, int count)
0381 {
0382 QMutexLocker<QMutex> locker{&mutex()};
0383 if ((this->queryState(Canceled) && !this->isAddResultsIfCanceledEnabled()) || this->queryState(Finished))
0384 return false;
0385
0386 Q_ASSERT(!hasException());
0387 auto &store = resultStoreBase();
0388
0389 const int resultCountBefore = store.count();
0390 const int insertIndex = store.addResults(beginIndex, &_results, count);
0391 if (insertIndex == -1)
0392 return false;
0393 if (store.filterMode()) {
0394 this->reportResultsReady(resultCountBefore, store.count());
0395 } else {
0396 this->reportResultsReady(insertIndex, insertIndex + _results.size());
0397 }
0398 return true;
0399 }
0400
0401 template <typename T>
0402 inline bool QFutureInterface<T>::reportFinished(const T *result)
0403 {
0404 bool resultReported = false;
0405 if (result)
0406 resultReported = reportResult(result);
0407 reportFinished();
0408 return resultReported;
0409 }
0410
0411 template <typename T>
0412 inline const T &QFutureInterface<T>::resultReference(int index) const
0413 {
0414 Q_ASSERT(!hasException());
0415
0416 QMutexLocker<QMutex> locker{&mutex()};
0417 return resultStoreBase().resultAt(index).template value<T>();
0418 }
0419
0420 template <typename T>
0421 inline const T *QFutureInterface<T>::resultPointer(int index) const
0422 {
0423 Q_ASSERT(!hasException());
0424
0425 QMutexLocker<QMutex> locker{&mutex()};
0426 return resultStoreBase().resultAt(index).template pointer<T>();
0427 }
0428
0429 template <typename T>
0430 inline QList<T> QFutureInterface<T>::results()
0431 {
0432 if (this->isCanceled()) {
0433 rethrowPossibleException();
0434 return QList<T>();
0435 }
0436
0437 QFutureInterfaceBase::waitForResult(-1);
0438
0439 QList<T> res;
0440 QMutexLocker<QMutex> locker{&mutex()};
0441
0442 QtPrivate::ResultIteratorBase it = resultStoreBase().begin();
0443 while (it != resultStoreBase().end()) {
0444 res.append(it.value<T>());
0445 ++it;
0446 }
0447
0448 return res;
0449 }
0450
0451 template<typename T>
0452 T QFutureInterface<T>::takeResult()
0453 {
0454
0455
0456 waitForResult(-1);
0457
0458 Q_ASSERT(isValid());
0459 Q_ASSERT(!hasException());
0460
0461 const QMutexLocker<QMutex> locker{&mutex()};
0462 QtPrivate::ResultIteratorBase position = resultStoreBase().resultAt(0);
0463 T ret(std::move_if_noexcept(position.value<T>()));
0464 reset();
0465 resultStoreBase().template clear<T>();
0466
0467 return ret;
0468 }
0469
0470 #if 0
0471 template<typename T>
0472 std::vector<T> QFutureInterface<T>::takeResults()
0473 {
0474 waitForResult(-1);
0475
0476 Q_ASSERT(isValid());
0477 Q_ASSERT(!hasException());
0478
0479 std::vector<T> res;
0480 res.reserve(resultCount());
0481
0482 const QMutexLocker<QMutex> locker{&mutex()};
0483
0484 QtPrivate::ResultIteratorBase it = resultStoreBase().begin();
0485 for (auto endIt = resultStoreBase().end(); it != endIt; ++it)
0486 res.push_back(std::move_if_noexcept(it.value<T>()));
0487
0488 reset();
0489 resultStoreBase().template clear<T>();
0490
0491 return res;
0492 }
0493 #endif
0494
0495 QT_WARNING_PUSH
0496 QT_WARNING_DISABLE_CLANG("-Wweak-vtables")
0497
0498 template <>
0499 class QFutureInterface<void> : public QFutureInterfaceBase
0500 {
0501 public:
0502 explicit QFutureInterface(State initialState = NoState)
0503 : QFutureInterfaceBase(initialState)
0504 { }
0505
0506 QFutureInterface(const QFutureInterfaceBase &dd) : QFutureInterfaceBase(dd) { }
0507
0508 static QFutureInterface<void> canceledResult()
0509 { return QFutureInterface(State(Started | Finished | Canceled)); }
0510
0511
0512 inline QFuture<void> future();
0513
0514 bool reportResult(const void *, int) { return false; }
0515 bool reportResults(const QList<void> &, int) { return false; }
0516 bool reportFinished(const void *)
0517 {
0518 reportFinished();
0519 return false;
0520 }
0521 void reportFinished()
0522 {
0523 QFutureInterfaceBase::reportFinished();
0524 QFutureInterfaceBase::runContinuation();
0525 }
0526 };
0527
0528 QT_WARNING_POP
0529
0530 template<typename T>
0531 inline void swap(QFutureInterface<T> &a, QFutureInterface<T> &b) noexcept
0532 {
0533 a.swap(b);
0534 }
0535
0536 QT_END_NAMESPACE
0537
0538 #endif