summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread
diff options
context:
space:
mode:
authorSona Kurazyan <sona.kurazyan@qt.io>2020-03-18 21:41:58 +0100
committerSona Kurazyan <sona.kurazyan@qt.io>2020-03-23 16:47:47 +0100
commit1005c86c6101a9cdc5ce37de3fd5bc67505bf8bc (patch)
treeed9fdd027c5401147e5a5360d12d755e18093233 /src/corelib/thread
parent20eabb72de94ddcef3c36b5cad0ce88944d42f8c (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.h159
-rw-r--r--src/corelib/thread/qfuture_impl.h6
-rw-r--r--src/corelib/thread/qfuturewatcher.h39
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