diff options
-rw-r--r-- | src/corelib/thread/qfutureinterface.cpp | 7 | ||||
-rw-r--r-- | src/corelib/thread/qfutureinterface.h | 10 | ||||
-rw-r--r-- | src/corelib/thread/qpromise.h | 28 | ||||
-rw-r--r-- | src/corelib/thread/qpromise.qdoc | 5 | ||||
-rw-r--r-- | tests/auto/corelib/thread/qfuture/tst_qfuture.cpp | 12 | ||||
-rw-r--r-- | tests/auto/corelib/thread/qpromise/tst_qpromise.cpp | 18 |
6 files changed, 59 insertions, 21 deletions
diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp index 1785815cf3..a625e05aac 100644 --- a/src/corelib/thread/qfutureinterface.cpp +++ b/src/corelib/thread/qfutureinterface.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -545,6 +545,11 @@ QFutureInterfaceBase &QFutureInterfaceBase::operator=(const QFutureInterfaceBase return *this; } +void QFutureInterfaceBase::swap(QFutureInterfaceBase &other) noexcept +{ + qSwap(d, other.d); +} + bool QFutureInterfaceBase::refT() const { return d->refCount.refT(); diff --git a/src/corelib/thread/qfutureinterface.h b/src/corelib/thread/qfutureinterface.h index 2e15cbb013..047d2eb2d3 100644 --- a/src/corelib/thread/qfutureinterface.h +++ b/src/corelib/thread/qfutureinterface.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -163,6 +163,8 @@ public: inline bool operator!=(const QFutureInterfaceBase &other) const { return d != other.d; } QFutureInterfaceBase &operator=(const QFutureInterfaceBase &other); + void swap(QFutureInterfaceBase &other) noexcept; + protected: bool refT() const; bool derefT() const; @@ -426,6 +428,12 @@ public: } }; +template<typename T> +inline void swap(QFutureInterface<T> &a, QFutureInterface<T> &b) noexcept +{ + a.swap(b); +} + QT_END_NAMESPACE #endif // QFUTUREINTERFACE_H diff --git a/src/corelib/thread/qpromise.h b/src/corelib/thread/qpromise.h index 9cd9238381..32aaa202f5 100644 --- a/src/corelib/thread/qpromise.h +++ b/src/corelib/thread/qpromise.h @@ -43,6 +43,8 @@ #include <QtCore/qglobal.h> #include <QtCore/qfuture.h> +#include <utility> + QT_REQUIRE_CONFIG(future); QT_BEGIN_NAMESPACE @@ -59,13 +61,12 @@ public: Q_DISABLE_COPY(QPromise) QPromise(QPromise<T> &&other) : d(other.d) { - // In constructor, there's no need to perform swap(). Assign new - // QFutureInterface to other.d instead which is slightly cheaper. other.d = QFutureInterface<T>(); } QPromise& operator=(QPromise<T> &&other) { - swap(other); + QPromise<T> tmp(std::move(other)); + tmp.swap(*this); return *this; } ~QPromise() @@ -110,24 +111,25 @@ public: d.setProgressValueAndText(progressValue, progressText); } + void swap(QPromise<T> &other) noexcept + { + qSwap(this->d, other.d); + } + #if defined(Q_CLANG_QDOC) // documentation-only simplified signatures void addResult(const T &result, int index = -1) { } void addResult(T &&result, int index = -1) { } #endif - private: mutable QFutureInterface<T> d = QFutureInterface<T>(); - - void swap(QPromise<T> &other) - { - // Note: copy operations are expensive! They trigger several atomic - // reference counts - auto tmp = this->d; - this->d = other.d; - other.d = tmp; - } }; +template<typename T> +inline void swap(QPromise<T> &a, QPromise<T> &b) noexcept +{ + a.swap(b); +} + QT_END_NAMESPACE #endif // QPROMISE_H diff --git a/src/corelib/thread/qpromise.qdoc b/src/corelib/thread/qpromise.qdoc index e78e16bdd6..b404732a9e 100644 --- a/src/corelib/thread/qpromise.qdoc +++ b/src/corelib/thread/qpromise.qdoc @@ -229,3 +229,8 @@ \sa QFuture::progressValue(), QFuture::progressText(), QFuture::cancel(), reportFinished() */ + +/*! \fn template<typename T> void QPromise<T>::swap(QPromise<T> &other) noexcept + + Swaps promise \a other with this promise. This operation is very fast and never fails. +*/ diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp index cdb69ab3a3..cc2e2e0984 100644 --- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp +++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -689,6 +689,16 @@ void tst_QFuture::futureInterface() VoidResult a; a.run().waitForFinished(); } + + { + QFutureInterface<int> i1; + i1.reportResult(1); + QFutureInterface<int> i2; + i2.reportResult(2); + swap(i1, i2); // ADL must resolve this + QCOMPARE(i1.resultReference(0), 2); + QCOMPARE(i2.resultReference(0), 1); + } } template <typename T> diff --git a/tests/auto/corelib/thread/qpromise/tst_qpromise.cpp b/tests/auto/corelib/thread/qpromise/tst_qpromise.cpp index 02c5b6a8bd..2b8853ccd7 100644 --- a/tests/auto/corelib/thread/qpromise/tst_qpromise.cpp +++ b/tests/auto/corelib/thread/qpromise/tst_qpromise.cpp @@ -64,7 +64,7 @@ private slots: void cancelWhenDestroyed(); #endif void cancelWhenReassigned(); - void finishWhenMoved(); + void finishWhenSwapped(); void cancelWhenMoved(); void waitUntilResumed(); void waitUntilCanceled(); @@ -470,7 +470,7 @@ void tst_QPromise::cancelWhenReassigned() QCOMPARE(f.isCanceled(), true); } -void tst_QPromise::finishWhenMoved() +void tst_QPromise::finishWhenSwapped() { QPromise<int> promise1; auto f1 = promise1.future(); @@ -482,8 +482,11 @@ void tst_QPromise::finishWhenMoved() ThreadWrapper thr([&promise1, &promise2] () mutable { QThread::msleep(100); - // There is swap semantics in move, so promise #1 and #2 just swap - promise1 = std::move(promise2); + promise1.addResult(0); + promise2.addResult(1); + swap(promise1, promise2); // ADL must resolve this + promise1.addResult(2); + promise2.addResult(3); promise1.reportFinished(); // this finish is for future #2 promise2.reportFinished(); // this finish is for future #1 }); @@ -497,6 +500,12 @@ void tst_QPromise::finishWhenMoved() QCOMPARE(f2.isFinished(), true); QCOMPARE(f2.isCanceled(), false); + + QCOMPARE(f1.resultAt(0), 0); + QCOMPARE(f1.resultAt(1), 3); + + QCOMPARE(f2.resultAt(0), 1); + QCOMPARE(f2.resultAt(1), 2); } void tst_QPromise::cancelWhenMoved() @@ -512,7 +521,6 @@ void tst_QPromise::cancelWhenMoved() // Move promises to local scope to test cancellation behavior ThreadWrapper thr([p1 = std::move(promise1), p2 = std::move(promise2)] () mutable { QThread::msleep(100); - // There is swap semantics in move, so promise #1 and #2 just swap p1 = std::move(p2); p1.reportFinished(); // this finish is for future #2 }); |