Commit eb073616 authored by Christian Stenger's avatar Christian Stenger
Browse files

Access test results list from multiple threads in a safe way

This had lead to crashes when executing projects with some more
tests or more test output. Now it's using a mutex to avoid
concurrent access.
parent 036c6486
...@@ -36,6 +36,7 @@ TestResultModel::TestResultModel(QObject *parent) : ...@@ -36,6 +36,7 @@ TestResultModel::TestResultModel(QObject *parent) :
TestResultModel::~TestResultModel() TestResultModel::~TestResultModel()
{ {
QWriteLocker lock(&m_rwLock);
m_testResults.clear(); m_testResults.clear();
} }
...@@ -53,6 +54,7 @@ QModelIndex TestResultModel::parent(const QModelIndex &) const ...@@ -53,6 +54,7 @@ QModelIndex TestResultModel::parent(const QModelIndex &) const
int TestResultModel::rowCount(const QModelIndex &parent) const int TestResultModel::rowCount(const QModelIndex &parent) const
{ {
// do not use the QReadLocker here or this will produce a deadlock
return parent.isValid() ? 0 : m_testResults.size(); return parent.isValid() ? 0 : m_testResults.size();
} }
...@@ -80,6 +82,7 @@ static QIcon testResultIcon(ResultType result) { ...@@ -80,6 +82,7 @@ static QIcon testResultIcon(ResultType result) {
QVariant TestResultModel::data(const QModelIndex &index, int role) const QVariant TestResultModel::data(const QModelIndex &index, int role) const
{ {
QReadLocker lock(&m_rwLock);
if (!index.isValid() || index.row() >= m_testResults.count() || index.column() != 0) if (!index.isValid() || index.row() >= m_testResults.count() || index.column() != 0)
return QVariant(); return QVariant();
if (role == Qt::DisplayRole) { if (role == Qt::DisplayRole) {
...@@ -106,8 +109,12 @@ QVariant TestResultModel::data(const QModelIndex &index, int role) const ...@@ -106,8 +109,12 @@ QVariant TestResultModel::data(const QModelIndex &index, int role) const
void TestResultModel::addTestResult(const TestResult &testResult) void TestResultModel::addTestResult(const TestResult &testResult)
{ {
QReadLocker rLock(&m_rwLock);
beginInsertRows(QModelIndex(), m_testResults.size(), m_testResults.size()); beginInsertRows(QModelIndex(), m_testResults.size(), m_testResults.size());
rLock.unlock();
QWriteLocker wLock(&m_rwLock);
m_testResults.append(testResult); m_testResults.append(testResult);
wLock.unlock();
int count = m_testResultCount.value(testResult.result(), 0); int count = m_testResultCount.value(testResult.result(), 0);
m_testResultCount.insert(testResult.result(), ++count); m_testResultCount.insert(testResult.result(), ++count);
endInsertRows(); endInsertRows();
...@@ -116,10 +123,14 @@ void TestResultModel::addTestResult(const TestResult &testResult) ...@@ -116,10 +123,14 @@ void TestResultModel::addTestResult(const TestResult &testResult)
void TestResultModel::clearTestResults() void TestResultModel::clearTestResults()
{ {
QReadLocker rLock(&m_rwLock);
if (m_testResults.size() == 0) if (m_testResults.size() == 0)
return; return;
beginRemoveRows(QModelIndex(), 0, m_testResults.size() - 1); beginRemoveRows(QModelIndex(), 0, m_testResults.size() - 1);
rLock.unlock();
QWriteLocker wLock(&m_rwLock);
m_testResults.clear(); m_testResults.clear();
wLock.unlock();
m_testResultCount.clear(); m_testResultCount.clear();
m_lastMaxWidthIndex = 0; m_lastMaxWidthIndex = 0;
m_maxWidthOfFileName = 0; m_maxWidthOfFileName = 0;
...@@ -132,12 +143,15 @@ TestResult TestResultModel::testResult(const QModelIndex &index) const ...@@ -132,12 +143,15 @@ TestResult TestResultModel::testResult(const QModelIndex &index) const
{ {
if (!index.isValid()) if (!index.isValid())
return TestResult(QString(), QString()); return TestResult(QString(), QString());
QReadLocker lock(&m_rwLock);
return m_testResults.at(index.row()); return m_testResults.at(index.row());
} }
int TestResultModel::maxWidthOfFileName(const QFont &font) int TestResultModel::maxWidthOfFileName(const QFont &font)
{ {
QReadLocker lock(&m_rwLock);
int count = m_testResults.size(); int count = m_testResults.size();
lock.unlock();
if (count == 0) if (count == 0)
return 0; return 0;
if (m_maxWidthOfFileName > 0 && font == m_measurementFont && m_lastMaxWidthIndex == count - 1) if (m_maxWidthOfFileName > 0 && font == m_measurementFont && m_lastMaxWidthIndex == count - 1)
...@@ -147,7 +161,9 @@ int TestResultModel::maxWidthOfFileName(const QFont &font) ...@@ -147,7 +161,9 @@ int TestResultModel::maxWidthOfFileName(const QFont &font)
m_measurementFont = font; m_measurementFont = font;
for (int i = m_lastMaxWidthIndex; i < count; ++i) { for (int i = m_lastMaxWidthIndex; i < count; ++i) {
lock.relock();
QString filename = m_testResults.at(i).fileName(); QString filename = m_testResults.at(i).fileName();
lock.unlock();
const int pos = filename.lastIndexOf(QLatin1Char('/')); const int pos = filename.lastIndexOf(QLatin1Char('/'));
if (pos != -1) if (pos != -1)
filename = filename.mid(pos +1); filename = filename.mid(pos +1);
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include <QFont> #include <QFont>
#include <QReadWriteLock>
#include <QSet> #include <QSet>
namespace Autotest { namespace Autotest {
...@@ -65,6 +66,7 @@ private: ...@@ -65,6 +66,7 @@ private:
int m_lastMaxWidthIndex; int m_lastMaxWidthIndex;
QFont m_measurementFont; QFont m_measurementFont;
QSet<ResultType> m_availableResultTypes; QSet<ResultType> m_availableResultTypes;
mutable QReadWriteLock m_rwLock;
}; };
class TestResultFilterModel : public QSortFilterProxyModel class TestResultFilterModel : public QSortFilterProxyModel
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment