Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Programming interfaces

Configuration and building
Memory order
Atomic objects
Fences
Feature testing macros

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_CMPXCHG16B

Affects 64-bit x86 MSVC 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_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
#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.

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

#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.

All atomic objects supports the following operations:

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

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.

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 explicit specification of a memory ordering constraint.

In addition to the operations listed in the previous section, boost::atomic<I> for integral types I supports the following operations:

Syntax

Description

T fetch_add(T v, memory_order order)

Add v to variable, returning previous value

T fetch_sub(T v, memory_order order)

Subtract v from variable, returning previous value

T fetch_and(T v, memory_order order)

Apply bit-wise "and" with v to variable, returning previous value

T fetch_or(T v, memory_order order)

Apply bit-wise "or" with v to variable, returning previous value

T fetch_xor(T v, memory_order order)

Apply bit-wise "xor" with v to variable, returning previous value

order always has memory_order_seq_cst as default parameter.

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 explicit specification of a memory ordering constraint.

In addition to the operations applicable to all atomic object, boost::atomic<P> for pointer types P (other than void pointers) support the following operations:

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

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.

#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).

#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.


PrevUpHomeNext