Using Qt, I've got this code in order to protect access to some shared data between threads. I'm pretty sure the idea is correct, but I don't know if RVO and/or RAII could potentially screw the get
function. I'm much more used to C and while I understand the idea, I'm not totally familiar with all the "gotchas" for these two concepts.
class DataManager {
Q_OBJECT
private:
QVector<DataType> data;
QReadWriteLock* rwLock;
public:
DataManager() {
rwLock = new QReadWriteLock();
}
~DataManager() {
delete rwLock;
}
Q_DISABLE_COPY(DataManager)
QVector<DataType> getData() {
QReadWriteLocker lock(rwLock);
return data;
}
QVector<DataType>* beginModifyData() {
rwLock->lockForWrite();
return &data;
}
void endModifyData() {
rwLock->unlock();
emit dataChanged();
}
signals:
void dataChanged();
};
In the get
function, is it possible that the RAII-type class QReadWriteLocker
unlocks the lock before the return copy is made? Thus allowing some thread, that was waiting to write, to overwrite the data being returned.
Also, if somebody writes
QVector<DataType>& myData = dataManager->getData();
Is it possible, due to RVO, that they get a reference to the actual data?
Also, I'd like to receive comments on the code and idea itself. Below I've outlined the reasons why I chose this approach.
- Simple to use. Since one can only read a copy of the data, they don't have to worry about synchronization and locking.
- Taking advantage of the implicit sharing of Qt containers, no actual copies will ever be made when using
getData()
, thus making read-only access very fast. - Since, when modifying the data, one gets a pointer to the actual data, again, in most cases, no copies will be made, unless some thread is caching the data (or one of the copies has not yet gone out of scope of whatever got it).
- Looking at the documentation and code, a non-recursive QReadWriteLock is ultra fast in the non-contended case, not doing any waiting or context-switching (uses atomic operations on an integer).
- I could potentially do some data validation/fixup in the
endModifyData
function if needed.
Thanks.