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

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

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

Благодарю.

0 ответов

Другие вопросы по тегам