std:: atomic
Defined in header
<atomic>
|
||
template
<
class
T
>
struct atomic ; |
(1) | (since C++11) |
template
<
class
U
>
struct atomic < U * > ; |
(2) | (since C++11) |
Defined in header
<memory>
|
||
template
<
class
U
>
struct atomic < std:: shared_ptr < U >> ; |
(3) | (since C++20) |
template
<
class
U
>
struct atomic < std:: weak_ptr < U >> ; |
(4) | (since C++20) |
Defined in header
<stdatomic.h>
|
||
#define _Atomic(T) /* see below */
|
(5) | (since C++23) |
Each instantiation and full specialization of the
std::atomic
template defines an atomic type. If one thread writes to an atomic object while another thread reads from it, the behavior is well-defined (see
memory model
for details on data races).
In addition, accesses to atomic objects may establish inter-thread synchronization and order non-atomic memory accesses as specified by std::memory_order .
std::atomic
is neither copyable nor movable.
The compatibility macro
It is unspecified whether any declaration in namespace
|
(since C++23) |
Specializations
Primary template
The primary
std::atomic
template may be instantiated with any
TriviallyCopyable
type
T
satisfying both
CopyConstructible
and
CopyAssignable
. The program is ill-formed if any of following values is
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; }; // user-defined trivially-copyable type std::atomic<Counters> cnt; // specialization for the user-defined type
std :: atomic < bool > uses the primary template. It is guaranteed to be a standard layout struct and has a trivial destructor .
Partial specializations
The standard library provides partial specializations of the
std::atomic
template for the following types with additional properties that the primary template does not have:
std::atomic<U*>
for all pointer types. These specializations have standard layout
, trivial default constructors,
(until C++20)
and trivial destructors. Besides the operations provided for all atomic types, these specializations additionally support atomic arithmetic operations appropriate to pointer types, such as
fetch_add
,
fetch_sub
.
3,4)
Partial specializations
std
::
atomic
<
std::
shared_ptr
<
U
>>
and
std
::
atomic
<
std::
weak_ptr
<
U
>>
are provided for
std::shared_ptr
and
std::weak_ptr
.
See std::atomic <std::shared_ptr> and std::atomic <std::weak_ptr> for details. |
(since C++20) |
Specializations for integral types
When instantiated with one of the following integral types,
std::atomic
provides additional atomic operations appropriate to integral types such as
fetch_add
,
fetch_sub
,
fetch_and
,
fetch_or
,
fetch_xor
:
-
- The character types char , char8_t (since C++20) , char16_t , char32_t , and wchar_t ;
- The standard signed integer types: signed char , short , int , long , and long long ;
- The standard unsigned integer types: unsigned char , unsigned short , unsigned int , unsigned long , and unsigned long long ;
- Any additional integral types needed by the typedefs in the header <cstdint> .
Additionally, the resulting
std::atomic<
Integral
>
specialization has standard layout
, a trivial default constructor,
(until C++20)
and a trivial destructor. Signed integer arithmetic is defined to use two's complement; there are no undefined results.
Specializations for floating-point types
When instantiated with one of the cv-unqualified floating-point types (
float
,
double
,
long
double
and cv-unqualified
extended floating-point types
(since C++23)
),
Additionally, the resulting
No operations result in undefined behavior even if the result is not representable in the floating-point type. The floating-point environment in effect may be different from the calling thread's floating-point environment. |
(since C++20) |
Member types
Member type | Definition |
value_type
|
T
(regardless of whether specialized or not)
|
difference_type
|
value_type
(only for
atomic<
Integral
>
and
atomic<
Floating
>
(since C++20)
specializations)
std::ptrdiff_t (only for
std::atomic<U*>
specializations)
|
difference_type
is not defined in the primary
std::atomic
template or in the partial specializations for
std::shared_ptr
and
std::weak_ptr
.
Member functions
constructs an atomic object
(public member function) |
|
stores a value into an atomic object
(public member function) |
|
checks if the atomic object is lock-free
(public member function) |
|
atomically replaces the value of the atomic object with a non-atomic argument
(public member function) |
|
atomically obtains the value of the atomic object
(public member function) |
|
loads a value from an atomic object
(public member function) |
|
atomically replaces the value of the atomic object and obtains the value held previously
(public member function) |
|
atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not
(public member function) |
|
(C++20)
|
blocks the thread until notified and the atomic value changes
(public member function) |
(C++20)
|
notifies at least one thread waiting on the atomic object
(public member function) |
(C++20)
|
notifies all threads blocked waiting on the atomic object
(public member function) |
Constants |
|
[static]
(C++17)
|
indicates that the type is always lock-free
(public static member constant) |
Specialized member functions
Specialized for integral , floating-point (since C++20) and pointer types |
|
atomically adds the argument to the value stored in the atomic object and obtains the value held previously
(public member function) |
|
atomically subtracts the argument from the value stored in the atomic object and obtains the value held previously
(public member function) |
|
adds to or subtracts from the atomic value
(public member function) |
|
Specialized for integral and pointer types only |
|
(C++26)
|
atomically performs
std::max
between the argument and the value of the atomic object and obtains the value held previously
(public member function) |
(C++26)
|
atomically performs
std::min
between the argument and the value of the atomic object and obtains the value held previously
(public member function) |
increments or decrements the atomic value by one
(public member function) |
|
Specialized for integral types only |
|
atomically performs bitwise AND between the argument and the value of the atomic object and obtains the value held previously
(public member function) |
|
atomically performs bitwise OR between the argument and the value of the atomic object and obtains the value held previously
(public member function) |
|
atomically performs bitwise XOR between the argument and the value of the atomic object and obtains the value held previously
(public member function) |
|
performs bitwise AND, OR, XOR with the atomic value
(public member function) |
Type aliases
Type aliases are provided for bool and all integral types listed above, as follows:
Aliases for all
|
|
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)
(optional)
|
std
::
atomic
<
std::
int8_t
>
(typedef) |
atomic_uint8_t
(C++11)
(optional)
|
std
::
atomic
<
std::
uint8_t
>
(typedef) |
atomic_int16_t
(C++11)
(optional)
|
std
::
atomic
<
std::
int16_t
>
(typedef) |
atomic_uint16_t
(C++11)
(optional)
|
std
::
atomic
<
std::
uint16_t
>
(typedef) |
atomic_int32_t
(C++11)
(optional)
|
std
::
atomic
<
std::
int32_t
>
(typedef) |
atomic_uint32_t
(C++11)
(optional)
|
std
::
atomic
<
std::
uint32_t
>
(typedef) |
atomic_int64_t
(C++11)
(optional)
|
std
::
atomic
<
std::
int64_t
>
(typedef) |
atomic_uint64_t
(C++11)
(optional)
|
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)
(optional)
|
std
::
atomic
<
std::
intptr_t
>
(typedef) |
atomic_uintptr_t
(C++11)
(optional)
|
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) |
Aliases for special-purpose types |
|
atomic_signed_lock_free
(C++20)
|
a signed integral atomic type that is lock-free and for which waiting/notifying is most efficient
(typedef) |
atomic_unsigned_lock_free
(C++20)
|
an unsigned integral atomic type that is lock-free and for which waiting/notifying is most efficient
(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.
|
(since C++20) |
Notes
There are non-member function template equivalents for all member functions of
std::atomic
. Those non-member functions may be additionally overloaded for types that are not specializations of
std::atomic
, but are able to guarantee atomicity. The only such type in the standard library is
std::
shared_ptr
<
U
>
.
_Atomic
is a
keyword
and used to provide
atomic types
in C.
Implementations are recommended to ensure that the representation of
_Atomic(T)
in C is same as that of
std::atomic<T>
in C++ for every possible type
T
. The mechanisms used to ensure atomicity and memory ordering should be compatible.
On gcc and clang, some of the functionality described here requires linking against
-latomic
.
Example
#include <atomic> #include <iostream> #include <thread> #include <vector> std::atomic_int acnt; int cnt; void f() { for (int n = 0; n < 10000; ++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'; }
Possible output:
The atomic counter is 100000 The non-atomic counter is 69696
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 2441 | C++11 |
typedefs for atomic versions of optional
fixed width integer types were missing |
added |
LWG 3012 | C++11 |
std::atomic<T>
was permitted for any
T
that is trivially copyable but not copyable |
such specializations are forbidden |
LWG 3949 | C++17 |
the wording requiring
std
::
atomic
<
bool
>
to have a
trivial destructor was accidently dropped in C++17 |
added back |
LWG 4069
( P3323R1 ) |
C++11 |
support for cv-qualified
T
was questionable
|
disallow
T
being cv-qualified
|
P0558R1 | C++11 |
template argument deduction for some
functions for atomic types might accidently fail; invalid pointer operations were provided |
specification was substantially rewritten:
member typedefs
value_type
and
difference_type
are added
|
See also
(C++11)
|
the lock-free boolean atomic type
(class) |
(C++20)
|
atomic shared pointer
(class template specialization) |
(C++20)
|
atomic weak pointer
(class template specialization) |
C documentation
for
Atomic types
|