std:: atomic_compare_exchange_weak, std:: atomic_compare_exchange_strong, std:: atomic_compare_exchange_weak_explicit, std:: atomic_compare_exchange_strong_explicit
|
Definiert im Header
<atomic>
|
||
|
template
<
class
T
>
bool
atomic_compare_exchange_weak
|
(1) | (seit C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_weak
|
(2) | (seit C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong
|
(3) | (seit C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong
|
(4) | (seit C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_weak_explicit
|
(5) | (seit C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_weak_explicit
|
(6) | (seit C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong_explicit
|
(7) | (seit C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong_explicit
|
(8) | (seit C++11) |
Vergleicht atomar die Objektrepräsentation (bis C++20) Wertrepräsentation (seit C++20) des Objekts, auf das obj zeigt, mit der des Objekts, auf das expected zeigt, und ersetzt erstere durch desired , falls diese bitweise gleich sind (führt Lese-Modifizier-Schreib-Operation durch). Andernfalls lädt es den tatsächlichen Wert, auf den obj zeigt, in * expected (führt Ladeoperation durch).
| Überladungen | Speichermodell für | |
|---|---|---|
| Lese‑Modifizieren‑Schreiben‑Operation | Ladeoperation | |
| (1-4) | std:: memory_order_seq_cst | std:: memory_order_seq_cst |
| (5-8) | success | failure |
Diese Funktionen sind definiert in Bezug auf Member-Funktionen von std::atomic :
Wenn failure stärker als success ist oder (bis C++17) einer der Werte std:: memory_order_release und std:: memory_order_acq_rel ist, ist das Verhalten undefiniert.
Inhaltsverzeichnis |
Parameter
| obj | - | Zeiger auf das atomare Objekt, das getestet und modifiziert werden soll |
| expected | - | Zeiger auf den Wert, der voraussichtlich im atomaren Objekt gefunden wird |
| desired | - | der Wert, der im atomaren Objekt gespeichert werden soll, falls es den Erwartungen entspricht |
| success | - | die Speichersynchronisationsreihenfolge für den Lese-Modifizier-Schreib-Vorgang bei erfolgreichem Vergleich |
| failure | - | die Speichersynchronisationsreihenfolge für den Ladevorgang bei fehlgeschlagenem Vergleich |
Rückgabewert
Das Ergebnis des Vergleichs: true wenn * obj gleich * expected war, false andernfalls.
Hinweise
std::atomic_compare_exchange_weak
und
std::atomic_compare_exchange_weak_explicit
(die schwachen Versionen) dürfen sporadisch fehlschlagen, das heißt, sich so verhalten, als ob
*
obj
!
=
*
expected
selbst wenn sie gleich sind. Wenn sich ein Compare-and-Exchange in einer Schleife befindet, erzielen sie auf einigen Plattformen eine bessere Leistung.
Wenn ein schwacher Vergleichs- und Austauschvorgang eine Schleife erfordern würde und ein starker nicht, ist der starke vorzuziehen, es sei denn, die Objektdarstellung von
T
kann
Padding-Bits,
(bis C++20)
Trap-Bits oder mehrere Objektdarstellungen für denselben Wert enthalten (z.B. Gleitkomma-NaN). In diesen Fällen funktioniert der schwache Vergleichs- und Austauschvorgang typischerweise, da er schnell auf eine stabile Objektdarstellung konvergiert.
Für eine Union mit Bits, die an den Wertdarstellungen einiger Mitglieder teilnehmen, aber nicht an anderen, könnte Compare-and-Exchange immer fehlschlagen, da solche Padding-Bits unbestimmte Werte haben, wenn sie nicht an der Wertdarstellung des aktiven Mitglieds teilnehmen.
|
Padding-Bits, die niemals an der Wertdarstellung eines Objekts teilnehmen, werden ignoriert. |
(since C++20) |
Beispiel
Compare-and-Exchange-Operationen werden häufig 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); }
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 |
exakte Typübereinstimmung war erforderlich, da
T
von mehreren Argumenten abgeleitet wurde
|
T
wird nur von
obj abgeleitet |
Siehe auch
|
vergleicht atomar den Wert des atomaren Objekts mit nicht-atomarem Argument und führt atomaren Austausch durch wenn gleich oder atomares Laden wenn nicht gleich
(öffentliche Mitgliedsfunktion von
std::atomic<T>
)
|
|
|
(C++11)
(C++11)
|
ersetzt atomar den Wert des atomaren Objekts mit nicht-atomarem Argument und gibt den alten Wert des atomaren Objekts zurück
(Funktionstemplate) |
|
(in C++20 veraltet)
(in C++26 entfernt)
|
spezialisiert atomare Operationen für std::shared_ptr
(Funktions-Template) |
|
C-Dokumentation
für
atomic_compare_exchange
,
atomic_compare_exchange_explicit
|
|