2

我有一些代码在使用 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;
    }
    ...
}

这是一场真正的数据竞赛吗?按引用或按值捕获有何不同?

谢谢。

4

0 回答 0