| Home | Libraries | People | FAQ | More

## Programming interfaces

### Configuration and building

The library contains header-only and compiled parts. The library is header-only for lock-free cases but requires a separate binary to implement the lock-based emulation. Users are able to detect whether linking to the compiled part is required by checking the feature macros.

The following macros affect library behavior:

Macro | Description
--- | ---

`BOOST_ATOMIC_NO_CMPXCHG8B`

Affects 32-bit x86 Oracle Studio builds. When defined, the library assumes the target CPU does not support `cmpxchg8b` instruction used to support 64-bit atomic operations. This is the case with very old CPUs (pre-Pentium). The library does not perform runtime detection of this instruction, so running the code that uses 64-bit atomics on such CPUs will result in crashes, unless this macro is defined. Note that the macro does not affect MSVC, GCC and compatible compilers because the library infers this information from the compiler-defined macros.

`BOOST_ATOMIC_NO_CMPXCHG16B`

Affects 64-bit x86 MSVC and Oracle Studio builds. When defined, the library assumes the target CPU does not support `cmpxchg16b` instruction used to support 128-bit atomic operations. This is the case with some early 64-bit AMD CPUs, all Intel CPUs and current AMD CPUs support this instruction. The library does not perform runtime detection of this instruction, so running the code that uses 128-bit atomics on such CPUs will result in crashes, unless this macro is defined. Note that the macro does not affect GCC and compatible compilers because the library infers this information from the compiler-defined macros.

`BOOST_ATOMIC_NO_MFENCE`

Affects 32-bit x86 Oracle Studio builds. When defined, the library assumes the target CPU does not support `mfence` instruction used to implement thread fences. This instruction was added with SSE2 instruction set extension, which was available in CPUs since Intel Pentium 4. The library does not perform runtime detection of this instruction, so running the library code on older CPUs will result in crashes, unless this macro is defined. Note that the macro does not affect MSVC, GCC and compatible compilers because the library infers this information from the compiler-defined macros.

`BOOST_ATOMIC_NO_FLOATING_POINT` | When defined, support for floating point operations is disabled. Floating point types shall be treated similar to trivially copyable structs and no capability macros will be defined.
`BOOST_ATOMIC_FORCE_FALLBACK` | When defined, all operations are implemented with locks. This is mostly used for testing and should not be used in real world projects.
`BOOST_ATOMIC_DYN_LINK` and `BOOST_ALL_DYN_LINK` | Control library linking. If defined, the library assumes dynamic linking, otherwise static. The latter macro affects all Boost libraries, not just Boost.Atomic.
`BOOST_ATOMIC_NO_LIB` and `BOOST_ALL_NO_LIB` | Control library auto-linking on Windows. When defined, disables auto-linking. The latter macro affects all Boost libraries, not just Boost.Atomic.

Besides macros, it is important to specify the correct compiler options for the target CPU. With GCC and compatible compilers this affects whether particular atomic operations are lock-free or not.

Boost building process is described in the Getting Started guide. For example, you can build Boost.Atomic with the following command line:

    bjam --with-atomic variant=release instruction-set=core2 stage

### Memory order

    #include <boost/memory_order.hpp>

The enumeration `boost::memory_order` defines the following values to represent memory ordering constraints:

Constant | Description
--- | ---

`memory_order_relaxed`

No ordering constraint. Informally speaking, following operations may be reordered before, preceding operations may be reordered after the atomic operation. This constraint is suitable only when either a) further operations do not depend on the outcome of the atomic operation or b) ordering is enforced through stand-alone `atomic_thread_fence` operations. The operation on the atomic value itself is still atomic though.

`memory_order_release` | Perform `release` operation. Informally speaking, prevents all preceding memory operations to be reordered past this point.
`memory_order_acquire` | Perform `acquire` operation. Informally speaking, prevents succeeding memory operations to be reordered before this point.
`memory_order_consume` | Perform `consume` operation. More relaxed (and on some architectures more efficient) than `memory_order_acquire` as it only affects succeeding operations that are computationally-dependent on the value retrieved from an atomic variable.
`memory_order_acq_rel` | Perform both `release` and `acquire` operation
`memory_order_seq_cst` | Enforce sequential consistency. Implies `memory_order_acq_rel`, but additionally enforces total order for all operations such qualified.

For compilers that support C++11 scoped enums, the library also defines scoped synonyms that are preferred in modern programs:

