Skip to content
Search

Std::atomic

lastmod 2020-08-08created 2015-03-1932 edits

Memory order

Used as an argument to functions that conduct atomic operations to specify how other operations on different threads are synchronized.

std::memory_order specifies how regular, non-atomic memory accesses are to be ordered around an atomic operation. Absent any constraints on a multi-core system, when multiple threads simultaneously read and write to several variables, one thread can observe the values change in an order different from the order another thread wrote them. Indeed, the apparent order of changes can even differ among multiple reader threads. Some similar effects can occur even on uniprocessor systems due to compiler transformations allowed by the memory model.

The default behavior of all atomic operations in the library provides for sequentially consistent ordering (see discussion below). That default can hurt performance, but the library's atomic operations can be given an additional std::memory_order argument to specify the exact constraints, beyond atomicity, that the compiler and processor must enforce for that operation.

compare_exchange_weak & compare_exchange_strong

Compares, and applies the value if it matches.

Parameters

expected
Reference to the value expected to be found in the object. (i.e., the value to compare)
desired
The value to store if the expected value equals the value of the atomic object.
success
the memory synchronization ordering for the read-modify-write operation if the comparison succeeds. All values are permitted.
failure
the memory synchronization ordering for the load operation if the comparison fails. Cannot be std::memory_order_release or std::memory_order_acq_rel and cannot specify stronger ordering than success (until C++17)
order
the memory synchronization ordering for both operations

Return value

Returns true if the value was successfully changed, otherwise false.

atomic_thread_fence

Establishes memory synchronization ordering of non-atomic and relaxed atomic accesses, as instructed by order, without an associated atomic operation.

atomic_signal_fence

Establishes memory synchronization ordering of non-atomic and relaxed atomic accesses, as instructed by order, between a thread and a signal handler executed on the same thread. This is equivalent to std::atomic_thread_fence, except no CPU instructions for memory ordering are issued. Only reordering of the instructions by the compiler is suppressed as order instructs. For example, a fence with release semantics prevents reads or writes from being moved past subsequent writes and a fence with acquire semantics prevents reads or writes from being moved ahead of preceding reads.

acquire / release

atomic_bool vs atomic_flag

std::atomic bool type not guranteed to be lock-free?

Correct. std::atomic may be implemented using locks.

then it's not atomic or what?

std::atomic is atomic whether it has been implemented using locks, or without. std::atomic_flag is guaranteed to be implemented without using locks.

So what's the difference b/w two

The primary difference besides the lock-free guarantee is:

std::atomic_flag does not provide load or store operations.
and when should I use which?

Usually, you will want to use std::atomic<bool> when you need an atomic boolean variable. std::atomic_flag is a low level structure that can be used to implement custom atomic structures.

Troubleshooting

Does std::atomic<std::string> work appropriately?

Undefined reference atomic

Passing a Trivial type above a certain size as the Atomic template argument can cause a linker error like the one below.

/tmp/cc8gyaZM.o: In function `std::atomic<A>::store(A, std::memory_order)':
dryn.cpp:     (.text._ZNSt6atomicI1AE5storeES0_St12memory_order[_ZNSt6atomicI1AE5storeES0_St12memory_order]+0x3e): undefined reference to `__atomic_store_16'

Atomic API isn't complete in GCC 4.7:

When lock free instructions are not available (either through hardware or OS support) atomic operations are left as function calls to be resolved by a library. Due to time constraints and an API which is not finalized, there is no libatomic supplied with GCC 4.7. This is easily determined by encountering unsatisfied external symbols beginning with __atomic_*.

Since there is no libatomic shipped with GCC 4.7 you need to use another compiler which actually supports the features you want or provide the missing features (sample implementation).

In short, add the atomic library to the linker as shown below.

-latomic

Libraries

See also

Favorite site

Atomic pointer

How to use

memory order

References


  1. Std_memory_order_-_cppreference.pdf ↩

  2. Findessentials_-_acquire_and_release_fence.pdf ↩

  3. Egloos_zum_com-sweeper-c++11_std_atomic.pdf ↩

  4. Concurrency-in-action-chapter-5.tar.gz ↩

author Zer0 sitemap