Overview
The atomic classes which provide synchronization thru interlocked atomic operations.
Details
atomic
An atomic class is template based and its instances are guaranteed to be thread safe during access, updates.
Certain POD types are also supported.
Specialization classes are defined for scalar data types such as boolean, integers, floating point, pointers etc, which provide additional atomic arithmetic and logical operations.
Additionally, atomic objects have the ability to synchronize access to other non-atomic objects in their threads by specifying different memory orders.
syntax
template< class T > struct atomic//specialization for pointers template< class U > struct atomic<U*>
member types
Name | Description |
---|---|
value_type | Template parameter - type of the data |
constructors
Name | Description |
---|---|
|
|
overloaded operators
Name | Description |
---|---|
T operator= (T val) | Atomically replaces the value with val. |
operator T() | Atomically loads and returns the current value of the atomic variable. Equivalent to load(). |
atomic<> derivative data types are declared as below.
atomic<int> i=5;
atomic_int j=10;
memory order
load(), store() and exchange() APIs also accept additional parameter for accepting memory order. It must be one of the following below.
Order | Description |
---|---|
memory_order_relaxed | There are no synchronization or ordering constraints imposed on other reads or writes, only this operation's atomicity is guaranteed |
memory_order_consume | A load operation with this memory order performs a consume operation on the affected memory location: no reads or writes in the current thread dependent on the value currently loaded can be reordered before this load. Writes to data-dependent variables in other threads that release the same atomic variable are visible in the current thread. On most platforms, this affects compiler optimizations only |
memory_order_acquire | A load operation with this memory order performs the acquire operation on the affected memory location: no reads or writes in the current thread can be reordered before this load. All writes in other threads that release the same atomic variable are visible in the current thread |
memory_order_release | A store operation with this memory order performs the release operation: no reads or writes in the current thread can be reordered after this store. All writes in the current thread are visible in other threads that acquire the same atomic variable and writes that carry a dependency into the atomic variable become visible in other threads that consume the same atomic. |
memory_order_acq_rel | A read-modify-write operation with this memory order is both an acquire operation and a release operation. No memory reads or writes in the current thread can be reordered before the load, nor after the store. All writes in other threads that release the same atomic variable are visible before the modification and the modification is visible in other threads that acquire the same atomic variable. |
memory_order_seq_cst | A load operation with this memory order performs an acquire operation, a store performs a release operation, and read-modify-write performs both an acquire operation and a release operation, plus a single total order exists in which all threads observe all modifications in the same order. |
methods
The following are general methods available to instances.
Name | Description |
---|---|
bool is_lock_free() | Checks if the atomic object is lock-free |
void store (T desired, memory_order order = memory_order_seq_cst ) | Atomically replaces the value of the atomic object with a non-atomic argument. Memory is affected according to the value of order which can be any of memory_order_relaxed, memory_order_release, memory_order_seq_cst |
T load (memory_order order = memory_order_seq_cst ) | Atomically obtains the value of the atomic object. Memory is affected according to the value of order which can be any of memory_order_relaxed, memory_order_consume, memory_order_acquire, memory_order_seq_cst. |
T exchange ( T desired, memory_order order = memory_order_seq_cst ) | Atomically replaces the value of the atomic object and obtains the value held previously. The entire operation is atomic (an atomic read-modify-write operation): the value is not affected by other threads between the instant its value is read (to be returned) and the moment it is modified by this function. Memory is affected according to the value of order which can be any of memory_order_relaxed, memory_order_consume, memory_order_acquire, memory_order_release, memory_order_acq_rel, memory_order_seq_cst. |
| Compares the contents of the atomic object's contained value with expected: - if true, it replaces the contained value with val (like store). - if false, it replaces expected with the contained value . The function always accesses the contained value to read it, and -if the comparison is true- it then also replaces it. But the entire operation is atomic: the value cannot be modified by other threads between the instant its value is read and the moment it is replaced. The memory order used in the 1st overload depends on the result of the comparison: if true, it uses success; if false, it uses failure. In the 2nd overload, memory is affected according to the value of order. Unlike compare_exchange_strong, this weak version is allowed to fail spuriously by returning false even when expected indeed compares equal to the contained object. This may be acceptable behavior for certain looping algorithms, and may lead to significantly better performance on some platforms. On these spurious failures, the function returns false while not modifying expected. For non-looping algorithms, compare_exchange_strong is generally preferred. |
| Behave same as compare_exchange_weak(). Unlike compare_exchange_weak(), this strong version is required to always return true when expected indeed compares equal to the contained object, not allowing spurious failures. However, on certain platforms, and for certain algorithms that check this in a loop, compare_exchange_weak may lead to significantly better performance. |
The following methods are defined for atomic class specialization for pointers.
Name | Description |
---|---|
T fetch_add (ptrdiff_t val, memory_order sync = memory_order_seq_cst) | Similar to += operation. Atomically adds val to the contained value and returns the previous value immediately before the operation. Memory is affected according to the value of sync. |
T fetch_sub (ptrdiff_t val, memory_order sync = memory_order_seq_cst) | Similar to -= operation. Atomically subtracts val to the contained value and returns the previous value immediately before the operation. Memory is affected according to the value of sync. |
T operator+= (ptrdiff_t val) | Same as fecth_add. |
T operator-= (ptrdiff_t val) | Same as fecth_sub. |
T operator++() T operator++ (int) | Same as pre and post increment operations for integral types. |
T operator--() T operator-- (int) | Same as pre and post decrement operations for integral types. |
The following methods are defined for atomic class specialization for floating types.
Name | Description |
---|---|
T fetch_add (T val, memory_order sync = memory_order_seq_cst) | Similar to += operation. Atomically adds val to the contained value and returns the previous value immediately before the operation. Memory is affected according to the value of sync. |
T fetch_sub (T val, memory_order sync = memory_order_seq_cst) | Similar to -= operation. Atomically subtracts val to the contained value and returns the previous value immediately before the operation. Memory is affected according to the value of sync. |
The following methods are defined for atomic class specialization for integral types.
Name | Description |
---|---|
T fetch_add (T val, memory_order sync = memory_order_seq_cst) | Similar to += operation. Atomically adds val to the contained value and returns the previous value immediately before the operation. Memory is affected according to the value of sync. |
T fetch_sub (T val, memory_order sync = memory_order_seq_cst) | Similar to -= operation. Atomically subtracts val to the contained value and returns the previous value immediately before the operation. Memory is affected according to the value of sync. |
T fetch_and (T val, memory_order sync = memory_order_seq_cst) | Atomically performs bitwise AND between the argument and the value of the atomic object and obtains the value held previously. Memory is affected according to the value of sync. |
T fetch_or (T val, memory_order sync = memory_order_seq_cst) | Atomically performs bitwise OR between the argument and the value of the atomic object and obtains the value held previously. Memory is affected according to the value of sync. |
T fetch_xor (T val, memory_order sync = memory_order_seq_cst) | atomically performs bitwise XOR between the argument and the value of the atomic object and obtains the value held previously. Memory is affected according to the value of sync. |
T operator++() T operator++ (int) |
The entire operation is atomic: the value cannot be modified between the instant its value is read and the moment it is modified by this function. |
T operator--() T operator-- (int) |
The entire operation is atomic: the value cannot be modified between the instant its value is read and the moment it is modified by this function. |
T operator+= (T val) | Same as fecth_add. |
T operator-= (T val) | Same as fecth_sub. |
T operator&= (T val) | Same as operator and. |
T operator|= (T val) | Same as operator or. |
T operator^= (T val) | Same as operator xor. |
It defines a critical_section based on atomic<bool> that can be used to synchronize threads like a mutex. It also defines a stack that can be used by multiple threads for access and updates.
This example 21 demonstrates the functionality of the atomic<> as seen in its console output.
The main thread spawns two worker threads to print numbers serially. Synchronization is provided by a atomic<int>.
atomic_flag
atomic_flag is an atomic boolean type. Unlike all specializations of atomic<>, it is guaranteed to be lock-free and also it does not provide load() or store() operations.
constructors
Name | Description |
---|---|
|
|
atomic_flag supports following operations.
Name | Description |
---|---|
void clear (memory_order order = memory_order_seq_cst ) | Atomically sets flag to false. Memory is affected according to the value of order which can be any of memory_order_relaxed, memory_order_release, memory_order_seq_cst |
bool test_and_set (memory_order order = memory_order_seq_cst) | Atomically sets the flag to true and obtains its previous value. Memory is affected according to the value of order which can be any of memory_order_relaxed, memory_order_consume, memory_order_acquire, memory_order_release, memory_order_acq_rel, memory_order_seq_cst. |
It defines a critical_section based on atomic<bool> that can be used to synchronize threads like a mutex. It also defines a stack that can be used by multiple threads for access and updates.
No comments:
Post a Comment