Захват локального объекта в лямбде по ссылке может вызвать гонку данных или нет?

У меня есть некоторый кусок кода, который вызывает ошибку при запуске с 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;
}
...
}

Это настоящая гонка данных? Как захват по ссылке или по значению имеет значение?

Благодарю.

2

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …