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>bb10
parent
27499d25fb
commit
c22aabe9bc
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in New Issue