summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrei Golubev <andrei.golubev@qt.io>2020-07-24 12:30:00 +0200
committerAndrei Golubev <andrei.golubev@qt.io>2020-08-03 16:47:31 +0200
commitb3c1093751072110d34b9746d419e8070c80fc3f (patch)
tree6efa2be54684b03d57f3f299247f0a14f144d82e
parentfddb0c895f9a12d61bbc4cf33149a8d1a93eaf19 (diff)
Introduce swap functions for QPromise/QFutureInterface
Made QPromise::swap public, added free standing swap() for QFutureInterface and QPromise. Updated QPromise special member functions. Extended tests Task-number: QTBUG-84977 Change-Id: I5daf6876df306d082441dbcdf5ae4dee3bfc0ead Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
-rw-r--r--src/corelib/thread/qfutureinterface.cpp7
-rw-r--r--src/corelib/thread/qfutureinterface.h10
-rw-r--r--src/corelib/thread/qpromise.h28
-rw-r--r--src/corelib/thread/qpromise.qdoc5
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp12
-rw-r--r--tests/auto/corelib/thread/qpromise/tst_qpromise.cpp18
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
});