Pre-C++11 constant | C++11 equivalent
--- | ---
`memory_order_relaxed` | `memory_order::relaxed`
`memory_order_release` | `memory_order::release`
`memory_order_acquire` | `memory_order::acquire`
`memory_order_consume` | `memory_order::consume`
`memory_order_acq_rel` | `memory_order::acq_rel`
`memory_order_seq_cst` | `memory_order::seq_cst`

See section happens-before for explanation of the various ordering constraints.

### Atomic flags

    #include <boost/atomic/atomic_flag.hpp>

The `boost::atomic_flag` type provides the most basic set of atomic operations suitable for implementing mutually exclusive access to thread-shared data. The flag can have one of the two possible states: set and clear. The class implements the following operations:

Syntax | Description
--- | ---
`atomic_flag()` | Initialize to the clear state. See the discussion below.
`bool test_and_set(memory_order order)` | Sets the atomic flag to the set state; returns `true` if the flag had been set prior to the operation
`void clear(memory_order order)` | Sets the atomic flag to the clear state

`order` always has `memory_order_seq_cst` as default parameter.

Note that the default constructor `atomic_flag()` is unlike `std::atomic_flag`, which leaves the default-constructed object uninitialized. This potentially requires dynamic initialization during the program startup to perform the object initialization, which makes it unsafe to create global `boost::atomic_flag` objects that can be used before entring `main()`. Some compilers though (especially those supporting C++11 `constexpr`) may be smart enough to perform flag initialization statically (which is, in C++11 terms, a constant initialization).

This difference is deliberate and is done to support C++03 compilers. C++11 defines the `ATOMIC_FLAG_INIT` macro which can be used to statically initialize `std::atomic_flag` to a clear state like this:

    std::atomic_flag flag = ATOMIC_FLAG_INIT; // constant initialization

This macro cannot be implemented in C++03 because for that `atomic_flag` would have to be an aggregate type, which it cannot be because it has to prohibit copying and consequently define the default constructor. Thus the closest equivalent C++03 code using Boost.Atomic would be:

    boost::atomic_flag flag; // possibly, dynamic initialization in C++03;
                             // constant initialization in C++11

The same code is also valid in C++11, so this code can be used universally. However, for interface parity with `std::atomic_flag`, if possible, the library also defines the `BOOST_ATOMIC_FLAG_INIT` macro, which is equivalent to `ATOMIC_FLAG_INIT`:

    boost::atomic_flag flag = BOOST_ATOMIC_FLAG_INIT; // constant initialization

This macro will only be implemented on a C++11 compiler. When this macro is not available, the library defines `BOOST_ATOMIC_NO_ATOMIC_FLAG_INIT`.

### Atomic objects

    #include <boost/atomic/atomic.hpp>

`boost::atomic<T>` provides methods for atomically accessing variables of a suitable type `T`. The type is suitable if it is trivially copyable (3.9/9 [basic.types]). Following are examples of the types compatible with this requirement:

- a scalar type (e.g. integer, boolean, enum or pointer type)
- a `class` or `struct` that has no non-trivial copy or move constructors or assignment operators, has a trivial destructor, and that is comparable via `memcmp`.

Note that classes with virtual functions or virtual base classes do not satisfy the requirements. Also be warned that structures with "padding" between data members may compare non-equal via `memcmp` even though all members are equal. This may also be the case with some floating point types, which include padding bits themselves.

#### `boost::atomic<T>` template class

All atomic objects support the following operations and properties:

Syntax | Description
--- | ---
`atomic()` | Initialize to an unspecified value
`atomic(T initial_value)` | Initialize to `initial_value`
`bool is_lock_free()` | Checks if the atomic object is lock-free; the returned value is consistent with the `is_always_lock_free` static constant, see below
`T load(memory_order order)` | Return current value
`void store(T value, memory_order order)` | Write new value to atomic variable
`T exchange(T new_value, memory_order order)` | Exchange current value with `new_value`, returning current value
`bool compare_exchange_weak(T & expected, T desired, memory_order order)` | Compare current value with `expected`, change it to `desired` if matches. Returns `true` if an exchange has been performed, and always writes the previous value back in `expected`. May fail spuriously, so must generally be retried in a loop.
`bool compare_exchange_weak(T & expected, T desired, memory_order success_order, memory_order failure_order)` | Compare current value with `expected`, change it to `desired` if matches. Returns `true` if an exchange has been performed, and always writes the previous value back in `expected`. May fail spuriously, so must generally be retried in a loop.
`bool compare_exchange_strong(T & expected, T desired, memory_order order)` | Compare current value with `expected`, change it to `desired` if matches. Returns `true` if an exchange has been performed, and always writes the previous value back in `expected`.
`bool compare_exchange_strong(T & expected, T desired, memory_order success_order, memory_order failure_order))` | Compare current value with `expected`, change it to `desired` if matches. Returns `true` if an exchange has been performed, and always writes the previous value back in `expected`.
`static bool is_always_lock_free` | This static boolean constant indicates if any atomic object of this type is lock-free

