diff options
author | Sona Kurazyan <sona.kurazyan@qt.io> | 2020-03-18 21:41:58 +0100 |
---|---|---|
committer | Sona Kurazyan <sona.kurazyan@qt.io> | 2020-03-23 16:47:47 +0100 |
commit | 1005c86c6101a9cdc5ce37de3fd5bc67505bf8bc (patch) | |
tree | ed9fdd027c5401147e5a5360d12d755e18093233 /src/corelib/thread | |
parent | 20eabb72de94ddcef3c36b5cad0ce88944d42f8c (diff) |
Clean-up the duplicate code in QFuture and QFutureWatcher
QFuture<void> and QFutureWatcher<void> are specialized to not contain
any of result fetching methods, but otherwise they share almost the same
implementation with QFuture<T> and QFutureWatcher<T> respectively.
This change unifies their implementations to get rid of unnecessary code
duplication.
Change-Id: I9494ddc58c6db192c66edb988105927da6d61a3b
Reviewed-by: Vitaly Fanaskov <vitaly.fanaskov@qt.io>
Diffstat (limited to 'src/corelib/thread')
-rw-r--r-- | src/corelib/thread/qfuture.h | 159 | ||||
-rw-r--r-- | src/corelib/thread/qfuture_impl.h | 6 | ||||
-rw-r--r-- | src/corelib/thread/qfuturewatcher.h | 39 |
3 files changed, 69 insertions, 135 deletions
diff --git a/src/corelib/thread/qfuture.h b/src/corelib/thread/qfuture.h index e103cfb552..dd2f5111e0 100644 --- a/src/corelib/thread/qfuture.h +++ b/src/corelib/thread/qfuture.h @@ -53,8 +53,6 @@ QT_BEGIN_NAMESPACE template <typename T> class QFutureWatcher; -template <> -class QFutureWatcher<void>; template <typename T> class QFuture @@ -63,13 +61,39 @@ 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); } @@ -95,11 +119,20 @@ 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<class Function> @@ -117,6 +150,9 @@ public: 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; @@ -203,9 +239,16 @@ 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: @@ -213,17 +256,21 @@ private: public: // Warning: the d pointer is not documented and is considered private. // TODO: make this private - mutable QFutureInterface<T> d; + using QFuturePrivate = + std::conditional_t<std::is_same_v<T, void>, QFutureInterfaceBase, QFutureInterface<T>>; + 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); @@ -265,80 +312,6 @@ QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QTh return promise.future(); } -Q_DECLARE_SEQUENTIAL_ITERATOR(Future) - -template <> -class QFuture<void> -{ -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(); } - - 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(); } - - bool isStarted() const { return d.isStarted(); } - bool isFinished() const { return d.isFinished(); } - bool isRunning() const { return d.isRunning(); } - - 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(); } - - template<class Function> - using ResultType = typename QtPrivate::ResultTypeHelper<Function, void>::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); - -private: - friend class QFutureWatcher<void>; - -#ifdef QFUTURE_TEST -public: -#endif - mutable QFutureInterfaceBase d; - - template<typename Function, typename ResultType, typename ParentResultType> - friend class QtPrivate::Continuation; -}; - inline QFuture<void> QFutureInterface<void>::future() { return QFuture<void>(this); @@ -350,31 +323,7 @@ QFuture<void> qToVoidFuture(const QFuture<T> &future) return QFuture<void>(future.d); } -template<class Function> -QFuture<QFuture<void>::ResultType<Function>> QFuture<void>::then(Function &&function) -{ - return then(QtFuture::Launch::Sync, std::forward<Function>(function)); -} - -template<class Function> -QFuture<QFuture<void>::ResultType<Function>> QFuture<void>::then(QtFuture::Launch policy, - Function &&function) -{ - QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending); - QtPrivate::Continuation<Function, ResultType<Function>, void>::create( - std::forward<Function>(function), this, promise, policy); - return promise.future(); -} - -template<class Function> -QFuture<QFuture<void>::ResultType<Function>> QFuture<void>::then(QThreadPool *pool, - Function &&function) -{ - QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending); - QtPrivate::Continuation<Function, ResultType<Function>, void>::create( - std::forward<Function>(function), this, promise, pool); - return promise.future(); -} +Q_DECLARE_SEQUENTIAL_ITERATOR(Future) QT_END_NAMESPACE diff --git a/src/corelib/thread/qfuture_impl.h b/src/corelib/thread/qfuture_impl.h index eed7828c35..20ee7e4f33 100644 --- a/src/corelib/thread/qfuture_impl.h +++ b/src/corelib/thread/qfuture_impl.h @@ -66,6 +66,12 @@ enum class Launch { Sync, Async, Inherit }; namespace QtPrivate { +template<class T> +using EnableForVoid = std::enable_if_t<std::is_same_v<T, void>>; + +template<class T> +using EnableForNonVoid = std::enable_if_t<!std::is_same_v<T, void>>; + template<typename F, typename Arg, typename Enable = void> struct ResultTypeHelper { diff --git a/src/corelib/thread/qfuturewatcher.h b/src/corelib/thread/qfuturewatcher.h index fb7dd30499..214dc37f01 100644 --- a/src/corelib/thread/qfuturewatcher.h +++ b/src/corelib/thread/qfuturewatcher.h @@ -110,6 +110,12 @@ private: virtual QFutureInterfaceBase &futureInterface() = 0; }; +namespace QtPrivate { + +template<class T> +using EnableForNonVoid = std::enable_if_t<!std::is_same_v<T, void>>; +} + template <typename T> class QFutureWatcher : public QFutureWatcherBase { @@ -124,7 +130,10 @@ public: QFuture<T> future() const { return m_future; } + template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T result() const { return m_future.result(); } + + template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T resultAt(int index) const { return m_future.resultAt(index); } #ifdef Q_QDOC @@ -180,36 +189,6 @@ Q_INLINE_TEMPLATE void QFutureWatcher<T>::setFuture(const QFuture<T> &_future) connectOutputInterface(); } -template <> -class QFutureWatcher<void> : public QFutureWatcherBase -{ -public: - explicit QFutureWatcher(QObject *_parent = nullptr) - : QFutureWatcherBase(_parent) - { } - ~QFutureWatcher() - { disconnectOutputInterface(); } - - void setFuture(const QFuture<void> &future); - QFuture<void> future() const - { return m_future; } - -private: - QFuture<void> m_future; - const QFutureInterfaceBase &futureInterface() const override { return m_future.d; } - QFutureInterfaceBase &futureInterface() override { return m_future.d; } -}; - -Q_INLINE_TEMPLATE void QFutureWatcher<void>::setFuture(const QFuture<void> &_future) -{ - if (_future == m_future) - return; - - disconnectOutputInterface(true); - m_future = _future; - connectOutputInterface(); -} - QT_END_NAMESPACE #endif // QFUTUREWATCHER_H |