Функция, которая может побочно перестать работать не перенесенный в цикл

Цикл проверяет условие отказа после возможного побочного отказа

Описание

Функция, которая может побочно перестать работать не перенесенный в цикл, происходит, когда следующие атомарные сравнивают и обмениваются функциями, которые могут перестать работать, побочно называются снаружи цикла.

  • C атомарные функции:

    • atomic_compare_exchange_weak()

    • atomic_compare_exchange_weak_explicit()

  • C++ атомарные функции:

    • std::atomic<T>::compare_exchange_weak(T* expected, T desired)

    • std::atomic<T>::compare_exchange_weak_explicit(T* expected, T desired, std::memory_order succ, std::memory_order fail)

    • std::atomic_compare_exchange_weak(std::atomic<T>* obj, T* expected, T desired)

    • std::atomic_compare_exchange_weak_explicit(volatile std::atomic<T>* obj, T* expected, T desired, std::memory_order succ, std::memory_order fail)

Функции сравнивают содержание памяти объектных представлений, на которые указывает obj и expected. Сравнение может побочно возвратить false, даже если содержание памяти равно. Этот побочный отказ делает функции быстрее на некоторых платформах.

Риск

Атомарное сравнивает и обменивается функцией, которая побочно перестала работать, может вызвать неожиданные результаты и неожиданный поток управления.

Фиксация

Перенеситесь атомарный, сравнивают и обмениваются функциями, которые могут побочно перестать работать в цикле. Цикл проверяет условие отказа после возможного побочного отказа.

Примеры

развернуть все

#include <stdatomic.h>

extern void reset_count(void);
atomic_int count = ATOMIC_VAR_INIT(0);

void increment_count(void)
{
    int old_count = atomic_load(&count);
    int new_count;
    new_count = old_count + 1;
    if (!atomic_compare_exchange_weak(&count, &old_count, new_count))
        reset_count();

}

В этом примере increment_count() использует atomic_compare_exchange_weak(), чтобы сравнить count и old_count. Если количества равны, count постепенно увеличивается к new_count. Если они не равны, количество сбрасывается. Когда atomic_compare_exchange_weak() перестал работать побочно, количество сбрасывается излишне.

Исправление — переносит atomic_compare_exchange_weak() в цикл while

Одно возможное исправление должно перенести вызов atomic_compare_exchange_weak() в цикле while. Цикл проверяет условие отказа после возможного побочного отказа.

#include <stdatomic.h>

extern void reset_count(void);
atomic_int count = ATOMIC_VAR_INIT(0);

void increment_count(void)
{
    int old_count = atomic_load(&count);
    int new_count;
    new_count = old_count + 1;

    do {
        reset_count();

    } while (!atomic_compare_exchange_weak(&count, &old_count, new_count));

}

Информация о результате

Группа: параллелизм
Язык: C | C++
Значение по умолчанию: 'off'
Синтаксис командной строки: SPURIOUS_FAILURE_NOT_WRAPPED_IN_LOOP
Влияние: низко

Введенный в R2018b