`order` always has `memory_order_seq_cst` as default parameter.

The `compare_exchange_weak`/`compare_exchange_strong` variants taking four parameters differ from the three parameter variants in that they allow a different memory ordering constraint to be specified in case the operation fails.

In addition to these explicit operations, each `atomic<T>` object also supports implicit `store` and `load` through the use of "assignment" and "conversion to `T`" operators. Avoid using these operators, as they do not allow to specify a memory ordering constraint which always defaults to `memory_order_seq_cst`.

#### `boost::atomic<integral>` template class

In addition to the operations listed in the previous section, `boost::atomic<I>` for integral types `I`, except `bool`, supports the following operations, which correspond to `std::atomic<I>`:

Syntax | Description
--- | ---
`I fetch_add(I v, memory_order order)` | Add `v` to variable, returning previous value
`I fetch_sub(I v, memory_order order)` | Subtract `v` from variable, returning previous value
`I fetch_and(I v, memory_order order)` | Apply bit-wise "and" with `v` to variable, returning previous value
`I fetch_or(I v, memory_order order)` | Apply bit-wise "or" with `v` to variable, returning previous value
`I fetch_xor(I v, memory_order order)` | Apply bit-wise "xor" with `v` to variable, returning previous value

Additionally, as a Boost.Atomic extension, the following operations are also provided:

Syntax | Description
--- | ---
`I fetch_negate(memory_order order)` | Change the sign of the value stored in the variable, returning previous value
`I fetch_complement(memory_order order)` | Set the variable to the one's complement of the current value, returning previous value
`I negate(memory_order order)` | Change the sign of the value stored in the variable, returning the result
`I add(I v, memory_order order)` | Add `v` to variable, returning the result
`I sub(I v, memory_order order)` | Subtract `v` from variable, returning the result
`I bitwise_and(I v, memory_order order)` | Apply bit-wise "and" with `v` to variable, returning the result
`I bitwise_or(I v, memory_order order)` | Apply bit-wise "or" with `v` to variable, returning the result
`I bitwise_xor(I v, memory_order order)` | Apply bit-wise "xor" with `v` to variable, returning the result
`I bitwise_complement(memory_order order)` | Set the variable to the one's complement of the current value, returning the result
`void opaque_negate(memory_order order)` | Change the sign of the value stored in the variable, returning nothing
`void opaque_add(I v, memory_order order)` | Add `v` to variable, returning nothing
`void opaque_sub(I v, memory_order order)` | Subtract `v` from variable, returning nothing
`void opaque_and(I v, memory_order order)` | Apply bit-wise "and" with `v` to variable, returning nothing
`void opaque_or(I v, memory_order order)` | Apply bit-wise "or" with `v` to variable, returning nothing
`void opaque_xor(I v, memory_order order)` | Apply bit-wise "xor" with `v` to variable, returning nothing
`void opaque_complement(memory_order order)` | Set the variable to the one's complement of the current value, returning nothing
`bool negate_and_test(memory_order order)` | Change the sign of the value stored in the variable, returning `true` if the result is non-zero and `false` otherwise
`bool add_and_test(I v, memory_order order)` | Add `v` to variable, returning `true` if the result is non-zero and `false` otherwise
`bool sub_and_test(I v, memory_order order)` | Subtract `v` from variable, returning `true` if the result is non-zero and `false` otherwise
`bool and_and_test(I v, memory_order order)` | Apply bit-wise "and" with `v` to variable, returning `true` if the result is non-zero and `false` otherwise
`bool or_and_test(I v, memory_order order)` | Apply bit-wise "or" with `v` to variable, returning `true` if the result is non-zero and `false` otherwise
`bool xor_and_test(I v, memory_order order)` | Apply bit-wise "xor" with `v` to variable, returning `true` if the result is non-zero and `false` otherwise
`bool complement_and_test(memory_order order)` | Set the variable to the one's complement of the current value, returning `true` if the result is non-zero and `false` otherwise
`bool bit_test_and_set(unsigned int n, memory_order order)` | Set bit number `n` in the variable to 1, returning `true` if the bit was previously set to 1 and `false` otherwise
`bool bit_test_and_reset(unsigned int n, memory_order order)` | Set bit number `n` in the variable to 0, returning `true` if the bit was previously set to 1 and `false` otherwise
`bool bit_test_and_complement(unsigned int n, memory_order order)` | Change bit number `n` in the variable to the opposite value, returning `true` if the bit was previously set to 1 and `false` otherwise

