◆ _Atomic

#define _Atomic (   T)    P99_PASTE2(atomic_, T)

refer to an atomic type of base type T

Ta type name

This implements only part of the _Atomic keyword of C11. First it implements only the part described in, atomic type specifiers. I does not cover type qualifiers.

Second for data types that are not predefined integer or floating point types, the underlying realization of the atomic type must have been previously declared with P99_DECLARE_ATOMIC.

Besides the atomic integer types that are listed in the standard we provide 6 atomic types for all real and complex floating point types, as long as they exist.

For the standard predefined integer types there are different atomic types as they are listed in the standard. The atomic types for the floating point types (as there are no names listed in the standard) are chosen arbitrarily with an atomic_ prefix. Don't rely on a particular naming. Whenever _Atomic is called with a typename T that resolves to one of the predefined arithmetic types (without enum and pointers) the same type as for the original type results: e.g if unsigned is 32 bit wide (and long is 64)

_Atomic(uint32_t) a;
_Atomic(unsigned) b;

is equivalent to

These types don't work with the usual operators such as +=, and a variable of such an atomic type doesn't evaluate to an rvalue of the base type.
These variables are guaranteed to be in a valid state when they are 0 initialized by the default initializer, either explicitly or when declared with static storage location. The initial value of the base type corresponds to its 0 initialized value.
See also
ATOMIC_VAR_INIT for an initializer macro
atomic_init for a initializer function
atomic_load to return an rvalue of the underlying base type T
atomic_store to store a value that is compatible with T
atomic_compare_exchange_weak to store a value conditionally

With the exception of the floating point types, these latter three operations are lock-free if a lock-free low-level function is implemented for an unsigned integer type with the same width. This should usually be the case for all integer types, including enum, and pointer types.

If the underlying operations are defined for T the following generic functions (macros) can be used with an atomic type:

See also
atomic_fetch_add to add a value to the object as += would on T. This should be lock-free for all integer types (see above) and is not lock-free for floating point types.
atomic_fetch_sub to subtract a value as -= would on T. See atomic_fetch_add for constraints.
atomic_fetch_or "or" a value in place as |= would on T
atomic_fetch_and "and" a value in place as &= would on T
atomic_fetch_xor "exclusive or" a value in place as ^= would on T
Don't assign atomic variables through the = operator. This will most probably not do what you expect:
  • This would copy state information from the right side to the left side.
  • Neither the read access on the right side nor the write access on the left side would be atomic.
Don't use atomic variables as function arguments.
  • If you are only interested in the value evaluate by atomic_load.
  • Otherwise pass it through a pointer to atomic type.

Definition at line 858 of file p99_atomic.h.