Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:07:24

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 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         /*! \internal
0217 
0218             Advances the iterator index \a idx \a n steps, waits for the
0219             result at the target index, and returns the target index.
0220 
0221             The index may be -1, indicating the end iterator, either
0222             as the argument or as the return value. The end iterator
0223             may be decremented.
0224 
0225             The caller is responsible for not advancing the iterator
0226             before begin() or past end(), with the exception that
0227             attempting to advance a non-end iterator past end() for
0228             a running future is allowed and will return the end iterator.
0229 
0230             Note that n == 0 is valid and will wait for the result
0231             at the given index.
0232         */
0233         int advanceIndex(int idx, int n) const
0234         {
0235             // The end iterator can be decremented, leave as-is for other cases
0236             if (idx == -1 && n >= 0)
0237                 return idx;
0238 
0239             // Special case for decrementing the end iterator: wait for
0240             // finished to get the total result count.
0241             if (idx == -1 && future->isRunning())
0242                 future->d.waitForFinished();
0243 
0244             // Wait for result at target index
0245             const int targetIndex = (idx == -1) ? future->resultCount() + n : idx + n;
0246             future->d.waitForResult(targetIndex);
0247 
0248             // After waiting there is either a result or the end was reached
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 }  // namespace QtPrivate
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 // Q_QDOC
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 // QT_DEPRECATED_SINCE(6, 10)
0537 
0538 } // namespace QtFuture
0539 
0540 Q_DECLARE_SEQUENTIAL_ITERATOR(Future)
0541 
0542 QT_END_NAMESPACE
0543 
0544 Q_DECLARE_METATYPE_TEMPLATE_1ARG(QFuture)
0545 
0546 #endif // QFUTURE_H