| Note

In Boost.Atomic 1.66 the `op_and_test` operations returned the opposite value (i.e. `true` if the result is zero). This was changed to the current behavior in 1.67 for consistency with other operations in Boost.Atomic, as well as with conventions taken in the C++ standard library. Boost.Atomic 1.66 was the only release shipped with the old behavior. Users upgrading from Boost 1.66 to a later release can define `BOOST_ATOMIC_HIGHLIGHT_OP_AND_TEST` macro when building their code to generate deprecation warnings on the `op_and_test` function calls (the functions are not actually deprecated though; this is just a way to highlight their use).

`order` always has `memory_order_seq_cst` as default parameter.

The `opaque_op` and `op_and_test` variants of the operations may result in a more efficient code on some architectures because the original value of the atomic variable is not preserved. In the `bit_test_and_op` operations, the bit number `n` starts from 0, which means the least significand bit, and must not exceed `std::numeric_limits<I>::digits - 1`.

In addition to these explicit operations, each `boost::atomic<I>` object also supports implicit pre-/post- increment/decrement, as well as the operators `+=`, `-=`, `&=`, `|=` and `^=`. Avoid using these operators, as they do not allow to specify a memory ordering constraint which always defaults to `memory_order_seq_cst`.

#### `boost::atomic<floating-point>` template class

| Note
The support for floating point types is optional and can be disabled by defining `BOOST_ATOMIC_NO_FLOATING_POINT`.

In addition to the operations applicable to all atomic objects, `boost::atomic<F>` for floating point types `F` supports the following operations, which correspond to `std::atomic<F>`:

Syntax | Description
--- | ---
`F fetch_add(F v, memory_order order)` | Add `v` to variable, returning previous value
`F fetch_sub(F v, memory_order order)` | Subtract `v` from variable, returning previous value

Additionally, as a Boost.Atomic extension, the following operations are also provided:

Syntax | Description
--- | ---
`F fetch_negate(memory_order order)` | Change the sign of the value stored in the variable, returning previous value
`F negate(memory_order order)` | Change the sign of the value stored in the variable, returning the result
`F add(F v, memory_order order)` | Add `v` to variable, returning the result
`F sub(F v, memory_order order)` | Subtract `v` from variable, returning the result
`void opaque_negate(memory_order order)` | Change the sign of the value stored in the variable, returning nothing
`void opaque_add(F v, memory_order order)` | Add `v` to variable, returning nothing
`void opaque_sub(F v, memory_order order)` | Subtract `v` from variable, returning nothing

`order` always has `memory_order_seq_cst` as default parameter.

The `opaque_op` variants of the operations may result in a more efficient code on some architectures because the original value of the atomic variable is not preserved.

In addition to these explicit operations, each `boost::atomic<F>` object also supports operators `+=` and `-=`. Avoid using these operators, as they do not allow to specify a memory ordering constraint which always defaults to `memory_order_seq_cst`.

When using atomic operations with floating point types, bear in mind that Boost.Atomic always performs bitwise comparison of the stored values. This means that operations like `compare_exchange*` may fail if the stored value and comparand have different binary representation, even if they would normally compare equal. This is typically the case when either of the numbers is denormalized. This also means that the behavior with regard to special floating point values like NaN and signed zero is also different from normal C++.

Another source of the problem is padding bits that are added to some floating point types for alignment. One widespread example of that is Intel x87 extended double format, which is typically stored as 80 bits of value padded with 16 or 48 unused bits. These padding bits are often uninitialized and contain garbage, which makes two equal numbers have different binary representation. The library attempts to account for the known such cases, but in general it is possible that some platforms are not covered. Note that the C++ standard makes no guarantees about reliability of `compare_exchange*` operations in the face of padding or trap bits.

#### `boost::atomic<pointer>` template class

In addition to the operations applicable to all atomic objects, `boost::atomic<P>` for pointer types `P` (other than pointers to `void`, function or member pointers) support the following operations, which correspond to `std::atomic<P>`:

