Template class for atomic operations.
template<typename T> atomic;
#include "tbb/atomic.h"
An atomic<T> supports atomic read, write, fetch-and-add, fetch-and-store, and compare-and-swap. Type T may be an integral type, enumeration type, or a pointer type. When T is a pointer type, arithmetic operations are interpreted as pointer arithmetic. For example, if x has type atomic<float*> and a float occupies four bytes, then ++x advances x by four bytes. Arithmetic on atomic<T> is not allowed if T is an enumeration type, void*, or bool.
Some of the methods have template method variants that permit more selective memory fencing. On IA-32 and Intel(R) 64 architecture processors, they have the same effect as the non-templated variants. On IA-64 architecture (Itanium®) processors, they may improve performance by allowing the memory subsystem more latitude on the orders of reads and write. Using them may improve performance. The table below shows the fencing for the non-template form.
Kind |
Description |
Default For |
---|---|---|
acquire |
Operations after the atomic operation never move over it. |
read |
release |
Operations before the atomic operation never move over it. |
write |
sequentially consistent |
Operations on either side never move over it and furthermore, the sequentially consistent atomic operations have a global order. |
fetch_and_store, fetch_and_add, compare_and_swap |
The copy constructor for class atomic<T> is not atomic. To atomically copy an atomic<T>, default-construct the copy first and assign to it. Below is an example that shows the difference.
atomic<T> y(x); // Not atomic atomic<T> z; z=x; // Atomic assignment
The copy constructor is not atomic because it is compiler generated. Introducing any non-trivial constructors might remove an important property of atomic<T>: namespace scope instances are zero-initialized before namespace scope dynamic initializers run. This property can be essential for code executing early during program startup.
To create an atomic<T> with a specific value, default-construct it first, and afterwards assign a value to it.
namespace tbb { enum memory_semantics { acquire, release }; struct atomic<T> { typedef T value_type; template<memory_semantics M> value_type compare_and_swap( value_type new_value, value_type comparand ); value_type compare_and_swap( value_type new_value, value_type comparand ); template<memory_semantics M> value_type fetch_and_store( value_type new_value ); value_type fetch_and_store( value_type new_value ); operator value_type() const; value_type operator=( value_type new_value ); atomic<T>& operator=( const atomic<T>& value ); // The following members exist only if T is an integral // or pointer type. template<memory_semantics M> value_type fetch_and_add( value_type addend ); value_type fetch_and_add( value_type addend ); template<memory_semantics M> value_type fetch_and_increment(); value_type fetch_and_increment(); template<memory_semantics M> value_type fetch_and_decrement(); value_type fetch_and_decrement(); value_type operator+=(value_type); value_type operator-=(value_type); value_type operator++(); value_type operator++(int); value_type operator--(); value_type operator--(int); }; }
So that an atomic<T*> can be used like a pointer to T, the specialization atomic<T*> also defines:
T* operator->() const;
Member | Description |
---|---|
memory_semantics Enum |
Defines values used to select the template variants that permit more selective control over visibility of operations (see the table above). |
value_type fetch_and_add( value_type addend ) |
Let x be the value of *this. Atomically updates x = x + addend. Returns: Original value of x. |
value_type fetch_and_increment() |
Let x be the value of *this. Atomically updates x = x + 1. Returns: Original value of x. |
value_type fetch_and_decrement() |
Let x be the value of *this. Atomically updates x = x - 1. Returns: Original value of x. |
value_type
compare_and_swap
value_type compare_and_swap( value_type new_value, value_type comparand ) |
Let x be the value of *this. Atomically compares x with comparand, and if they are equal, sets x=new_value. Returns: Original value of x. |
value_type fetch_and_store( value_type new_value ) |
Let x be the value of *this. Atomically exchanges old value of x with new_value. Returns: Original value of x. |