summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/tools
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-23 17:39:52 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-01-20 09:27:14 +0000
commitdd58ddd5d97f0663d5fafb7e81bff4fc7db13ba7 (patch)
tree4e275f3ded24dde28d6a751efe86784f2e8745a6 /tests/auto/corelib/tools
parent0d23b7f074fde36a164ed2535957114a52a28ad8 (diff)
Add rvalue overload of insert/prepend to QVarLengthArray and QVector
Improves performance and STL compatibility by adding rvalue versions of prepend and insert. [ChangeLog][QtCore][QVarLengthArray] Added rvalue overloads of prepend and insert. [ChangeLog][QtCore][QVector] Added rvalue overloads of prepend and insert. [ChangeLog][QtCore][QVarLengthArray] Can now contain movable but non-copyable types, such as std::unique_ptr. Change-Id: I6c946acc5b67502c91c52ac5dea67cedb1af93a5 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests/auto/corelib/tools')
-rw-r--r--tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp146
-rw-r--r--tests/auto/corelib/tools/qvector/tst_qvector.cpp57
2 files changed, 194 insertions, 9 deletions
diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
index 3971353cbb..229969a943 100644
--- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
+++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
@@ -53,6 +53,9 @@ private slots:
void initializeListInt();
void initializeListMovable();
void initializeListComplex();
+ void insertMove();
+ void nonCopyable();
+
private:
template<typename T>
void initializeList();
@@ -287,6 +290,11 @@ struct MyBase
} else {
++errorCount;
}
+ if (!data) {
+ --movedCount;
+ ++liveCount;
+ }
+ data = this;
return *this;
}
@@ -294,36 +302,46 @@ struct MyBase
~MyBase()
{
if (isCopy) {
- if (!copyCount)
+ if (!copyCount || !data)
++errorCount;
else
--copyCount;
}
- if (!liveCount)
- ++errorCount;
- else
- --liveCount;
+ if (data) {
+ if (!liveCount)
+ ++errorCount;
+ else
+ --liveCount;
+ } else
+ --movedCount;
}
- bool hasMoved() const
+ bool wasConstructedAt(const MyBase *that) const
{
- return this != data;
+ return that == data;
}
+ bool hasMoved() const { return !wasConstructedAt(this); }
+
protected:
- MyBase const * const data;
+ MyBase(const MyBase *data, bool isCopy)
+ : data(data), isCopy(isCopy) {}
+
+ const MyBase *data;
bool isCopy;
public:
static int errorCount;
static int liveCount;
static int copyCount;
+ static int movedCount;
};
int MyBase::errorCount = 0;
int MyBase::liveCount = 0;
int MyBase::copyCount = 0;
+int MyBase::movedCount = 0;
struct MyPrimitive
: MyBase
@@ -348,7 +366,39 @@ struct MyPrimitive
struct MyMovable
: MyBase
{
- MyMovable(char input = 'j') : i(input) {}
+ MyMovable(char input = 'j') : MyBase(), i(input) {}
+
+ MyMovable(MyMovable const &other) : MyBase(other), i(other.i) {}
+
+ MyMovable(MyMovable &&other) : MyBase(other.data, other.isCopy), i(other.i)
+ {
+ ++movedCount;
+ other.isCopy = false;
+ other.data = nullptr;
+ }
+
+ MyMovable & operator=(const MyMovable &other)
+ {
+ MyBase::operator=(other);
+ i = other.i;
+ return *this;
+ }
+
+ MyMovable & operator=(MyMovable &&other)
+ {
+ if (isCopy)
+ --copyCount;
+ ++movedCount;
+ if (other.data)
+ --liveCount;
+ isCopy = other.isCopy;
+ data = other.data;
+ other.isCopy = false;
+ other.data = nullptr;
+
+ return *this;
+ }
+
bool operator==(const MyMovable &other) const
{
return i == other.i;
@@ -898,5 +948,83 @@ void tst_QVarLengthArray::initializeList()
#endif
}
+void tst_QVarLengthArray::insertMove()
+{
+ MyBase::errorCount = 0;
+ QCOMPARE(MyBase::liveCount, 0);
+ QCOMPARE(MyBase::copyCount, 0);
+
+ {
+ QVarLengthArray<MyMovable, 4> vec;
+ MyMovable m1;
+ MyMovable m2;
+ MyMovable m3;
+ MyMovable m4;
+ QCOMPARE(MyBase::copyCount, 0);
+ QCOMPARE(MyBase::liveCount, 4);
+
+ vec.append(std::move(m3));
+ QVERIFY(vec.at(0).wasConstructedAt(&m3));
+ QCOMPARE(MyBase::errorCount, 0);
+ QCOMPARE(MyBase::liveCount, 4);
+ QCOMPARE(MyBase::movedCount, 1);
+
+ vec.push_back(std::move(m4));
+ QVERIFY(vec.at(0).wasConstructedAt(&m3));
+ QVERIFY(vec.at(1).wasConstructedAt(&m4));
+ QCOMPARE(MyBase::errorCount, 0);
+ QCOMPARE(MyBase::liveCount, 4);
+ QCOMPARE(MyBase::movedCount, 2);
+
+ vec.prepend(std::move(m1));
+ QVERIFY(vec.at(0).wasConstructedAt(&m1));
+ QVERIFY(vec.at(1).wasConstructedAt(&m3));
+ QVERIFY(vec.at(2).wasConstructedAt(&m4));
+ QCOMPARE(MyBase::errorCount, 0);
+ QCOMPARE(MyBase::liveCount, 4);
+ QCOMPARE(MyBase::movedCount, 3);
+
+ vec.insert(1, std::move(m2));
+ QVERIFY(vec.at(0).wasConstructedAt(&m1));
+ QVERIFY(vec.at(1).wasConstructedAt(&m2));
+ QVERIFY(vec.at(2).wasConstructedAt(&m3));
+
+ QCOMPARE(MyBase::copyCount, 0);
+ QCOMPARE(MyBase::liveCount, 4);
+ QCOMPARE(MyBase::errorCount, 0);
+ QCOMPARE(MyBase::movedCount, 4);
+ }
+ QCOMPARE(MyBase::liveCount, 0);
+ QCOMPARE(MyBase::errorCount, 0);
+ QCOMPARE(MyBase::movedCount, 0);
+}
+
+void tst_QVarLengthArray::nonCopyable()
+{
+ QVarLengthArray<std::unique_ptr<int>> vec;
+ std::unique_ptr<int> val1(new int(1));
+ std::unique_ptr<int> val2(new int(2));
+ std::unique_ptr<int> val3(new int(3));
+ std::unique_ptr<int> val4(new int(4));
+ int *const ptr1 = val1.get();
+ int *const ptr2 = val2.get();
+ int *const ptr3 = val3.get();
+ int *const ptr4 = val4.get();
+
+ vec.append(std::move(val3));
+ QVERIFY(ptr3 == vec.at(0).get());
+ vec.append(std::move(val4));
+ QVERIFY(ptr3 == vec.at(0).get());
+ QVERIFY(ptr4 == vec.at(1).get());
+ vec.prepend(std::move(val1));
+ QVERIFY(ptr1 == vec.at(0).get());
+ QVERIFY(ptr3 == vec.at(1).get());
+ QVERIFY(ptr4 == vec.at(2).get());
+ vec.insert(1, std::move(val2));
+ QVERIFY(ptr1 == vec.at(0).get());
+ QVERIFY(ptr2 == vec.at(1).get());
+ QVERIFY(ptr3 == vec.at(2).get());
+}
+
QTEST_APPLESS_MAIN(tst_QVarLengthArray)
#include "tst_qvarlengtharray.moc"
diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
index 713109a214..ef10357b6d 100644
--- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp
+++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
@@ -35,17 +35,28 @@
struct Movable {
Movable(char input = 'j')
: i(input)
+ , that(this)
, state(Constructed)
{
counter.fetchAndAddRelaxed(1);
}
Movable(const Movable &other)
: i(other.i)
+ , that(this)
, state(Constructed)
{
check(other.state, Constructed);
counter.fetchAndAddRelaxed(1);
}
+ Movable(Movable &&other)
+ : i(other.i)
+ , that(other.that)
+ , state(Constructed)
+ {
+ check(other.state, Constructed);
+ counter.fetchAndAddRelaxed(1);
+ other.that = nullptr;
+ }
~Movable()
{
@@ -67,11 +78,27 @@ struct Movable {
check(state, Constructed);
check(other.state, Constructed);
i = other.i;
+ that = this;
+ return *this;
+ }
+ Movable &operator=(Movable &&other)
+ {
+ check(state, Constructed);
+ check(other.state, Constructed);
+ i = other.i;
+ that = other.that;
+ other.that = nullptr;
return *this;
}
+ bool wasConstructedAt(const Movable *other) const
+ {
+ return that == other;
+ }
char i;
static QAtomicInt counter;
private:
+ Movable *that; // used to check if an instance was moved
+
enum State { Constructed = 106, Destructed = 110 };
State state;
@@ -297,6 +324,8 @@ private slots:
void detachThreadSafetyMovable() const;
void detachThreadSafetyCustom() const;
+ void insertMove() const;
+
private:
template<typename T> void copyConstructor() const;
template<typename T> void add() const;
@@ -2861,6 +2890,34 @@ void tst_QVector::detachThreadSafetyCustom() const
}
}
+void tst_QVector::insertMove() const
+{
+ const int instancesCount = Movable::counter.loadAcquire();
+ {
+ QVector<Movable> vec;
+ Movable m1;
+ Movable m2;
+ Movable m3;
+ Movable m4;
+
+ vec.append(std::move(m3));
+ QVERIFY(vec.at(0).wasConstructedAt(&m3));
+ vec.push_back(std::move(m4));
+ QVERIFY(vec.at(0).wasConstructedAt(&m3));
+ QVERIFY(vec.at(1).wasConstructedAt(&m4));
+ vec.prepend(std::move(m1));
+ QVERIFY(vec.at(0).wasConstructedAt(&m1));
+ QVERIFY(vec.at(1).wasConstructedAt(&m3));
+ QVERIFY(vec.at(2).wasConstructedAt(&m4));
+ vec.insert(1, std::move(m2));
+ QVERIFY(vec.at(0).wasConstructedAt(&m1));
+ QVERIFY(vec.at(1).wasConstructedAt(&m2));
+ QVERIFY(vec.at(2).wasConstructedAt(&m3));
+
+ QCOMPARE(Movable::counter.loadAcquire(), instancesCount + 8);
+ }
+ QCOMPARE(Movable::counter.loadAcquire(), instancesCount);
+}
QTEST_MAIN(tst_QVector)
#include "tst_qvector.moc"