Syntax | Description
--- | ---
`T fetch_add(ptrdiff_t v, memory_order order)` | Add `v` to variable, returning previous value
`T fetch_sub(ptrdiff_t v, memory_order order)` | Subtract `v` from variable, returning previous value

Similarly to integers, the following Boost.Atomic extensions are also provided:

Syntax | Description
--- | ---
`void add(ptrdiff_t v, memory_order order)` | Add `v` to variable, returning the result
`void sub(ptrdiff_t v, memory_order order)` | Subtract `v` from variable, returning the result
`void opaque_add(ptrdiff_t v, memory_order order)` | Add `v` to variable, returning nothing
`void opaque_sub(ptrdiff_t v, memory_order order)` | Subtract `v` from variable, returning nothing
`bool add_and_test(ptrdiff_t v, memory_order order)` | Add `v` to variable, returning `true` if the result is non-null and `false` otherwise
`bool sub_and_test(ptrdiff_t v, memory_order order)` | Subtract `v` from variable, returning `true` if the result is non-null and `false` otherwise

`order` always has `memory_order_seq_cst` as default parameter.

In addition to these explicit operations, each `boost::atomic<P>` object also supports implicit pre-/post- increment/decrement, as well as the operators `+=`, `-=`. Avoid using these operators, as they do not allow explicit specification of a memory ordering constraint which always defaults to `memory_order_seq_cst`.

#### `boost::atomic<T>` convenience typedefs

For convenience, several shorthand typedefs of `boost::atomic<T>` are provided:

    typedef atomic< char > atomic_char;
    typedef atomic< unsigned char > atomic_uchar;
    typedef atomic< signed char > atomic_schar;
    typedef atomic< unsigned short > atomic_ushort;
    typedef atomic< short > atomic_short;
    typedef atomic< unsigned int > atomic_uint;
    typedef atomic< int > atomic_int;
    typedef atomic< unsigned long > atomic_ulong;
    typedef atomic< long > atomic_long;
    typedef atomic< unsigned long long > atomic_ullong;
    typedef atomic< long long > atomic_llong;

    typedef atomic< void* > atomic_address;
    typedef atomic< bool > atomic_bool;
    typedef atomic< wchar_t > atomic_wchar_t;
    typedef atomic< char16_t > atomic_char16_t;
    typedef atomic< char32_t > atomic_char32_t;

    typedef atomic< uint8_t > atomic_uint8_t;
    typedef atomic< int8_t > atomic_int8_t;
    typedef atomic< uint16_t > atomic_uint16_t;
    typedef atomic< int16_t > atomic_int16_t;
    typedef atomic< uint32_t > atomic_uint32_t;
    typedef atomic< int32_t > atomic_int32_t;
    typedef atomic< uint64_t > atomic_uint64_t;
    typedef atomic< int64_t > atomic_int64_t;

    typedef atomic< int_least8_t > atomic_int_least8_t;
    typedef atomic< uint_least8_t > atomic_uint_least8_t;
    typedef atomic< int_least16_t > atomic_int_least16_t;
    typedef atomic< uint_least16_t > atomic_uint_least16_t;
    typedef atomic< int_least32_t > atomic_int_least32_t;
    typedef atomic< uint_least32_t > atomic_uint_least32_t;
    typedef atomic< int_least64_t > atomic_int_least64_t;
    typedef atomic< uint_least64_t > atomic_uint_least64_t;
    typedef atomic< int_fast8_t > atomic_int_fast8_t;
    typedef atomic< uint_fast8_t > atomic_uint_fast8_t;
    typedef atomic< int_fast16_t > atomic_int_fast16_t;
    typedef atomic< uint_fast16_t > atomic_uint_fast16_t;
    typedef atomic< int_fast32_t > atomic_int_fast32_t;
    typedef atomic< uint_fast32_t > atomic_uint_fast32_t;
    typedef atomic< int_fast64_t > atomic_int_fast64_t;
    typedef atomic< uint_fast64_t > atomic_uint_fast64_t;
    typedef atomic< intmax_t > atomic_intmax_t;
    typedef atomic< uintmax_t > atomic_uintmax_t;

    typedef atomic< std::size_t > atomic_size_t;
    typedef atomic< std::ptrdiff_t > atomic_ptrdiff_t;

    typedef atomic< intptr_t > atomic_intptr_t;
    typedef atomic< uintptr_t > atomic_uintptr_t;

