diff options
Diffstat (limited to 'src/corelib/thread/qfuture.h')
-rw-r--r-- | src/corelib/thread/qfuture.h | 198 |
1 files changed, 139 insertions, 59 deletions
diff --git a/src/corelib/thread/qfuture.h b/src/corelib/thread/qfuture.h index d3135510b3..bfca16b641 100644 --- a/src/corelib/thread/qfuture.h +++ b/src/corelib/thread/qfuture.h @@ -45,30 +45,62 @@ #include <QtCore/qfutureinterface.h> #include <QtCore/qstring.h> +#include <QtCore/qfuture_impl.h> + +#include <type_traits> +#include <vector> + QT_REQUIRE_CONFIG(future); QT_BEGIN_NAMESPACE - template <typename T> class QFutureWatcher; -template <> -class QFutureWatcher<void>; template <typename T> class QFuture { + static_assert (std::is_copy_constructible_v<T> + || std::is_move_constructible_v<T> + || std::is_same_v<T, void>, + "Type with copy or move constructors or type void is required"); public: QFuture() : d(QFutureInterface<T>::canceledResult()) { } + + template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> explicit QFuture(QFutureInterface<T> *p) // internal : d(*p) { } + + template<typename U = T, typename = QtPrivate::EnableForVoid<U>> + explicit QFuture(QFutureInterfaceBase *p) // internal + : d(*p) + { + } + +#if !defined(Q_CC_XLC) + template<typename U, typename V = T, typename = QtPrivate::EnableForVoid<V>> + QFuture(const QFuture<U> &other) : d(other.d) + { + } + + template<typename U, typename V = T, typename = QtPrivate::EnableForVoid<V>> + QFuture<void> &operator=(const QFuture<U> &other) + { + d = other.d; + return *this; + } +#endif + #if defined(Q_CLANG_QDOC) ~QFuture() { } QFuture(const QFuture<T> &) { } QFuture<T> & operator=(const QFuture<T> &) { } + + // This is required to allow QDoc to find the declaration of operator T(). + operator T() const; #endif bool operator==(const QFuture &other) const { return (d == other.d); } @@ -94,16 +126,54 @@ public: QString progressText() const { return d.progressText(); } void waitForFinished() { d.waitForFinished(); } + template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> inline T result() const; + + template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> inline T resultAt(int index) const; + + template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> bool isResultReadyAt(int resultIndex) const { return d.isResultReadyAt(resultIndex); } - operator T() const { return result(); } + // operator T() + template<typename U = T> + operator typename std::enable_if_t<!std::is_same_v<U, void>, U>() const { return result(); } + + template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QList<T> results() const { return d.results(); } + template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> + T takeResult() { return d.takeResult(); } + + template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> + std::vector<T> takeResults() { return d.takeResults(); } + + bool isValid() const { return d.isValid(); } + + template<class Function> + using ResultType = typename QtPrivate::ResultTypeHelper<Function, T>::ResultType; + + template<class Function> + QFuture<ResultType<Function>> then(Function &&function); + + template<class Function> + QFuture<ResultType<Function>> then(QtFuture::Launch policy, Function &&function); + + template<class Function> + QFuture<ResultType<Function>> then(QThreadPool *pool, Function &&function); + +#ifndef QT_NO_EXCEPTIONS + template<class Function, + typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>> + QFuture<T> onFailed(Function &&handler); +#endif + class const_iterator { public: + static_assert(!std::is_same_v<T, void>, + "It isn't possible to define QFuture<void>::const_iterator"); + typedef std::bidirectional_iterator_tag iterator_category; typedef qptrdiff difference_type; typedef T value_type; @@ -190,26 +260,51 @@ public: friend class const_iterator; typedef const_iterator ConstIterator; + template<class U = T, typename = QtPrivate::EnableForNonVoid<U>> const_iterator begin() const { return const_iterator(this, 0); } + + template<class U = T, typename = QtPrivate::EnableForNonVoid<U>> const_iterator constBegin() const { return const_iterator(this, 0); } + + template<class U = T, typename = QtPrivate::EnableForNonVoid<U>> const_iterator end() const { return const_iterator(this, -1); } + + template<class U = T, typename = QtPrivate::EnableForNonVoid<U>> const_iterator constEnd() const { return const_iterator(this, -1); } private: friend class QFutureWatcher<T>; -public: // Warning: the d pointer is not documented and is considered private. - mutable QFutureInterface<T> d; + template<class U> + friend class QFuture; + + template<class Function, class ResultType, class ParentResultType> + friend class QtPrivate::Continuation; + +#ifndef QT_NO_EXCEPTIONS + template<class Function, class ResultType> + friend class QtPrivate::FailureHandler; +#endif + + using QFuturePrivate = + std::conditional_t<std::is_same_v<T, void>, QFutureInterfaceBase, QFutureInterface<T>>; + +#ifdef QFUTURE_TEST +public: +#endif + mutable QFuturePrivate d; }; -template <typename T> +template<typename T> +template<typename U, typename> inline T QFuture<T>::result() const { d.waitForResult(0); return d.resultReference(0); } -template <typename T> +template<typename T> +template<typename U, typename> inline T QFuture<T>::resultAt(int index) const { d.waitForResult(index); @@ -222,64 +317,47 @@ inline QFuture<T> QFutureInterface<T>::future() return QFuture<T>(this); } -Q_DECLARE_SEQUENTIAL_ITERATOR(Future) - -template <> -class QFuture<void> +template<class T> +template<class Function> +QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(Function &&function) { -public: - QFuture() - : d(QFutureInterface<void>::canceledResult()) - { } - explicit QFuture(QFutureInterfaceBase *p) // internal - : d(*p) - { } - - bool operator==(const QFuture &other) const { return (d == other.d); } - bool operator!=(const QFuture &other) const { return (d != other.d); } - -#if !defined(Q_CC_XLC) - template <typename T> - QFuture(const QFuture<T> &other) - : d(other.d) - { } - - template <typename T> - QFuture<void> &operator=(const QFuture<T> &other) - { - d = other.d; - return *this; - } -#endif - - void cancel() { d.cancel(); } - bool isCanceled() const { return d.isCanceled(); } + return then(QtFuture::Launch::Sync, std::forward<Function>(function)); +} - void setPaused(bool paused) { d.setPaused(paused); } - bool isPaused() const { return d.isPaused(); } - void pause() { setPaused(true); } - void resume() { setPaused(false); } - void togglePaused() { d.togglePaused(); } +template<class T> +template<class Function> +QFuture<typename QFuture<T>::template ResultType<Function>> +QFuture<T>::then(QtFuture::Launch policy, Function &&function) +{ + QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending); + QtPrivate::Continuation<Function, ResultType<Function>, T>::create( + std::forward<Function>(function), this, promise, policy); + return promise.future(); +} - bool isStarted() const { return d.isStarted(); } - bool isFinished() const { return d.isFinished(); } - bool isRunning() const { return d.isRunning(); } +template<class T> +template<class Function> +QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QThreadPool *pool, + Function &&function) +{ + QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending); + QtPrivate::Continuation<Function, ResultType<Function>, T>::create( + std::forward<Function>(function), this, promise, pool); + return promise.future(); +} - int resultCount() const { return d.resultCount(); } - int progressValue() const { return d.progressValue(); } - int progressMinimum() const { return d.progressMinimum(); } - int progressMaximum() const { return d.progressMaximum(); } - QString progressText() const { return d.progressText(); } - void waitForFinished() { d.waitForFinished(); } +#ifndef QT_NO_EXCEPTIONS -private: - friend class QFutureWatcher<void>; +template<class T> +template<class Function, typename> +QFuture<T> QFuture<T>::onFailed(Function &&handler) +{ + QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending); + QtPrivate::FailureHandler<Function, T>::create(std::forward<Function>(handler), this, promise); + return promise.future(); +} -#ifdef QFUTURE_TEST -public: #endif - mutable QFutureInterfaceBase d; -}; inline QFuture<void> QFutureInterface<void>::future() { @@ -292,6 +370,8 @@ QFuture<void> qToVoidFuture(const QFuture<T> &future) return QFuture<void>(future.d); } +Q_DECLARE_SEQUENTIAL_ITERATOR(Future) + QT_END_NAMESPACE #endif // QFUTURE_H |