Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-16 09:03:42

0001 // Copyright (C) 2016 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
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) // internal
0037         : d(*p)
0038     { }
0039 
0040     template<typename U = T, typename = QtPrivate::EnableForVoid<U>>
0041     explicit QFuture(QFutureInterfaceBase *p) // internal
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     // TODO: Enable and make it return a QList, when QList is fixed to support move-only types
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 const_iterator &operator++()
0187         { index = advanceIndex(index, 1); return *this; }
0188         inline const_iterator &operator--()
0189         { index = advanceIndex(index, -1); return *this; }
0190         inline const_iterator operator++(int)
0191         {
0192             const_iterator r = *this;
0193             index = advanceIndex(index, 1);
0194             return r;
0195         }
0196         inline const_iterator operator--(int)
0197         {
0198             const_iterator r = *this;
0199             index = advanceIndex(index, -1);
0200             return r;
0201         }
0202         inline const_iterator operator+(int j) const
0203         { return const_iterator(future, advanceIndex(index, j)); }
0204         inline const_iterator operator-(int j) const
0205         { return const_iterator(future, advanceIndex(index, -j)); }
0206         inline const_iterator &operator+=(int j)
0207         { index = advanceIndex(index, j); return *this; }
0208         inline const_iterator &operator-=(int j)
0209         { index = advanceIndex(index, -j); return *this; }
0210         friend inline const_iterator operator+(int j, const_iterator k)
0211         { return const_iterator(k.future, k.advanceIndex(k.index, j)); }
0212 
0213     private:
0214         friend bool comparesEqual(const const_iterator &lhs, const const_iterator &rhs) noexcept
0215         {
0216             return lhs.index == rhs.index;
0217         }
0218         Q_DECLARE_EQUALITY_COMPARABLE(const_iterator)
0219 
0220         /*! \internal
0221 
0222             Advances the iterator index \a idx \a n steps, waits for the
0223             result at the target index, and returns the target index.
0224 
0225             The index may be -1, indicating the end iterator, either
0226             as the argument or as the return value. The end iterator
0227             may be decremented.
0228 
0229             The caller is responsible for not advancing the iterator
0230             before begin() or past end(), with the exception that
0231             attempting to advance a non-end iterator past end() for
0232             a running future is allowed and will return the end iterator.
0233 
0234             Note that n == 0 is valid and will wait for the result
0235             at the given index.
0236         */
0237         int advanceIndex(int idx, int n) const
0238         {
0239             // The end iterator can be decremented, leave as-is for other cases
0240             if (idx == -1 && n >= 0)
0241                 return idx;
0242 
0243             // Special case for decrementing the end iterator: wait for
0244             // finished to get the total result count.
0245             if (idx == -1 && future->isRunning())
0246                 future->d.waitForFinished();
0247 
0248             // Wait for result at target index
0249             const int targetIndex = (idx == -1) ? future->resultCount() + n : idx + n;
0250             future->d.waitForResult(targetIndex);
0251 
0252             // After waiting there is either a result or the end was reached
0253             return (targetIndex < future->resultCount()) ? targetIndex : -1;
0254         }
0255 
0256         QFuture const * future;
0257         int index;
0258     };
0259     friend class const_iterator;
0260     typedef const_iterator ConstIterator;
0261 
0262     template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
0263     const_iterator begin() const { return  const_iterator(this, 0); }
0264 
0265     template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
0266     const_iterator constBegin() const { return  const_iterator(this, 0); }
0267 
0268     template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
0269     const_iterator end() const { return const_iterator(this, -1); }
0270 
0271     template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
0272     const_iterator constEnd() const { return const_iterator(this, -1); }
0273 
0274 private:
0275     friend class QFutureWatcher<T>;
0276 
0277     template<class U>
0278     friend class QFuture;
0279 
0280     friend class QFutureInterfaceBase;
0281 
0282     template<class Function, class ResultType, class ParentResultType>
0283     friend class QtPrivate::CompactContinuation;
0284 
0285     template<class Function, class ResultType>
0286     friend class QtPrivate::CanceledHandler;
0287 
0288 #ifndef QT_NO_EXCEPTIONS
0289     template<class Function, class ResultType>
0290     friend class QtPrivate::FailureHandler;
0291 #endif
0292 
0293     template<typename ResultType>
0294     friend struct QtPrivate::WhenAnyContext;
0295 
0296     friend struct QtPrivate::UnwrapHandler;
0297 
0298     using QFuturePrivate =
0299             std::conditional_t<std::is_same_v<T, void>, QFutureInterfaceBase, QFutureInterface<T>>;
0300 
0301 #ifdef QFUTURE_TEST
0302 public:
0303 #endif
0304     mutable QFuturePrivate d;
0305 };
0306 
0307 template<typename T>
0308 template<typename U, typename>
0309 inline T QFuture<T>::result() const
0310 {
0311     d.waitForResult(0);
0312     return d.resultReference(0);
0313 }
0314 
0315 template<typename T>
0316 template<typename U, typename>
0317 inline T QFuture<T>::resultAt(int index) const
0318 {
0319     d.waitForResult(index);
0320     return d.resultReference(index);
0321 }
0322 
0323 template <typename T>
0324 inline QFuture<T> QFutureInterface<T>::future()
0325 {
0326     return QFuture<T>(this);
0327 }
0328 
0329 template<class T>
0330 template<class Function>
0331 QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(Function &&function)
0332 {
0333     return then(QtFuture::Launch::Sync, std::forward<Function>(function));
0334 }
0335 
0336 template<class T>
0337 template<class Function>
0338 QFuture<typename QFuture<T>::template ResultType<Function>>
0339 QFuture<T>::then(QtFuture::Launch policy, Function &&function)
0340 {
0341     QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
0342     QtPrivate::CompactContinuation<std::decay_t<Function>, ResultType<Function>, T>::create(
0343             std::forward<Function>(function), this, promise, policy);
0344     return promise.future();
0345 }
0346 
0347 template<class T>
0348 template<class Function>
0349 QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QThreadPool *pool,
0350                                                                              Function &&function)
0351 {
0352     QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
0353     QtPrivate::CompactContinuation<std::decay_t<Function>, ResultType<Function>, T>::create(
0354             std::forward<Function>(function), this, promise, pool);
0355     return promise.future();
0356 }
0357 
0358 template<class T>
0359 template<class Function>
0360 QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QObject *context,
0361                                                                              Function &&function)
0362 {
0363     QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
0364     QtPrivate::CompactContinuation<std::decay_t<Function>, ResultType<Function>, T>::create(
0365             std::forward<Function>(function), this, promise, context);
0366     return promise.future();
0367 }
0368 
0369 #ifndef QT_NO_EXCEPTIONS
0370 template<class T>
0371 template<class Function, typename>
0372 QFuture<T> QFuture<T>::onFailed(Function &&handler)
0373 {
0374     QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
0375     QtPrivate::FailureHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
0376                                                                  this, promise);
0377     return promise.future();
0378 }
0379 
0380 template<class T>
0381 template<class Function, typename>
0382 QFuture<T> QFuture<T>::onFailed(QObject *context, Function &&handler)
0383 {
0384     QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
0385     QtPrivate::FailureHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
0386                                                                  this, promise, context);
0387     return promise.future();
0388 }
0389 
0390 #endif
0391 
0392 template<class T>
0393 template<class Function, typename>
0394 QFuture<T> QFuture<T>::onCanceled(Function &&handler)
0395 {
0396     QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
0397     QtPrivate::CanceledHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
0398                                                                   this, promise);
0399     return promise.future();
0400 }
0401 
0402 template<class T>
0403 template<class Function, typename>
0404 QFuture<T> QFuture<T>::onCanceled(QObject *context, Function &&handler)
0405 {
0406     QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
0407     QtPrivate::CanceledHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
0408                                                                   this, promise, context);
0409     return promise.future();
0410 }
0411 
0412 template<class T>
0413 template<class U, typename>
0414 auto QFuture<T>::unwrap()
0415 {
0416     if constexpr (QtPrivate::isQFutureV<typename QtPrivate::Future<T>::type>)
0417         return QtPrivate::UnwrapHandler::unwrapImpl(this).unwrap();
0418     else
0419         return QtPrivate::UnwrapHandler::unwrapImpl(this);
0420 }
0421 
0422 inline QFuture<void> QFutureInterface<void>::future()
0423 {
0424     return QFuture<void>(this);
0425 }
0426 
0427 template<typename T>
0428 QFutureInterfaceBase QFutureInterfaceBase::get(const QFuture<T> &future)
0429 {
0430     return future.d;
0431 }
0432 
0433 namespace QtPrivate
0434 {
0435 
0436 template<typename T>
0437 struct MetaTypeQFutureHelper<QFuture<T>>
0438 {
0439     static bool registerConverter() {
0440         if constexpr (std::is_same_v<T, void>) {
0441             return false;
0442         } else {
0443             return QMetaType::registerConverter<QFuture<T>, QFuture<void>>(
0444                     [](const QFuture<T> &future) { return QFuture<void>(future); });
0445         }
0446     }
0447 };
0448 
0449 }  // namespace QtPrivate
0450 
0451 namespace QtFuture {
0452 
0453 #ifndef Q_QDOC
0454 
0455 template<typename OutputSequence, typename InputIt,
0456          typename ValueType = typename std::iterator_traits<InputIt>::value_type,
0457          std::enable_if_t<std::conjunction_v<QtPrivate::IsForwardIterable<InputIt>,
0458                                              QtPrivate::IsRandomAccessible<OutputSequence>,
0459                                              QtPrivate::isQFuture<ValueType>>,
0460                           int> = 0>
0461 QFuture<OutputSequence> whenAll(InputIt first, InputIt last)
0462 {
0463     return QtPrivate::whenAllImpl<OutputSequence, InputIt, ValueType>(first, last);
0464 }
0465 
0466 template<typename InputIt, typename ValueType = typename std::iterator_traits<InputIt>::value_type,
0467          std::enable_if_t<std::conjunction_v<QtPrivate::IsForwardIterable<InputIt>,
0468                                              QtPrivate::isQFuture<ValueType>>,
0469                           int> = 0>
0470 QFuture<QList<ValueType>> whenAll(InputIt first, InputIt last)
0471 {
0472     return QtPrivate::whenAllImpl<QList<ValueType>, InputIt, ValueType>(first, last);
0473 }
0474 
0475 template<typename OutputSequence, typename... Futures,
0476          std::enable_if_t<std::conjunction_v<QtPrivate::IsRandomAccessible<OutputSequence>,
0477                                              QtPrivate::NotEmpty<Futures...>,
0478                                              QtPrivate::isQFuture<std::decay_t<Futures>>...>,
0479                           int> = 0>
0480 QFuture<OutputSequence> whenAll(Futures &&... futures)
0481 {
0482     return QtPrivate::whenAllImpl<OutputSequence, Futures...>(std::forward<Futures>(futures)...);
0483 }
0484 
0485 template<typename... Futures,
0486          std::enable_if_t<std::conjunction_v<QtPrivate::NotEmpty<Futures...>,
0487                                              QtPrivate::isQFuture<std::decay_t<Futures>>...>,
0488                           int> = 0>
0489 QFuture<QList<std::variant<std::decay_t<Futures>...>>> whenAll(Futures &&... futures)
0490 {
0491     return QtPrivate::whenAllImpl<QList<std::variant<std::decay_t<Futures>...>>, Futures...>(
0492             std::forward<Futures>(futures)...);
0493 }
0494 
0495 template<typename InputIt, typename ValueType = typename std::iterator_traits<InputIt>::value_type,
0496          std::enable_if_t<std::conjunction_v<QtPrivate::IsForwardIterable<InputIt>,
0497                                              QtPrivate::isQFuture<ValueType>>,
0498                           int> = 0>
0499 QFuture<WhenAnyResult<typename QtPrivate::Future<ValueType>::type>> whenAny(InputIt first,
0500                                                                             InputIt last)
0501 {
0502     return QtPrivate::whenAnyImpl<InputIt, ValueType>(first, last);
0503 }
0504 
0505 template<typename... Futures,
0506          std::enable_if_t<std::conjunction_v<QtPrivate::NotEmpty<Futures...>,
0507                                              QtPrivate::isQFuture<std::decay_t<Futures>>...>,
0508                           int> = 0>
0509 QFuture<std::variant<std::decay_t<Futures>...>> whenAny(Futures &&... futures)
0510 {
0511     return QtPrivate::whenAnyImpl(std::forward<Futures>(futures)...);
0512 }
0513 
0514 #else
0515 
0516 template<typename OutputSequence, typename InputIt>
0517 QFuture<OutputSequence> whenAll(InputIt first, InputIt last);
0518 
0519 template<typename OutputSequence, typename... Futures>
0520 QFuture<OutputSequence> whenAll(Futures &&... futures);
0521 
0522 template<typename T, typename InputIt>
0523 QFuture<QtFuture::WhenAnyResult<T>> whenAny(InputIt first, InputIt last);
0524 
0525 template<typename... Futures>
0526 QFuture<std::variant<std::decay_t<Futures>...>> whenAny(Futures &&... futures);
0527 
0528 #endif // Q_QDOC
0529 
0530 #if QT_DEPRECATED_SINCE(6, 10)
0531 #if defined(Q_QDOC)
0532 static QFuture<void> makeReadyFuture()
0533 #else
0534 template<typename T = void>
0535 QT_DEPRECATED_VERSION_X(6, 10, "Use makeReadyVoidFuture() instead.")
0536 static QFuture<T> makeReadyFuture()
0537 #endif
0538 {
0539     return makeReadyVoidFuture();
0540 }
0541 #endif // QT_DEPRECATED_SINCE(6, 10)
0542 
0543 } // namespace QtFuture
0544 
0545 Q_DECLARE_SEQUENTIAL_ITERATOR(Future)
0546 
0547 QT_END_NAMESPACE
0548 
0549 Q_DECLARE_METATYPE_TEMPLATE_1ARG(QFuture)
0550 
0551 #endif // QFUTURE_H