<stdatomic.h> defines several macros and declares several types
and functions for performing atomic operations on data shared between
Implementations that define the macro
__STDC_NO_ATOMICS__ need not provide this header nor support any of its facilities.
The macros defined are the atomic lock-free macros
which indicate the lock-free property of the corresponding atomic types (both signed and unsigned); and
which expands to an initializer for an object of type
The types include
which is an enumerated type whose enumerators identify memory ordering constraints;
which is a structure type representing a lock-free, primitive atomic flag; and several atomic analogs of integer types.
In the following synopses:
- An A refers to one of the atomic types.
- A C refers to its corresponding non-atomic type.
- An M refers to the type of the other argument for arithmetic
operations. For atomic integer types, M is C. For atomic pointer types,
- The functions not ending in
_explicithave the same semantics as the corresponding
NOTE Many operations are volatile-qualified. The “volatile as device register” semantics have not changed in the standard. This qualification means that volatility is preserved when applying these operations to volatile objects.
#include <stdatomic.h> #define ATOMIC_VAR_INIT(C value)
The ATOMIC_VAR_INIT macro expands to a token sequence suitable for initializing an atomic object of a type that is initialization-compatible with value. An atomic object with automatic storage duration that is not explicitly initialized using ATOMIC_VAR_INIT is initially in an indeterminate state; however, the default (zero) initialization for objects with static or thread-local storage duration is guaranteed to produce a valid state.
Concurrent access to the variable being initialized, even via an atomic operation, constitutes a data race.
atomic_int guide = ATOMIC_VAR_INIT(42);
31.2.2. The atomic_init generic function¶
#include <stdatomic.h> void atomic_init(volatile A *obj, C value);
atomic_init generic function initializes the atomic object pointed to
by obj to the value value, while also initializing any additional state that
the implementation might need to carry for the atomic object.
Although this function initializes an atomic object, it does not avoid data races; concurrent access to the variable being initialized, even via an atomic operation, constitutes a data race.
The atomic_init generic function returns no value.
atomic_int guide; atomic_init(&guide, 42);
31.3. Order and consistency¶
The enumerated type
memory_order specifies the detailed regular
(non-atomic) memory synchronization operations as defined in (iso.220.127.116.11 and
may provide for operation ordering. Its enumeration constants are as follows:
memory_order_relaxed, no operation orders memory.
memory_order_release, memory_order_acq_rel and
memory_order_seq_cst, a store operation performs a release operation on the
affected memory location.
memory_order_acquire, memory_order_acq_rel and
memory_order_seq_cst, a load operation performs an acquire operation on the
affected memory location.
memory_order_consume, a load operation performs a consume operation on
the affected memory location.
There shall be a single total order
S on all
operations, consistent with the “happens before” order and modification orders
for all affected locations, such that each
B that loads a value from an atomic object M observes one of the following
the result of the last modification A of M that precedes B in S, if it exists, or
if A exists, the result of some modification of M in the visible sequence of side effects with respect to B that is not
memory_order_seq_cstand that does not happen before A, or
if A does not exist, the result of some modification of M in the visible sequence of side effects with respect to B that is not
Although it is not explicitly required that S include lock operations, it can always be extended to an order that does include lock and unlock operations, since the ordering between those is already included in the “happens before” ordering.
Atomic operations specifying
memory_order_relaxedare relaxed only with respect to memory ordering. Implementations must still guarantee that any given atomic access to a particular atomic object be indivisible with respect to all other atomic accesses to that object.
For an atomic operation B that reads the value of an atomic object M, if
there is a
memory_order_seq_cst fence X sequenced before B, then B
observes either the last
memory_order_seq_cst modification of M preceding
X in the total order S or a later modification of M in its modification
For atomic operations A and B on an atomic object M, where A modifies
M and B takes its value, if there is a
memory_order_seq_cst fence X
such that A is sequenced before X and B follows X in S, then B
observes either the effects of A or a later modification of M in its
For atomic operations A and B on an atomic object M, where A modifies M and B takes its value, if there are memory_order_seq_cst fences X and Y such that A is sequenced before X, Y is sequenced before B, and X precedes Y in S, then B observes either the effects of A or a later modification of M in its modification order.
Atomic read-modify-write operations shall always read the last value (in the modification order) stored before the write associated with the read-modify-write operation.
An atomic store shall only store a value that has been computed from constants and program input values by a finite sequence of program evaluations, such that each evaluation observes the values of variables as computed by the last prior assignment in the sequence. The ordering of evaluations in this sequence shall be such that
If an evaluation B observes a value computed by A in a different thread, then B does not happen before A. If an evaluation A is included in the sequence, then all evaluations that assign to the same variable and happen before A are also included.
|||(1, 2) See “future library direction” (iso.7.31.8).|