summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrei Golubev <andrei.golubev@qt.io>2020-10-08 15:40:41 +0200
committerAndrei Golubev <andrei.golubev@qt.io>2020-10-09 16:26:01 +0200
commitc22aabe9bc10b8123682a9ed27769a41e862b5e4 (patch)
treee2a85a9c0d45b3c410087c1bbebd693f365d7133
parent27499d25fb6d5b12ee6f97f5a6bedcde53b2dcee (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.h27
-rw-r--r--tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp75
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"