У меня есть некоторый кусок кода, который вызывает ошибку при запуске с 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;
}
...
}
Лямбда [&renderWatcher]() { return !renderWatcher.isRenderInProgress(); }
это boost::async
экземпляр хранится в приватном поле и спрашивает о том, «можно ли отменить этот процесс рендеринга?».
Гонка TSAN в RenderWatcher
конструктор, при установке cancellationToken, и renderWatcher.isRenderInProgress
, который читает cancellationToken
без мьютекса.
Могу ли я получить гонку данных, если RenderWatcher — локальная переменная, но она захвачена по ссылке в лямбде?
Захват по значению решает гонку:
[renderWatcher]() { return !renderWatcher.isRenderInProgress(); }
Или защита с помощью мьютекса:
bool RenderWatcher::isRenderInProgress() const {
// Lock mutex here
if (!cancellationToken) {
return true;
}
...
}
Это настоящая гонка данных? Как захват по ссылке или по значению имеет значение?
Благодарю.
Задача ещё не решена.
Других решений пока нет …