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>
This commit is contained in:
parent
20eabb72de
commit
1005c86c61
@ -53,8 +53,6 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class QFutureWatcher;
|
class QFutureWatcher;
|
||||||
template <>
|
|
||||||
class QFutureWatcher<void>;
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class QFuture
|
class QFuture
|
||||||
@ -63,13 +61,39 @@ public:
|
|||||||
QFuture()
|
QFuture()
|
||||||
: d(QFutureInterface<T>::canceledResult())
|
: d(QFutureInterface<T>::canceledResult())
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
|
||||||
explicit QFuture(QFutureInterface<T> *p) // internal
|
explicit QFuture(QFutureInterface<T> *p) // internal
|
||||||
: d(*p)
|
: 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)
|
#if defined(Q_CLANG_QDOC)
|
||||||
~QFuture() { }
|
~QFuture() { }
|
||||||
QFuture(const QFuture<T> &) { }
|
QFuture(const QFuture<T> &) { }
|
||||||
QFuture<T> & operator=(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
|
#endif
|
||||||
|
|
||||||
bool operator==(const QFuture &other) const { return (d == other.d); }
|
bool operator==(const QFuture &other) const { return (d == other.d); }
|
||||||
@ -95,11 +119,20 @@ public:
|
|||||||
QString progressText() const { return d.progressText(); }
|
QString progressText() const { return d.progressText(); }
|
||||||
void waitForFinished() { d.waitForFinished(); }
|
void waitForFinished() { d.waitForFinished(); }
|
||||||
|
|
||||||
|
template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
|
||||||
inline T result() const;
|
inline T result() const;
|
||||||
|
|
||||||
|
template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
|
||||||
inline T resultAt(int index) const;
|
inline T resultAt(int index) const;
|
||||||
|
|
||||||
|
template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
|
||||||
bool isResultReadyAt(int resultIndex) const { return d.isResultReadyAt(resultIndex); }
|
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(); }
|
QList<T> results() const { return d.results(); }
|
||||||
|
|
||||||
template<class Function>
|
template<class Function>
|
||||||
@ -117,6 +150,9 @@ public:
|
|||||||
class const_iterator
|
class const_iterator
|
||||||
{
|
{
|
||||||
public:
|
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 std::bidirectional_iterator_tag iterator_category;
|
||||||
typedef qptrdiff difference_type;
|
typedef qptrdiff difference_type;
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
@ -203,9 +239,16 @@ public:
|
|||||||
friend class const_iterator;
|
friend class const_iterator;
|
||||||
typedef const_iterator ConstIterator;
|
typedef const_iterator ConstIterator;
|
||||||
|
|
||||||
|
template<class U = T, typename = QtPrivate::EnableForNonVoid<U>>
|
||||||
const_iterator begin() const { return const_iterator(this, 0); }
|
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); }
|
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); }
|
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); }
|
const_iterator constEnd() const { return const_iterator(this, -1); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -213,17 +256,21 @@ private:
|
|||||||
|
|
||||||
public: // Warning: the d pointer is not documented and is considered private.
|
public: // Warning: the d pointer is not documented and is considered private.
|
||||||
// TODO: make this 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
|
inline T QFuture<T>::result() const
|
||||||
{
|
{
|
||||||
d.waitForResult(0);
|
d.waitForResult(0);
|
||||||
return d.resultReference(0);
|
return d.resultReference(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
|
template<typename U, typename>
|
||||||
inline T QFuture<T>::resultAt(int index) const
|
inline T QFuture<T>::resultAt(int index) const
|
||||||
{
|
{
|
||||||
d.waitForResult(index);
|
d.waitForResult(index);
|
||||||
@ -265,80 +312,6 @@ QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QTh
|
|||||||
return promise.future();
|
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()
|
inline QFuture<void> QFutureInterface<void>::future()
|
||||||
{
|
{
|
||||||
return QFuture<void>(this);
|
return QFuture<void>(this);
|
||||||
@ -350,31 +323,7 @@ QFuture<void> qToVoidFuture(const QFuture<T> &future)
|
|||||||
return QFuture<void>(future.d);
|
return QFuture<void>(future.d);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Function>
|
Q_DECLARE_SEQUENTIAL_ITERATOR(Future)
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
@ -66,6 +66,12 @@ enum class Launch { Sync, Async, Inherit };
|
|||||||
|
|
||||||
namespace QtPrivate {
|
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>
|
template<typename F, typename Arg, typename Enable = void>
|
||||||
struct ResultTypeHelper
|
struct ResultTypeHelper
|
||||||
{
|
{
|
||||||
|
@ -110,6 +110,12 @@ private:
|
|||||||
virtual QFutureInterfaceBase &futureInterface() = 0;
|
virtual QFutureInterfaceBase &futureInterface() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace QtPrivate {
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
using EnableForNonVoid = std::enable_if_t<!std::is_same_v<T, void>>;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class QFutureWatcher : public QFutureWatcherBase
|
class QFutureWatcher : public QFutureWatcherBase
|
||||||
{
|
{
|
||||||
@ -124,7 +130,10 @@ public:
|
|||||||
QFuture<T> future() const
|
QFuture<T> future() const
|
||||||
{ return m_future; }
|
{ return m_future; }
|
||||||
|
|
||||||
|
template<typename U = T, typename = QtPrivate::EnableForNonVoid<U>>
|
||||||
T result() const { return m_future.result(); }
|
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); }
|
T resultAt(int index) const { return m_future.resultAt(index); }
|
||||||
|
|
||||||
#ifdef Q_QDOC
|
#ifdef Q_QDOC
|
||||||
@ -180,36 +189,6 @@ Q_INLINE_TEMPLATE void QFutureWatcher<T>::setFuture(const QFuture<T> &_future)
|
|||||||
connectOutputInterface();
|
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
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QFUTUREWATCHER_H
|
#endif // QFUTUREWATCHER_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user