std:: atomic_compare_exchange_weak, std:: atomic_compare_exchange_strong, std:: atomic_compare_exchange_weak_explicit, std:: atomic_compare_exchange_strong_explicit
|
Definido en el encabezado
<atomic>
|
||
|
template
<
class
T
>
bool
atomic_compare_exchange_weak
|
(1) | (desde C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_weak
|
(2) | (desde C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong
|
(3) | (desde C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong
|
(4) | (desde C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_weak_explicit
|
(5) | (desde C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_weak_explicit
|
(6) | (desde C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong_explicit
|
(7) | (desde C++11) |
|
template
<
class
T
>
bool
atomic_compare_exchange_strong_explicit
|
(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 :
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>
)
|
|
|
(C++11)
(C++11)
|
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) |
|
(obsoleto en C++20)
(eliminado en C++26)
|
especializa operaciones atómicas para std::shared_ptr
(plantilla de función) |
|
Documentación C
para
atomic_compare_exchange
,
atomic_compare_exchange_explicit
|
|