From 1005c86c6101a9cdc5ce37de3fd5bc67505bf8bc Mon Sep 17 00:00:00 2001 From: Sona Kurazyan Date: Wed, 18 Mar 2020 21:41:58 +0100 Subject: [PATCH] Clean-up the duplicate code in QFuture and QFutureWatcher QFuture and QFutureWatcher are specialized to not contain any of result fetching methods, but otherwise they share almost the same implementation with QFuture and QFutureWatcher respectively. This change unifies their implementations to get rid of unnecessary code duplication. Change-Id: I9494ddc58c6db192c66edb988105927da6d61a3b Reviewed-by: Vitaly Fanaskov --- src/corelib/thread/qfuture.h | 159 ++++++++++------------------ src/corelib/thread/qfuture_impl.h | 6 ++ 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 e103cfb5526..dd2f5111e04 100644 --- a/src/corelib/thread/qfuture.h +++ b/src/corelib/thread/qfuture.h @@ -53,8 +53,6 @@ QT_BEGIN_NAMESPACE template class QFutureWatcher; -template <> -class QFutureWatcher; template class QFuture @@ -63,13 +61,39 @@ public: QFuture() : d(QFutureInterface::canceledResult()) { } + + template> explicit QFuture(QFutureInterface *p) // internal : d(*p) { } + + template> + explicit QFuture(QFutureInterfaceBase *p) // internal + : d(*p) + { + } + +#if !defined(Q_CC_XLC) + template> + QFuture(const QFuture &other) : d(other.d) + { + } + + template> + QFuture &operator=(const QFuture &other) + { + d = other.d; + return *this; + } +#endif + #if defined(Q_CLANG_QDOC) ~QFuture() { } QFuture(const QFuture &) { } QFuture & operator=(const QFuture &) { } + + // 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> inline T result() const; + + template> inline T resultAt(int index) const; + + template> bool isResultReadyAt(int resultIndex) const { return d.isResultReadyAt(resultIndex); } - operator T() const { return result(); } + // operator T() + template + operator typename std::enable_if_t, U>() const { return result(); } + + template> QList results() const { return d.results(); } template @@ -117,6 +150,9 @@ public: class const_iterator { public: + static_assert(!std::is_same_v, + "It isn't possible to define QFuture::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> const_iterator begin() const { return const_iterator(this, 0); } + + template> const_iterator constBegin() const { return const_iterator(this, 0); } + + template> const_iterator end() const { return const_iterator(this, -1); } + + template> 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 d; + using QFuturePrivate = + std::conditional_t, QFutureInterfaceBase, QFutureInterface>; + mutable QFuturePrivate d; }; -template +template +template inline T QFuture::result() const { d.waitForResult(0); return d.resultReference(0); } -template +template +template inline T QFuture::resultAt(int index) const { d.waitForResult(index); @@ -265,80 +312,6 @@ QFuture::template ResultType> QFuture::then(QTh return promise.future(); } -Q_DECLARE_SEQUENTIAL_ITERATOR(Future) - -template <> -class QFuture -{ -public: - QFuture() - : d(QFutureInterface::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 - QFuture(const QFuture &other) - : d(other.d) - { } - - template - QFuture &operator=(const QFuture &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 - using ResultType = typename QtPrivate::ResultTypeHelper::ResultType; - - template - QFuture> then(Function &&function); - - template - QFuture> then(QtFuture::Launch policy, Function &&function); - - template - QFuture> then(QThreadPool *pool, Function &&function); - -private: - friend class QFutureWatcher; - -#ifdef QFUTURE_TEST -public: -#endif - mutable QFutureInterfaceBase d; - - template - friend class QtPrivate::Continuation; -}; - inline QFuture QFutureInterface::future() { return QFuture(this); @@ -350,31 +323,7 @@ QFuture qToVoidFuture(const QFuture &future) return QFuture(future.d); } -template -QFuture::ResultType> QFuture::then(Function &&function) -{ - return then(QtFuture::Launch::Sync, std::forward(function)); -} - -template -QFuture::ResultType> QFuture::then(QtFuture::Launch policy, - Function &&function) -{ - QFutureInterface> promise(QFutureInterfaceBase::State::Pending); - QtPrivate::Continuation, void>::create( - std::forward(function), this, promise, policy); - return promise.future(); -} - -template -QFuture::ResultType> QFuture::then(QThreadPool *pool, - Function &&function) -{ - QFutureInterface> promise(QFutureInterfaceBase::State::Pending); - QtPrivate::Continuation, void>::create( - std::forward(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 eed7828c358..20ee7e4f338 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 +using EnableForVoid = std::enable_if_t>; + +template +using EnableForNonVoid = std::enable_if_t>; + template struct ResultTypeHelper { diff --git a/src/corelib/thread/qfuturewatcher.h b/src/corelib/thread/qfuturewatcher.h index fb7dd304997..214dc37f01f 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 +using EnableForNonVoid = std::enable_if_t>; +} + template class QFutureWatcher : public QFutureWatcherBase { @@ -124,7 +130,10 @@ public: QFuture future() const { return m_future; } + template> T result() const { return m_future.result(); } + + template> T resultAt(int index) const { return m_future.resultAt(index); } #ifdef Q_QDOC @@ -180,36 +189,6 @@ Q_INLINE_TEMPLATE void QFutureWatcher::setFuture(const QFuture &_future) connectOutputInterface(); } -template <> -class QFutureWatcher : public QFutureWatcherBase -{ -public: - explicit QFutureWatcher(QObject *_parent = nullptr) - : QFutureWatcherBase(_parent) - { } - ~QFutureWatcher() - { disconnectOutputInterface(); } - - void setFuture(const QFuture &future); - QFuture future() const - { return m_future; } - -private: - QFuture m_future; - const QFutureInterfaceBase &futureInterface() const override { return m_future.d; } - QFutureInterfaceBase &futureInterface() override { return m_future.d; } -}; - -Q_INLINE_TEMPLATE void QFutureWatcher::setFuture(const QFuture &_future) -{ - if (_future == m_future) - return; - - disconnectOutputInterface(true); - m_future = _future; - connectOutputInterface(); -} - QT_END_NAMESPACE #endif // QFUTUREWATCHER_H