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.
Atomic operations are of the following types:
- Store: Writes
- Load: Reads
- Read-modify-write(RMW): Reads and then writes. Note: This is one atomic operation, not several.
All atomic operations have their memory order, which determines the strictness of the restrictions on instruction reordering and the visibility requirements. Note that the standard requires that read-modify-write operations must each time read the value of the last write in the modification order preceding the associated write operation (in other words, RMW operations always read the latest value).
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>::valuestd::is_copy_constructible<T>::valuestd::is_move_constructible<T>::valuestd::is_copy_assignable<T>::valuestd::is_move_assignable<T>::valuestd::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, andwchar_t; - The standard signed integer types:
signed char,short,int,long, andlong long; - The standard unsigned integer types:
unsigned char,unsigned short,unsigned int,unsigned long, andunsigned long long; - Any additional integral types needed by the typedefs in the header <cstdint>.
- The character types
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 typesWhen instantiated with one of the cv-unqualified floating-point types ( 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
| Type | Definition | ||||
value_type
|
T (regardless of whether specialized or not)
| ||||
difference_type[1]
|
|
- ↑
difference_typeis not defined in the primarystd::atomictemplate 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
| |
(C++11) |
std::atomic<bool> (typedef) |
(C++11) |
std::atomic<char> (typedef) |
(C++11) |
std::atomic<signed char> (typedef) |
(C++11) |
std::atomic<unsigned char> (typedef) |
(C++11) |
std::atomic<short> (typedef) |
(C++11) |
std::atomic<unsigned short> (typedef) |
(C++11) |
std::atomic<int> (typedef) |
(C++11) |
std::atomic<unsigned int> (typedef) |
(C++11) |
std::atomic<long> (typedef) |
(C++11) |
std::atomic<unsigned long> (typedef) |
(C++11) |
std::atomic<long long> (typedef) |
(C++11) |
std::atomic<unsigned long long> (typedef) |
(C++20) |
std::atomic<char8_t> (typedef) |
(C++11) |
std::atomic<char16_t> (typedef) |
(C++11) |
std::atomic<char32_t> (typedef) |
(C++11) |
std::atomic<wchar_t> (typedef) |
(C++11)(optional) |
std::atomic<std::int8_t> (typedef) |
(C++11)(optional) |
std::atomic<std::uint8_t> (typedef) |
(C++11)(optional) |
std::atomic<std::int16_t> (typedef) |
(C++11)(optional) |
std::atomic<std::uint16_t> (typedef) |
(C++11)(optional) |
std::atomic<std::int32_t> (typedef) |
(C++11)(optional) |
std::atomic<std::uint32_t> (typedef) |
(C++11)(optional) |
std::atomic<std::int64_t> (typedef) |
(C++11)(optional) |
std::atomic<std::uint64_t> (typedef) |
(C++11) |
std::atomic<std::int_least8_t> (typedef) |
(C++11) |
std::atomic<std::uint_least8_t> (typedef) |
(C++11) |
std::atomic<std::int_least16_t> (typedef) |
(C++11) |
std::atomic<std::uint_least16_t> (typedef) |
(C++11) |
std::atomic<std::int_least32_t> (typedef) |
(C++11) |
std::atomic<std::uint_least32_t> (typedef) |
(C++11) |
std::atomic<std::int_least64_t> (typedef) |
(C++11) |
std::atomic<std::uint_least64_t> (typedef) |
(C++11) |
std::atomic<std::int_fast8_t> (typedef) |
(C++11) |
std::atomic<std::uint_fast8_t> (typedef) |
(C++11) |
std::atomic<std::int_fast16_t> (typedef) |
(C++11) |
std::atomic<std::uint_fast16_t> (typedef) |
(C++11) |
std::atomic<std::int_fast32_t> (typedef) |
(C++11) |
std::atomic<std::uint_fast32_t> (typedef) |
(C++11) |
std::atomic<std::int_fast64_t> (typedef) |
(C++11) |
std::atomic<std::uint_fast64_t> (typedef) |
(C++11)(optional) |
std::atomic<std::intptr_t> (typedef) |
(C++11)(optional) |
std::atomic<std::uintptr_t> (typedef) |
(C++11) |
std::atomic<std::size_t> (typedef) |
(C++11) |
std::atomic<std::ptrdiff_t> (typedef) |
(C++11) |
std::atomic<std::intmax_t> (typedef) |
(C++11) |
std::atomic<std::uintmax_t> (typedef) |
Aliases for special-purpose types | |
(C++20) |
a signed integral atomic type that is lock-free and for which waiting/notifying is most efficient (typedef) |
(C++20) |
an unsigned integral atomic type that is lock-free and for which waiting/notifying is most efficient (typedef) |
Note: std::atomic_intN_t, std::atomic_uintN_t, std::atomic_intptr_t, and std::atomic_uintptr_t are defined if and only if std::intN_t, std::uintN_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.
| Feature-test macro | Value | Std | Feature |
|---|---|---|---|
__cpp_lib_atomic_ref |
201806L |
(C++20) | std::atomic_ref
|
__cpp_lib_constexpr_atomic |
202411L |
(C++26) | constexpr std::atomic and std::atomic_ref
|
Example
#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';
}
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 Tthat is trivially copyable but not copyable |
such specializations are forbidden |
| LWG 3949 | C++17 | the wording requiring std::atomic<bool> to have atrivial 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_typeand 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
| |