The typedefs are provided only if the corresponding type is available.

### Fences

    #include <boost/atomic/fences.hpp>

Syntax | Description
--- | ---
`void atomic_thread_fence(memory_order order)` | Issue fence for coordination with other threads.
`void atomic_signal_fence(memory_order order)` | Issue fence for coordination with signal handler (only in same thread).

### Feature testing macros

    #include <boost/atomic/capabilities.hpp>

Boost.Atomic defines a number of macros to allow compile-time detection whether an atomic data type is implemented using "true" atomic operations, or whether an internal "lock" is used to provide atomicity. The following macros will be defined to `0` if operations on the data type always require a lock, to `1` if operations on the data type may sometimes require a lock, and to `2` if they are always lock-free:

Macro | Description
--- | ---
`BOOST_ATOMIC_FLAG_LOCK_FREE` | Indicate whether `atomic_flag` is lock-free
`BOOST_ATOMIC_BOOL_LOCK_FREE` | Indicate whether `atomic<bool>` is lock-free
`BOOST_ATOMIC_CHAR_LOCK_FREE` | Indicate whether `atomic<char>` (including signed/unsigned variants) is lock-free
`BOOST_ATOMIC_CHAR16_T_LOCK_FREE` | Indicate whether `atomic<char16_t>` (including signed/unsigned variants) is lock-free
`BOOST_ATOMIC_CHAR32_T_LOCK_FREE` | Indicate whether `atomic<char32_t>` (including signed/unsigned variants) is lock-free
`BOOST_ATOMIC_WCHAR_T_LOCK_FREE` | Indicate whether `atomic<wchar_t>` (including signed/unsigned variants) is lock-free
`BOOST_ATOMIC_SHORT_LOCK_FREE` | Indicate whether `atomic<short>` (including signed/unsigned variants) is lock-free
`BOOST_ATOMIC_INT_LOCK_FREE` | Indicate whether `atomic<int>` (including signed/unsigned variants) is lock-free
`BOOST_ATOMIC_LONG_LOCK_FREE` | Indicate whether `atomic<long>` (including signed/unsigned variants) is lock-free
`BOOST_ATOMIC_LLONG_LOCK_FREE` | Indicate whether `atomic<long long>` (including signed/unsigned variants) is lock-free
`BOOST_ATOMIC_ADDRESS_LOCK_FREE` or `BOOST_ATOMIC_POINTER_LOCK_FREE` | Indicate whether `atomic<T *>` is lock-free
`BOOST_ATOMIC_THREAD_FENCE` | Indicate whether `atomic_thread_fence` function is lock-free
`BOOST_ATOMIC_SIGNAL_FENCE` | Indicate whether `atomic_signal_fence` function is lock-free

In addition to these standard macros, Boost.Atomic also defines a number of extension macros, which can also be useful. Like the standard ones, these macros are defined to values `0`, `1` and `2` to indicate whether the corresponding operations are lock-free or not.

Macro | Description
--- | ---
`BOOST_ATOMIC_INT8_LOCK_FREE` | Indicate whether `atomic<int8_type>` is lock-free.
`BOOST_ATOMIC_INT16_LOCK_FREE` | Indicate whether `atomic<int16_type>` is lock-free.
`BOOST_ATOMIC_INT32_LOCK_FREE` | Indicate whether `atomic<int32_type>` is lock-free.
`BOOST_ATOMIC_INT64_LOCK_FREE` | Indicate whether `atomic<int64_type>` is lock-free.
`BOOST_ATOMIC_INT128_LOCK_FREE` | Indicate whether `atomic<int128_type>` is lock-free.
`BOOST_ATOMIC_NO_ATOMIC_FLAG_INIT` | Defined after including `atomic_flag.hpp`, if the implementation does not support the `BOOST_ATOMIC_FLAG_INIT` macro for static initialization of `atomic_flag`. This macro is typically defined for pre-C++11 compilers.

In the table above, `intN_type` is a type that fits storage of contiguous `N` bits, suitably aligned for atomic operations.

For floating-point types the following macros are similarly defined:

Macro | Description
--- | ---
`BOOST_ATOMIC_FLOAT_LOCK_FREE` | Indicate whether `atomic<float>` is lock-free.
`BOOST_ATOMIC_DOUBLE_LOCK_FREE` | Indicate whether `atomic<double>` is lock-free.
`BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE` | Indicate whether `atomic<long double>` is lock-free.

These macros are not defined when support for floating point types is disabled by user.