Namensräume
Varianten
Aktionen

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

Von cppreference.com
< cpp‎ | atomic
 
 
Bibliothek für nebenläufige Programmierung
Threads
(C++11)
(C++20)
this_thread Namespace
(C++11)
(C++11)
(C++11)
Kooperatives Beenden
Gegenseitiger Ausschluss
(C++11)
Allgemeines Sperrungsmanagement
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
Bedingungsvariablen
(C++11)
Semaphoren
Latches und Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
(C++11)
Sichere Wiederherstellung
(C++26)
Hazard Pointer
Atomare Typen
(C++11)
(C++20)
Initialisierung von atomaren Typen
(C++11)(veraltet in C++20)
(C++11)(veraltet in C++20)
Speicherordnung
(C++11)(deprecated in C++26)
Freie Funktionen für atomare Operationen
atomic_compare_exchange_weakatomic_compare_exchange_weak_explicitatomic_compare_exchange_strongatomic_compare_exchange_strong_explicit
(C++11)(C++11)(C++11)(C++11)
Freie Funktionen für atomare Flags
 
Definiert in Header <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) (seit 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) (seit 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) (seit 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) (seit 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) (seit 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) (seit 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) (seit 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) (seit C++11)

Vergleicht atomar die Objektrepräsentation(bis C++20)Wertrepräsentation(seit C++20) des von obj gezeigten Objekts mit der des von expected gezeigten Objekts. Wenn diese bitweise gleich sind, wird das erstere durch desired ersetzt (führt eine Lese-Modifikations-Schreib-Operation durch). Andernfalls wird der tatsächliche Wert, auf den obj zeigt, in *expected geladen (führt eine Ladeoperation durch).

 Overloads  Speichermodell für
 Lese-Modifikations-Schreib‑Operation  Ladeoperation
(1-4) std::memory_order_seq_cst  std::memory_order_seq_cst 
(5-8) erfolgreich failure

Diese Funktionen sind in Bezug auf die Member-Funktionen von std::atomic definiert.

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)

Wenn failure stärker ist als success oder(bis C++17) einer der folgenden ist: std::memory_order_release und std::memory_order_acq_rel, dann ist das Verhalten undefiniert.

Inhalt

[edit] Parameter

obj - Zeiger auf das atomare Objekt, das getestet und geändert werden soll.
expected - Zeiger auf den erwarteten Wert im atomaren Objekt.
desired - der Wert, der in das atomare Objekt geschrieben werden soll, wenn er wie erwartet ist
erfolgreich - die Speicher-Synchronisationsreihenfolge für die Lese-Änderungs-Schreib-Operation, wenn der Vergleich erfolgreich ist
failure - die Speicher-Synchronisationsreihenfolge für die Ladeoperation, wenn der Vergleich fehlschlägt

[edit] Rückgabewert

Das Ergebnis des Vergleichs: true, wenn *obj gleich *expected war, andernfalls false.

[edit] Hinweise

std::atomic_compare_exchange_weak und std::atomic_compare_exchange_weak_explicit (die schwachen Versionen) dürfen fehlschlagen (spurious failure), d. h. sie können sich so verhalten, als wäre *obj != *expected, auch wenn sie gleich sind. Wenn ein Vergleich-und-Austausch in einer Schleife verwendet wird, können diese auf einigen Plattformen eine bessere Leistung erzielen.

Wenn ein schwacher Vergleich-und-Austausch eine Schleife erfordern würde und ein starker nicht, ist der starke vorzuziehen, es sei denn, die Objektrepräsentation von T kann Füllbits,(bis C++20) Trap-Bits enthalten oder bietet mehrere Objektrepräsentationen für denselben Wert (z. B. Floating-Point NaN). In diesen Fällen funktioniert der schwache Vergleich-und-Austausch in der Regel, da er schnell zu einer stabilen Objektrepräsentation konvergiert.

Für eine Union mit Bits, die an den Wertrepräsentationen einiger Member, aber nicht der anderen teilnehmen, kann ein Compare-and-Exchange immer fehlschlagen, da solche Auffüllbits undefinierte Werte haben, wenn sie nicht an der Wertrepräsentation des aktiven Members teilnehmen.

Auffüllbits, die niemals an der Wertrepräsentation eines Objekts teilnehmen, werden ignoriert.

(seit C++20)

[edit] Beispiel

Vergleich-und-Austausch-Operationen werden oft als grundlegende Bausteine von lockfreien Datenstrukturen verwendet.

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

[edit] Fehlerberichte

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
P0558R1 C++11 exakter Typabgleich war erforderlich, weil
T aus mehreren Argumenten abgeleitet wurde
T wird nur abgeleitet
von obj

[edit] Siehe auch

vergleicht atomar den Wert des atomaren Objekts mit einem nicht-atomaren Argument und führt bei Gleichheit einen atomaren Austausch oder bei Ungleichheit eine atomare Ladeoperation durch
(öffentliche Member-Funktion von std::atomic<T>) [edit]
ersetzt atomar den Wert des atomaren Objekts durch ein nicht-atomares Argument und gibt den alten Wert des atomaren Objekts zurück
(Funktions-Template) [bearbeiten]
spezialisiert atomare Operationen für std::shared_ptr
(function template)
C-Dokumentation für atomic_compare_exchange, atomic_compare_exchange_explicit