std:: atomic
|
Definido en el encabezado
<atomic>
|
||
|
template
<
class
T
>
struct atomic ; |
(1) | (desde C++11) |
|
template
<
class
U
>
struct atomic < U * > ; |
(2) | (desde C++11) |
|
Definido en el encabezado
<memory>
|
||
|
template
<
class
U
>
struct atomic < std:: shared_ptr < U >> ; |
(3) | (desde C++20) |
|
template
<
class
U
>
struct atomic < std:: weak_ptr < U >> ; |
(4) | (desde C++20) |
|
Definido en el encabezado
<stdatomic.h>
|
||
|
#define _Atomic(T) /* ver más abajo */
|
(5) | (desde C++23) |
Cada instanciación y especialización completa de la plantilla
std::atomic
define un tipo atómico. Si un hilo escribe en un objeto atómico mientras otro hilo lo lee, el comportamiento está bien definido (consulte el
modelo de memoria
para más detalles sobre carreras de datos).
Además, los accesos a objetos atómicos pueden establecer sincronización entre hilos y ordenar accesos a memoria no atómicos según lo especificado por std::memory_order .
std::atomic
no es copiable ni movible.
|
La macro de compatibilidad
No está especificado si alguna declaración en el espacio de nombres
|
(desde C++23) |
Contenidos |
Especializaciones
Plantilla principal
La plantilla principal
std::atomic
puede instanciarse con cualquier tipo
TriviallyCopyable
T
que satisfaga tanto
CopyConstructible
como
CopyAssignable
. El programa está mal formado si alguno de los siguientes valores es
false
:
- std:: is_trivially_copyable < T > :: value
- std:: is_copy_constructible < T > :: value
- std:: is_move_constructible < T > :: value
- std:: is_copy_assignable < T > :: value
- std:: is_move_assignable < T > :: value
- std:: is_same < T, typename std:: remove_cv < T > :: type > :: value
struct Counters { int a; int b; }; // tipo definido por el usuario trivialmente copiable std::atomic<Counters> cnt; // especialización para el tipo definido por el usuario
std :: atomic < bool > utiliza la plantilla principal. Se garantiza que es una estructura de diseño estándar y tiene un destructor trivial .
Especializaciones parciales
La biblioteca estándar proporciona especializaciones parciales de la plantilla
std::atomic
para los siguientes tipos con propiedades adicionales que la plantilla principal no tiene:
std::atomic<U*>
para todos los tipos de puntero. Estas especializaciones tienen diseño estándar
, constructores por defecto triviales,
(hasta C++20)
y destructores triviales. Además de las operaciones proporcionadas para todos los tipos atómicos, estas especializaciones adicionalmente soportan operaciones aritméticas atómicas apropiadas para tipos de puntero, como
fetch_add
,
fetch_sub
.
|
3,4)
Especializaciones parciales
std
::
atomic
<
std::
shared_ptr
<
U
>>
y
std
::
atomic
<
std::
weak_ptr
<
U
>>
están disponibles para
std::shared_ptr
y
std::weak_ptr
.
Consulte std::atomic <std::shared_ptr> y std::atomic <std::weak_ptr> para más detalles. |
(desde C++20) |
Especializaciones para tipos integrales
Cuando se instancia con uno de los siguientes tipos integrales,
std::atomic
proporciona operaciones atómicas adicionales apropiadas para tipos integrales tales como
fetch_add
,
fetch_sub
,
fetch_and
,
fetch_or
,
fetch_xor
:
-
- Los tipos de caracteres char , char8_t (desde C++20) , char16_t , char32_t , y wchar_t ;
- Los tipos enteros con signo estándar: signed char , short , int , long , y long long ;
- Los tipos enteros sin signo estándar: unsigned char , unsigned short , unsigned int , unsigned long , y unsigned long long ;
- Cualquier tipo integral adicional requerido por los typedefs en el encabezado <cstdint> .
Además, la especialización resultante
std::atomic<
Integral
>
tiene diseño estándar
, un constructor por defecto trivial,
(hasta C++20)
y un destructor trivial. La aritmética de enteros con signo está definida para usar complemento a dos; no hay resultados indefinidos.
Especializaciones para tipos de punto flotante
Cuando se instancia con uno de los tipos de punto flotante sin calificadores cv (
float
,
double
,
long
double
y tipos de punto flotante extendidos sin calificadores cv
extended floating-point types
(desde C++23)
),
Adicionalmente, la especialización resultante
Ninguna operación resulta en comportamiento indefinido incluso si el resultado no es representable en el tipo de punto flotante. El entorno de punto flotante en efecto puede ser diferente del entorno de punto flotante del hilo que realiza la llamada. |
(desde C++20) |
Tipos de miembros
| Tipo | Definición | ||||
value_type
|
T
(independientemente de si está especializado o no)
|
||||
difference_type
[1]
|
|
-
↑
difference_typeno está definido en la plantilla principalstd::atomicni en las especializaciones parciales para std::shared_ptr y std::weak_ptr .
Funciones miembro
|
construye un objeto atómico
(función miembro pública) |
|
|
almacena un valor en un objeto atómico
(función miembro pública) |
|
|
verifica si el objeto atómico es libre de bloqueo
(función miembro pública) |
|
|
reemplaza atómicamente el valor del objeto atómico con un argumento no atómico
(función miembro pública) |
|
|
obtiene atómicamente el valor del objeto atómico
(función miembro pública) |
|
|
carga un valor desde un objeto atómico
(función miembro pública) |
|
|
reemplaza atómicamente el valor del objeto atómico y obtiene el valor mantenido previamente
(función miembro pública) |
|
|
compara atómicamente el valor del objeto atómico con un argumento no atómico y realiza intercambio atómico si son iguales o carga atómica si no
(función miembro pública) |
|
|
(C++20)
|
bloquea el hilo hasta que sea notificado y el valor atómico cambie
(función miembro pública) |
|
(C++20)
|
notifica al menos un hilo esperando en el objeto atómico
(función miembro pública) |
|
(C++20)
|
notifica todos los hilos bloqueados esperando en el objeto atómico
(función miembro pública) |
Constantes |
|
|
[static]
(C++17)
|
indica que el tipo es siempre libre de bloqueo
(constante miembro estática pública) |
Funciones miembro especializadas
Especializado para tipos integrales , de punto flotante (desde C++20) y punteros |
|
|
agrega atómicamente el argumento al valor almacenado en el objeto atómico y obtiene el valor mantenido previamente
(función miembro pública) |
|
|
resta atómicamente el argumento del valor almacenado en el objeto atómico y obtiene el valor mantenido previamente
(función miembro pública) |
|
|
suma o resta del valor atómico
(función miembro pública) |
|
Especializado solo para tipos integrales y punteros |
|
|
(C++26)
|
realiza atómicamente
std::max
entre el argumento y el valor del objeto atómico y obtiene el valor mantenido previamente
(función miembro pública) |
|
(C++26)
|
realiza atómicamente
std::min
entre el argumento y el valor del objeto atómico y obtiene el valor mantenido previamente
(función miembro pública) |
|
incrementa o decrementa el valor atómico en uno
(función miembro pública) |
|
Especializado solo para tipos integrales |
|
|
realiza atómicamente AND bit a bit entre el argumento y el valor del objeto atómico y obtiene el valor mantenido previamente
(función miembro pública) |
|
|
realiza atómicamente OR bit a bit entre el argumento y el valor del objeto atómico y obtiene el valor mantenido previamente
(función miembro pública) |
|
|
realiza atómicamente XOR bit a bit entre el argumento y el valor del objeto atómico y obtiene el valor mantenido previamente
(función miembro pública) |
|
|
realiza AND, OR, XOR bit a bit con el valor atómico
(función miembro pública) |
|
Alias de tipos
Se proporcionan alias de tipo para bool y todos los tipos integrales mencionados anteriormente, de la siguiente manera:
Alias para todos
|
|
|
atomic_bool
(C++11)
|
std
::
atomic
<
bool
>
(typedef) |
|
atomic_char
(C++11)
|
std
::
atomic
<
char
>
(typedef) |
|
atomic_schar
(C++11)
|
std
::
atomic
<
signed
char
>
(typedef) |
|
atomic_uchar
(C++11)
|
std
::
atomic
<
unsigned
char
>
(typedef) |
|
atomic_short
(C++11)
|
std
::
atomic
<
short
>
(typedef) |
|
atomic_ushort
(C++11)
|
std
::
atomic
<
unsigned
short
>
(typedef) |
|
atomic_int
(C++11)
|
std
::
atomic
<
int
>
(typedef) |
|
atomic_uint
(C++11)
|
std
::
atomic
<
unsigned
int
>
(typedef) |
|
atomic_long
(C++11)
|
std
::
atomic
<
long
>
(typedef) |
|
atomic_ulong
(C++11)
|
std
::
atomic
<
unsigned
long
>
(typedef) |
|
atomic_llong
(C++11)
|
std
::
atomic
<
long
long
>
(typedef) |
|
atomic_ullong
(C++11)
|
std
::
atomic
<
unsigned
long
long
>
(typedef) |
|
atomic_char8_t
(C++20)
|
std
::
atomic
<
char8_t
>
(typedef) |
|
atomic_char16_t
(C++11)
|
std
::
atomic
<
char16_t
>
(typedef) |
|
atomic_char32_t
(C++11)
|
std
::
atomic
<
char32_t
>
(typedef) |
|
atomic_wchar_t
(C++11)
|
std
::
atomic
<
wchar_t
>
(typedef) |
|
atomic_int8_t
(C++11)
(opcional)
|
std
::
atomic
<
std::
int8_t
>
(typedef) |
|
atomic_uint8_t
(C++11)
(opcional)
|
std
::
atomic
<
std::
uint8_t
>
(typedef) |
|
atomic_int16_t
(C++11)
(opcional)
|
std
::
atomic
<
std::
int16_t
>
(typedef) |
|
atomic_uint16_t
(C++11)
(opcional)
|
std
::
atomic
<
std::
uint16_t
>
(typedef) |
|
atomic_int32_t
(C++11)
(opcional)
|
std
::
atomic
<
std::
int32_t
>
(typedef) |
|
atomic_uint32_t
(C++11)
(opcional)
|
std
::
atomic
<
std::
uint32_t
>
(typedef) |
|
atomic_int64_t
(C++11)
(opcional)
|
std
::
atomic
<
std::
int64_t
>
(typedef) |
|
atomic_uint64_t
(C++11)
(opcional)
|
std
::
atomic
<
std::
uint64_t
>
(typedef) |
|
atomic_int_least8_t
(C++11)
|
std
::
atomic
<
std::
int_least8_t
>
(typedef) |
|
atomic_uint_least8_t
(C++11)
|
std
::
atomic
<
std::
uint_least8_t
>
(typedef) |
|
atomic_int_least16_t
(C++11)
|
std
::
atomic
<
std::
int_least16_t
>
(typedef) |
|
atomic_uint_least16_t
(C++11)
|
std
::
atomic
<
std::
uint_least16_t
>
(typedef) |
|
atomic_int_least32_t
(C++11)
|
std
::
atomic
<
std::
int_least32_t
>
(typedef) |
|
atomic_uint_least32_t
(C++11)
|
std
::
atomic
<
std::
uint_least32_t
>
(typedef) |
|
atomic_int_least64_t
(C++11)
|
std
::
atomic
<
std::
int_least64_t
>
(typedef) |
|
atomic_uint_least64_t
(C++11)
|
std
::
atomic
<
std::
uint_least64_t
>
(typedef) |
|
atomic_int_fast8_t
(C++11)
|
std
::
atomic
<
std::
int_fast8_t
>
(typedef) |
|
atomic_uint_fast8_t
(C++11)
|
std
::
atomic
<
std::
uint_fast8_t
>
(typedef) |
|
atomic_int_fast16_t
(C++11)
|
std
::
atomic
<
std::
int_fast16_t
>
(typedef) |
|
atomic_uint_fast16_t
(C++11)
|
std
::
atomic
<
std::
uint_fast16_t
>
(typedef) |
|
atomic_int_fast32_t
(C++11)
|
std
::
atomic
<
std::
int_fast32_t
>
(typedef) |
|
atomic_uint_fast32_t
(C++11)
|
std
::
atomic
<
std::
uint_fast32_t
>
(typedef) |
|
atomic_int_fast64_t
(C++11)
|
std
::
atomic
<
std::
int_fast64_t
>
(typedef) |
|
atomic_uint_fast64_t
(C++11)
|
std
::
atomic
<
std::
uint_fast64_t
>
(typedef) |
|
atomic_intptr_t
(C++11)
(opcional)
|
std
::
atomic
<
std::
intptr_t
>
(typedef) |
|
atomic_uintptr_t
(C++11)
(opcional)
|
std
::
atomic
<
std::
uintptr_t
>
(typedef) |
|
atomic_size_t
(C++11)
|
std
::
atomic
<
std::
size_t
>
(typedef) |
|
atomic_ptrdiff_t
(C++11)
|
std
::
atomic
<
std::
ptrdiff_t
>
(typedef) |
|
atomic_intmax_t
(C++11)
|
std
::
atomic
<
std::
intmax_t
>
(typedef) |
|
atomic_uintmax_t
(C++11)
|
std
::
atomic
<
std::
uintmax_t
>
(typedef) |
Alias para tipos de propósito especial |
|
|
atomic_signed_lock_free
(C++20)
|
un tipo atómico entero con signo que no utiliza bloqueos y para el cual la espera/notificación es más eficiente
(typedef) |
|
atomic_unsigned_lock_free
(C++20)
|
un tipo atómico integral sin signo que es libre de bloqueo y para el cual la espera/notificación es más eficiente
(typedef) |
std::atomic_int
N
_t
,
std::atomic_uint
N
_t
,
std::atomic_intptr_t
, and
std::atomic_uintptr_t
are defined if and only if
std::int
N
_t
,
std::uint
N
_t
,
std::intptr_t
, and
std::uintptr_t
are defined, respectively.
|
|
(desde C++20) |
Notas
Existen equivalentes de plantillas de funciones no miembro para todas las funciones miembro de
std::atomic
. Estas funciones no miembro pueden estar adicionalmente sobrecargadas para tipos que no son especializaciones de
std::atomic
, pero son capaces de garantizar atomicidad. El único tipo de este tipo en la biblioteca estándar es
std::
shared_ptr
<
U
>
.
_Atomic
es una
palabra clave
y se utiliza para proporcionar
tipos atómicos
en C.
Se recomienda que las implementaciones garanticen que la representación de
_Atomic(T)
en C sea la misma que la de
std::atomic<T>
en C++ para todo tipo posible
T
. Los mecanismos utilizados para garantizar atomicidad y ordenamiento de memoria deben ser compatibles.
En GCC y Clang, parte de la funcionalidad descrita aquí requiere enlazar con
-latomic
.
| Macro de prueba de características | Valor | Estándar | Característica |
|---|---|---|---|
__cpp_lib_atomic_ref
|
201806L
|
(C++20) |
std::atomic_ref
|
__cpp_lib_constexpr_atomic
|
202411L
|
(C++26) |
constexpr
std::atomic
y
std::atomic_ref
|
Ejemplo
#include <atomic> #include <iostream> #include <thread> #include <vector> std::atomic_int acnt; int cnt; void f() { for (auto n{10000}; n; --n) { ++acnt; ++cnt; // Note: for this example, relaxed memory order is sufficient, // e.g. acnt.fetch_add(1, std::memory_order_relaxed); } } int main() { { std::vector<std::jthread> pool; for (int n = 0; n < 10; ++n) pool.emplace_back(f); } std::cout << "The atomic counter is " << acnt << '\n' << "The non-atomic counter is " << cnt << '\n'; }
Salida posible:
The atomic counter is 100000 The non-atomic counter is 69696
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 |
|---|---|---|---|
| LWG 2441 | C++11 |
faltaban los typedefs para las versiones atómicas de los
tipos de enteros de ancho fijo opcionales |
añadidos |
| LWG 3012 | C++11 |
std::atomic<T>
estaba permitido para cualquier
T
que fuera trivialmente copiable pero no copiable |
tales especializaciones están prohibidas |
| LWG 3949 | C++17 |
la redacción que requería que
std
::
atomic
<
bool
>
tuviera un
destructor trivial se eliminó accidentalmente en C++17 |
restaurada |
|
LWG 4069
( P3323R1 ) |
C++11 |
el soporte para
T
calificado con cv era cuestionable
|
prohibir que
T
esté calificado con cv
|
| P0558R1 | C++11 |
la deducción de argumentos de plantilla para algunas
funciones de tipos atómicos podría fallar accidentalmente; se proporcionaron operaciones de puntero inválidas |
la especificación se reescribió sustancialmente:
se añadieron los typedefs miembro
value_type
y
difference_type
|
Véase también
|
(C++11)
|
el tipo atómico booleano libre de bloqueo
(clase) |
|
(C++20)
|
puntero compartido atómico
(especialización de plantilla de clase) |
|
(C++20)
|
puntero débil atómico
(especialización de plantilla de clase) |
|
Documentación de C
para
Tipos atómicos
|
|