PDA

View Full Version : Odd QMap/QList possible thread problem



RolandHughes
18th February 2015, 17:36
This is odd.

I have a model which supports a table. The model is owned by the application class and exists in the GUI thread. The database access all happens in a different thread to avoid locking the GUI. There is now another thread which connects to the model for use with data extraction. The data is chunked into this model for other reasons. When utilized in the GUI by QTableViews I can chunk and scroll to my heart's content. The extract thread will sometimes process the entire database range N times without issue. Other times it will gag a seg-fault in the exact same place with different index values. Adding insult to injury, I can open up the object which was indicated by the index and see the data.

Qt 4.8.x on 32-bit Linux for embedded target.

It always dies right here: line 183 qmap.h
inline QMap(const QMap<Key, T> &other) : d(other.d)


QVariant ExportModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
{
return QVariant();
}

ResultCell cell = m_rows[ index.row()][ index.column()]; // dies right here both row and column completely valid and m_row[][] data viewable in debugger

return cell.data( role);
}

m_rows is nothing complex

QList< QList< ResultCell> > m_rows; // list of rows, each row is a list of cells


ResultCell is no great shakes either:

class ResultCell
{
public:

bool setData( const QVariant& value, int role=Qt::DisplayRole)
{
m_data.insert( role, value);
return true;
}

QVariant data( int role) { return m_data[ role]; }

private:
QMap< int, QVariant> m_data;
};

I guess my question is, can a model based on QAbstractTableModel be shared across threads? That would explain the very oddness of this problem. I've been monitoring with top and it isn't a memory leakage issue. Thought I would ask before I created another instance of this model out in the export thread.

Thanks

jefftee
18th February 2015, 18:54
Most Qt classes are reentrant, but not thread safe. I believe you need to serialize access to QMap/QList by using a QMutex or QMutexLocker convenience function.

Edit: Each Qt class has a note just past the class overview that states whether the class is reentrant or thread safe. If the class is reentrant, then you need to serialize access to the instance of the class on your own. If the the class is documented as thread safe, then the class itself serializes resources to ensure they can be safely used by multiple threads simultaneously.