我有一些代码在使用 Thread Sanitizer 运行时导致错误:
bool Renderer::render(std::optional<int32_t> cancellationToken) {
const RenderWatcher renderWatcher{cancellationToken};
...
return Render(...
[&renderWatcher]() { return !renderWatcher.isRenderInProgress(); });
}
在里面RenderWatcher
我有一个构造函数,它在私有字段中设置取消令牌:
const std::optional<int32_t> cancellationToken;
还有一些吸气剂:
bool RenderWatcher::isRenderInProgress() const {
if (!cancellationToken) {
return true;
}
...
}
lambda[&renderWatcher]() { return !renderWatcher.isRenderInProgress(); }
是boost::async
存储在私有字段中的实例,并询问“可以取消此渲染过程吗?”。
TSAN 竞赛在RenderWatcher
构造函数中,在设置 cancelToken 时,并且在没有互斥锁的情况下renderWatcher.isRenderInProgress
读取。cancellationToken
如果 RenderWatcher 是一个局部变量,但它是通过 lambda 中的引用捕获的,我可以进行数据竞争吗?
按价值捕获解决了竞争:
[renderWatcher]() { return !renderWatcher.isRenderInProgress(); }
或使用互斥锁进行保护:
bool RenderWatcher::isRenderInProgress() const {
// Lock mutex here
if (!cancellationToken) {
return true;
}
...
}
这是一场真正的数据竞赛吗?按引用或按值捕获有何不同?
谢谢。