使用Qt,我获得了这段代码,以保护线程之间对某些共享数据的访问。我很确定这个想法是正确的,但我不知道RVO和/或RAII是否有可能破坏get
函数。我更习惯于C,虽然我理解这个概念,但我并不完全熟悉这两个概念的所有“难点”。
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();
};
在get
函数中,在复制返回之前,RAII类型的类QReadWriteLocker
是否有可能解锁?这样,一些等待写入的线程就可以覆盖正在返回的数据。
还有,如果有人写
QVector<DataType>& myData = dataManager->getData();
由于RVO,他们是否有可能获得对实际数据的引用?
另外,我还想收到关于代码和idea本身的评论。下面我已经概述了我选择这种方法的原因。
getData()
时将永远不会生成实际的副本,从而使只读访问非常快。endModifyData
函数中进行一些数据验证/修复。谢谢。
发布于 2018-06-29 20:20:58
让我们看看这些成员函数实际上做了什么,以及哪些可能出错:
getData
在getData
中获得的锁基本上只确保没有人在内部修改data
。一旦调用方获得返回的值,另一个线程就可以自由地修改它。
更清楚一点的是,RAII就是这样分解的:
QVector<DataType> getData() {
QReadWriteLocker lock(rwLock);
QVector<DataType> temp = data;
lock.~QReadWriteLocker(); // unlock
return temp;
}
所以锁实际上不包括后续的使用。
beginModifyData
/endModifyData
这两个成员函数将被串联调用。但是,如果beginModifyData
的调用方忘记调用endModifyData
(例如,因为抛出异常),会发生什么情况?显然,在这种情况下,锁永远不会被释放。
另外,有人可能会存储返回的指针,因此在释放锁后可以不同步地访问数据。
为什么rwLock
必须是指针,有什么具体的原因吗?它可能只是QReadWriteLock
类型的代替。
beginModifyData
为什么返回一个QVector<DataType>*
而不是一个QVector<DataType>&
有什么具体原因吗?
的问题
不,这不是返回值优化(RVO)的工作方式。为了更好地理解,如果编译器应用RVO,它可能会在概念上重写代码,如下所示:
void getData(QVector<DataType>* return_value) {
QReadWriteLocker lock(rwLock);
// construct a new QVector<DataType> at the given address (to be passed from the callsite)
new(return_value) QVector<DataType>(data);
}
// the callsite would be rewritten from
QVector<DataType> myData = dataManager->getData();
// to
QVector<DataType> myData; // uninitialized!
dataManger->getData(&myData);
因此,这显然不适用于引用。
如果没有RVO,引用将根本无法工作,因为返回对象的生存期在其声明结束时结束。但是,它将(至少部分)用于const QVector<DataType>&
,因为这些临时人员的生命周期将得到延长(尽管它仍将引用副本)。
https://codereview.stackexchange.com/questions/197511
复制相似问题