diff options
author | Andrei Golubev <andrei.golubev@qt.io> | 2021-03-24 16:47:33 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-04-26 17:47:06 +0000 |
commit | 9c1e58803ced873e3bc00c3b9632fa2b57315667 (patch) | |
tree | 887503090588d0f7edd8d3c3570df6f064942b54 /tests/auto/corelib/tools | |
parent | e6436af8eb25312cb676436d5a04b85d9178346d (diff) |
Resurrect data moves in QList
Use the data moves to readjust the free space in the QList,
which ultimately fixes the out-of-memory issues caused by
cases like:
forever {
list.prepend(list.back());
list.removeLast();
}
Task-number: QTBUG-91801
Task-number: QTBUG-91360
Task-number: QTBUG-93019
Change-Id: Iacff69cbf36b8b5b176bb2663df635ec972c875c
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
(cherry picked from commit a0253f5f0249024580050e4ec22d50cb139ef8d9)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'tests/auto/corelib/tools')
-rw-r--r-- | tests/auto/corelib/tools/qarraydata/simplevector.h | 17 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qlist/tst_qlist.cpp | 59 |
2 files changed, 59 insertions, 17 deletions
diff --git a/tests/auto/corelib/tools/qarraydata/simplevector.h b/tests/auto/corelib/tools/qarraydata/simplevector.h index 747af3d422..1fc5e9b8e1 100644 --- a/tests/auto/corelib/tools/qarraydata/simplevector.h +++ b/tests/auto/corelib/tools/qarraydata/simplevector.h @@ -209,22 +209,7 @@ public: d->insert(0, first, last - first); } - void append(const_iterator first, const_iterator last) - { - if (first == last) - return; - - auto requiredSize = qsizetype(last - first); - if (d->needsDetach() || d.freeSpaceAtEnd() < requiredSize) { - DataPointer oldData; - d.reallocateAndGrow(QArrayData::GrowsAtEnd, requiredSize, &oldData); - - d->copyAppend(first, last); - return; - } - - d->copyAppend(first, last); - } + void append(const_iterator first, const_iterator last) { d->growAppend(first, last); } void insert(int position, const_iterator first, const_iterator last) { diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp index 80adb0f6a1..14c679562f 100644 --- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp +++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp @@ -348,8 +348,13 @@ private slots: void emplaceWithElementFromTheSameContainer_data(); void fromReadOnlyData() const; - void qtbug_90359() const; + void reinsertToBeginInt_qtbug91360() const { reinsertToBegin<int>(); } + void reinsertToBeginMovable_qtbug91360() const { reinsertToBegin<Movable>(); } + void reinsertToBeginCustom_qtbug91360() const { reinsertToBegin<Custom>(); } + void reinsertToEndInt_qtbug91360() const { reinsertToEnd<int>(); } + void reinsertToEndMovable_qtbug91360() const { reinsertToEnd<Movable>(); } + void reinsertToEndCustom_qtbug91360() const { reinsertToEnd<Custom>(); } private: template<typename T> void copyConstructor() const; @@ -379,6 +384,10 @@ private: template<typename T> void detachThreadSafety() const; template<typename T> void emplaceImpl() const; template<typename T> void emplaceConsistentWithStdVectorImpl() const; + template<typename T> + void reinsertToBegin() const; + template<typename T> + void reinsertToEnd() const; }; @@ -3265,5 +3274,53 @@ void tst_QList::qtbug_90359() const QCOMPARE(actual, expected); } +template<typename T> +void tst_QList::reinsertToBegin() const +{ + QList<T> list(1); + const auto reinsert = [](QList<T> &list) { + list.prepend(list.back()); + list.removeLast(); + }; + + // this constant is big enough for the QList to stop reallocating, after + // all, size is always less than 3 + const int maxIters = 128; + for (int i = 0; i < maxIters; ++i) { + reinsert(list); + } + + // if QList continues to grow, it's an error + qsizetype capacity = list.capacity(); + for (int i = 0, enoughIters = int(capacity) * 2; i < enoughIters; ++i) { + reinsert(list); + QCOMPARE(capacity, list.capacity()); + } +} + +template<typename T> +void tst_QList::reinsertToEnd() const +{ + QList<T> list(1); + const auto reinsert = [](QList<T> &list) { + list.append(list.front()); + list.removeFirst(); + }; + + // this constant is big enough for the QList to stop reallocating, after + // all, size is always less than 3 + const int maxIters = 128; + for (int i = 0; i < maxIters; ++i) { + reinsert(list); + } + + // if QList continues to grow, it's an error + qsizetype capacity = list.capacity(); + for (int i = 0, enoughIters = int(capacity) * 2; i < enoughIters; ++i) { + reinsert(list); + QCOMPARE(capacity, list.capacity()); + } +} + QTEST_MAIN(tst_QList) #include "tst_qlist.moc" |