diff options
author | Andrei Golubev <andrei.golubev@qt.io> | 2020-10-08 15:40:41 +0200 |
---|---|---|
committer | Andrei Golubev <andrei.golubev@qt.io> | 2020-10-09 16:26:01 +0200 |
commit | c22aabe9bc10b8123682a9ed27769a41e862b5e4 (patch) | |
tree | e2a85a9c0d45b3c410087c1bbebd693f365d7133 | |
parent | 27499d25fb6d5b12ee6f97f5a6bedcde53b2dcee (diff) |
Clear pending results in ResultStore
Pending results were never cleared by result store. This led to memory
leaks when the results never transitioned to "visible" results
Change-Id: I674302eb51542ad5f4d918da68d616428c73ae9f
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
-rw-r--r-- | src/corelib/thread/qresultstore.h | 27 | ||||
-rw-r--r-- | tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp | 75 |
2 files changed, 93 insertions, 9 deletions
diff --git a/src/corelib/thread/qresultstore.h b/src/corelib/thread/qresultstore.h index 523c745a8e..5f8c7f150a 100644 --- a/src/corelib/thread/qresultstore.h +++ b/src/corelib/thread/qresultstore.h @@ -151,6 +151,20 @@ protected: QMap<int, ResultItem> pendingResults; int filteredResults; + template <typename T> + static void clear(QMap<int, ResultItem> &store) + { + QMap<int, ResultItem>::const_iterator mapIterator = store.constBegin(); + while (mapIterator != store.constEnd()) { + if (mapIterator.value().isVector()) + delete reinterpret_cast<const QList<T> *>(mapIterator.value().result); + else + delete reinterpret_cast<const T *>(mapIterator.value().result); + ++mapIterator; + } + store.clear(); + } + public: template <typename T> int addResult(int index, const T *result) @@ -197,16 +211,11 @@ public: template <typename T> void clear() { - QMap<int, ResultItem>::const_iterator mapIterator = m_results.constBegin(); - while (mapIterator != m_results.constEnd()) { - if (mapIterator.value().isVector()) - delete reinterpret_cast<const QList<T> *>(mapIterator.value().result); - else - delete reinterpret_cast<const T *>(mapIterator.value().result); - ++mapIterator; - } + ResultStoreBase::clear<T>(m_results); resultCount = 0; - m_results.clear(); + insertIndex = 0; + ResultStoreBase::clear<T>(pendingResults); + filteredResults = 0; } }; diff --git a/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp b/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp index 5b545fe37a..6e0bbda2c2 100644 --- a/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp +++ b/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp @@ -53,6 +53,8 @@ private slots: void filterMode(); void addCanceledResult(); void count(); + void pendingResultsDoNotLeak_data(); + void pendingResultsDoNotLeak(); private: int int0; int int1; @@ -477,5 +479,78 @@ void tst_QtConcurrentResultStore::count() } } +// simplified version of CountedObject from tst_qarraydata.cpp +struct CountedObject +{ + CountedObject() : id(liveCount++) + { } + + CountedObject(const CountedObject &other) : id(other.id) + { + ++liveCount; + } + + ~CountedObject() + { + --liveCount; + } + + CountedObject &operator=(const CountedObject &) = default; + + struct LeakChecker + { + LeakChecker() + : previousLiveCount(liveCount) + { + } + + ~LeakChecker() + { + QCOMPARE(liveCount, previousLiveCount); + } + + private: + const size_t previousLiveCount; + }; + + int id = 0; + static size_t liveCount; +}; + +size_t CountedObject::liveCount = 0; + +struct ResultStoreCountedObject : ResultStoreBase +{ + ~ResultStoreCountedObject() { clear<CountedObject>(); } +}; + +void tst_QtConcurrentResultStore::pendingResultsDoNotLeak_data() +{ + QTest::addColumn<bool>("filterMode"); + + QTest::addRow("filter-mode-off") << false; + QTest::addRow("filter-mode-on") << true; +} + +void tst_QtConcurrentResultStore::pendingResultsDoNotLeak() +{ + QFETCH(bool, filterMode); + CountedObject::LeakChecker leakChecker; Q_UNUSED(leakChecker); + + ResultStoreCountedObject store; + store.setFilterMode(filterMode); + + // lvalue + auto lvalueObj = CountedObject(); + store.addResult(42, &lvalueObj); + + // rvalue + store.moveResult(43, CountedObject()); + + // array + auto lvalueListOfObj = QList<CountedObject>({CountedObject(), CountedObject()}); + store.addResults(44, &lvalueListOfObj); +} + QTEST_MAIN(tst_QtConcurrentResultStore) #include "tst_qresultstore.moc" |