Namespaces
Variants

std:: atomic_compare_exchange_weak, std:: atomic_compare_exchange_strong, std:: atomic_compare_exchange_weak_explicit, std:: atomic_compare_exchange_strong_explicit

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
Condition variables
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
atomic_compare_exchange_weak atomic_compare_exchange_weak_explicit atomic_compare_exchange_strong atomic_compare_exchange_strong_explicit
(C++11) (C++11) (C++11) (C++11)
Free functions for atomic flags
Определено в заголовочном файле <atomic>
template < class T >

bool atomic_compare_exchange_weak
( std:: atomic < T > * obj, typename std:: atomic < T > :: value_type * expected,

typename std:: atomic < T > :: value_type desired ) noexcept ;
(1) (начиная с C++11)
template < class T >

bool atomic_compare_exchange_weak
( volatile std:: atomic < T > * obj,
typename std:: atomic < T > :: value_type * expected,

typename std:: atomic < T > :: value_type desired ) noexcept ;
(2) (начиная с C++11)
template < class T >

bool atomic_compare_exchange_strong
( std:: atomic < T > * obj, typename std:: atomic < T > :: value_type * expected,

typename std:: atomic < T > :: value_type desired ) noexcept ;
(3) (начиная с C++11)
template < class T >

bool atomic_compare_exchange_strong
( volatile std:: atomic < T > * obj,
typename std:: atomic < T > :: value_type * expected,

typename std:: atomic < T > :: value_type desired ) noexcept ;
(4) (начиная с C++11)
template < class T >

bool atomic_compare_exchange_weak_explicit
( std:: atomic < T > * obj, typename std:: atomic < T > :: value_type * expected,
typename std:: atomic < T > :: value_type desired,

std:: memory_order success, std:: memory_order failure ) noexcept ;
(5) (начиная с C++11)
template < class T >

bool atomic_compare_exchange_weak_explicit
( volatile std:: atomic < T > * obj,
typename std:: atomic < T > :: value_type * expected,
typename std:: atomic < T > :: value_type desired,

std:: memory_order success, std:: memory_order failure ) noexcept ;
(6) (начиная с C++11)
template < class T >

bool atomic_compare_exchange_strong_explicit
( std:: atomic < T > * obj, typename std:: atomic < T > :: value_type * expected,
typename std:: atomic < T > :: value_type desired,

std:: memory_order success, std:: memory_order failure ) noexcept ;
(7) (начиная с C++11)
template < class T >

bool atomic_compare_exchange_strong_explicit
( volatile std:: atomic < T > * obj,
typename std:: atomic < T > :: value_type * expected,
typename std:: atomic < T > :: value_type desired,

std:: memory_order success, std:: memory_order failure ) noexcept ;
(8) (начиная с C++11)

Атомарно сравнивает представление объекта (до C++20) представление значения (начиная с C++20) объекта, на который указывает obj , с представлением объекта, на который указывает expected , и если они побитово равны, заменяет первое на desired (выполняет операцию чтения-изменения-записи). В противном случае загружает фактическое значение, на которое указывает obj , в * expected (выполняет операцию загрузки).

Перегрузки Модель памяти для
операции чтение‑модификация‑запись операции загрузки
(1-4) std:: memory_order_seq_cst std:: memory_order_seq_cst
(5-8) success failure

Эти функции определены в терминах функций-членов класса std::atomic :

1,2) obj - > compare_exchange_weak ( * expected, desired )
3,4) obj - > compare_exchange_strong ( * expected, desired )
5,6) obj - > compare_exchange_weak ( * expected, desired, success, failure )
7,8) obj - > compare_exchange_strong ( * expected, desired, success, failure )

Если failure сильнее, чем success или (до C++17) является одним из std:: memory_order_release и std:: memory_order_acq_rel , поведение не определено.

Содержание

Параметры

obj - указатель на атомарный объект для проверки и модификации
expected - указатель на значение, которое ожидается найти в атомарном объекте
desired - значение для записи в атомарный объект, если он соответствует ожидаемому
success - порядок синхронизации памяти для операции чтения-модификации-записи при успешном сравнении
failure - порядок синхронизации памяти для операции загрузки при неудачном сравнении

Возвращаемое значение

Результат сравнения: true если * obj был равен * expected , false в противном случае.

Примечания

std::atomic_compare_exchange_weak и std::atomic_compare_exchange_weak_explicit (слабые версии) могут спорадически завершаться неудачей, то есть действовать так, как если бы * obj ! = * expected даже если они равны. При использовании операции сравнения-и-обмена в цикле они обеспечивают лучшую производительность на некоторых платформах.

Когда слабая операция сравнения с обменом потребовала бы цикла, а сильная — нет, предпочтительнее использовать сильную, за исключением случаев, когда объектное представление T может включать биты заполнения, (до C++20) биты-ловушки или предоставляет множественные объектные представления для одного значения (например, NaN с плавающей точкой). В этих случаях слабая операция сравнения с обменом обычно работает, поскольку быстро сходится к некоторому стабильному объектному представлению.

Для объединения, у которого некоторые биты участвуют в представлениях значений одних членов, но не других, операции сравнения-и-обмена могут всегда завершаться неудачей, поскольку такие биты заполнения имеют неопределённые значения, когда они не участвуют в представлении значения активного члена.

Биты заполнения, которые никогда не участвуют в представлении значения объекта, игнорируются.

(since C++20)

Пример

Операции сравнения и обмена часто используются в качестве базовых строительных блоков для lock-free структур данных.

#include <atomic>
template<class T>
struct node
{
    T data;
    node* next;
    node(const T& data) : data(data), next(nullptr) {}
};
template<class T>
class stack
{
    std::atomic<node<T>*> head;
public:
    void push(const T& data)
    {
        node<T>* new_node = new node<T>(data);
        // put the current value of head into new_node->next
        new_node->next = head.load(std::memory_order_relaxed);
        // now make new_node the new head, but if the head
        // is no longer what's stored in new_node->next
        // (some other thread must have inserted a node just now)
        // then put that new head into new_node->next and try again
        while (!std::atomic_compare_exchange_weak_explicit(
                   &head, &new_node->next, new_node,
                   std::memory_order_release, std::memory_order_relaxed))
            ; // the body of the loop is empty
// note: the above loop is not thread-safe in at least
// GCC prior to 4.8.3 (bug 60272), clang prior to 2014-05-05 (bug 18899)
// MSVC prior to 2014-03-17 (bug 819819). See member function version for workaround
    }
};
int main()
{
    stack<int> s;
    s.push(1);
    s.push(2);
    s.push(3);
}

Отчёты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Applied to Behavior as published Correct behavior
P0558R1 C++11 требовалось точное соответствие типов, потому что
T выводился из нескольких аргументов
T выводится только
из obj

Смотрите также

атомно сравнивает значение атомарного объекта с неатомарным аргументом и выполняет атомарный обмен при равенстве или атомарную загрузку при неравенстве
(публичная функция-член std::atomic<T> )
атомно заменяет значение атомарного объекта неатомарным аргументом и возвращает старое значение атомарного объекта
(шаблон функции)
специализирует атомарные операции для std::shared_ptr
(шаблон функции)
Документация C для atomic_compare_exchange , atomic_compare_exchange_explicit