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
Défini dans l'en-tête <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) (depuis 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) (depuis 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) (depuis 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) (depuis 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) (depuis 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) (depuis 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) (depuis 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) (depuis C++11)

Compare atomiquement la représentation d'objet (jusqu'à C++20) représentation de valeur (depuis C++20) de l'objet pointé par obj avec celle de l'objet pointé par expected , et si elles sont égales bit à bit, remplace la première par desired (effectue une opération de lecture-modification-écriture). Sinon, charge la valeur actuelle pointée par obj dans * expected (effectue une opération de chargement).

Surcharges Modèle de mémoire pour
opération de lecture‑modification‑écriture opération de chargement
(1-4) std:: memory_order_seq_cst std:: memory_order_seq_cst
(5-8) success failure

Ces fonctions sont définies en termes de fonctions membres 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 est plus fort que success ou (jusqu'à C++17) est l'un de std:: memory_order_release et std:: memory_order_acq_rel , le comportement est indéfini.

Table des matières

Paramètres

obj - pointeur vers l'objet atomique à tester et modifier
expected - pointeur vers la valeur attendue dans l'objet atomique
desired - valeur à stocker dans l'objet atomique si elle correspond à celle attendue
success - ordonnancement de synchronisation mémoire pour l'opération de lecture-modification-écriture si la comparaison réussit
failure - ordonnancement de synchronisation mémoire pour l'opération de chargement si la comparaison échoue

Valeur de retour

Le résultat de la comparaison : true si * obj était égal à * expected , false sinon.

Notes

std::atomic_compare_exchange_weak et std::atomic_compare_exchange_weak_explicit (les versions faibles) peuvent échouer de manière sporadique, c'est-à-dire agir comme si * obj ! = * expected même s'ils sont égaux. Lorsqu'une opération compare-and-exchange est dans une boucle, elles offrent de meilleures performances sur certaines plateformes.

Lorsqu'un échange-comparaison faible nécessiterait une boucle et qu'un échange-comparaison fort ne le nécessiterait pas, ce dernier est préférable, sauf si la représentation objet de T peut inclure des bits de remplissage, (jusqu'au C++20) des bits de piège, ou offre plusieurs représentations objet pour la même valeur (par exemple, NaN en virgule flottante). Dans ces cas, l'échange-comparaison faible fonctionne généralement car il converge rapidement vers une représentation objet stable.

Pour une union dont certains bits participent aux représentations de valeur de certains membres mais pas d'autres, la comparaison-et-échange peut toujours échouer car ces bits de remplissage ont des valeurs indéterminées lorsqu'ils ne participent pas à la représentation de valeur du membre actif.

Les bits de remplissage qui ne participent jamais à la représentation de la valeur d'un objet sont ignorés.

(since C++20)

Exemple

Les opérations de comparaison et d'échange sont souvent utilisées comme blocs de construction fondamentaux des structures de données sans verrou.

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

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement publié Comportement correct
P0558R1 C++11 une correspondance exacte de type était requise car
T était déduit de multiples arguments
T est uniquement déduit
de obj

Voir aussi

compare atomiquement la valeur de l'objet atomique avec l'argument non atomique et effectue un échange atomique si égal ou un chargement atomique sinon
(fonction membre publique de std::atomic<T> )
remplace atomiquement la valeur de l'objet atomique par l'argument non atomique et retourne l'ancienne valeur de l'atome
(modèle de fonction)
spécialise les opérations atomiques pour std::shared_ptr
(modèle de fonction)
Documentation C pour atomic_compare_exchange , atomic_compare_exchange_explicit