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
Definido en el encabezado <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) (desde 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) (desde 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) (desde 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) (desde 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) (desde 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) (desde 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) (desde 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) (desde C++11)

Compara atómicamente la representación del objeto (until C++20) representación del valor (since C++20) del objeto apuntado por obj con la del objeto apuntado por expected , y si son bit a bit iguales, reemplaza la primera con desired (realiza una operación de lectura-modificación-escritura). De lo contrario, carga el valor real apuntado por obj en * expected (realiza una operación de carga).

Sobrecargas Modelo de memoria para
operación de lectura‑modificación‑escritura operación de carga
(1-4) std:: memory_order_seq_cst std:: memory_order_seq_cst
(5-8) success failure

Estas funciones se definen en términos de funciones miembro de 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 )

Si failure es más fuerte que success o (hasta C++17) es uno de std:: memory_order_release y std:: memory_order_acq_rel , el comportamiento es indefinido.

Contenidos

Parámetros

obj - puntero al objeto atómico a probar y modificar
expected - puntero al valor esperado en el objeto atómico
desired - valor a almacenar en el objeto atómico si coincide con lo esperado
success - orden de sincronización de memoria para la operación de lectura-modificación-escritura si la comparación tiene éxito
failure - orden de sincronización de memoria para la operación de carga si la comparación falla

Valor de retorno

El resultado de la comparación: true si * obj era igual a * expected , false en caso contrario.

Notas

std::atomic_compare_exchange_weak y std::atomic_compare_exchange_weak_explicit (las versiones débiles) pueden fallar espuriamente, es decir, actuar como si * obj ! = * expected incluso si son iguales. Cuando un compare-and-exchange está en un bucle, ofrecerán un mejor rendimiento en algunas plataformas.

Cuando una comparación e intercambio débil requeriría un bucle y una fuerte no, la fuerte es preferible a menos que la representación del objeto de T pueda incluir bits de relleno, (hasta C++20) bits de trampa, u ofrezca múltiples representaciones de objeto para el mismo valor (por ejemplo, NaN de punto flotante). En esos casos, la comparación e intercambio débil típicamente funciona porque converge rápidamente en alguna representación de objeto estable.

Para una unión con bits que participan en las representaciones de valor de algunos miembros pero no de otros, la operación de comparación e intercambio podría fallar siempre porque dichos bits de relleno tienen valores indeterminados cuando no participan en la representación de valor del miembro activo.

Los bits de relleno que nunca participan en la representación de valor de un objeto son ignorados.

(since C++20)

Ejemplo

Las operaciones de comparación e intercambio se utilizan a menudo como bloques de construcción básicos de estructuras de datos libres de bloqueo.

#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);
}

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
P0558R1 C++11 se requería coincidencia exacta de tipo porque
T se deducía de múltiples argumentos
T solo se deduce
de obj

Véase también

compara atómicamente el valor del objeto atómico con el argumento no atómico y realiza un intercambio atómico si son iguales o una carga atómica si no lo son
(función miembro pública de std::atomic<T> )
reemplaza atómicamente el valor del objeto atómico con el argumento no atómico y devuelve el valor antiguo del atómico
(plantilla de función)
especializa operaciones atómicas para std::shared_ptr
(plantilla de función)
Documentación C para atomic_compare_exchange , atomic_compare_exchange_explicit