Std::atomic
Memory order
- enum std::memory_order
- cppreference.com - std::memory_order 1
- Google translate en->ko: Cppreference.com_-atomic-memory_order(ko).pdf
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
- MSDN: atomic::compare_exchange_strong 메서드
- Stackoverflow: std::atomic: compare_exchange_weak vs. compare_exchange_strong
- cppreference.com: std::atomic_compare_exchange*
비교하여, 정확하다면 값을 적용한다.
Parameters
- expected
- 객체에서 예상되는 값의 참조형. (즉, 비교할 값)
- desired
-
expected
값이 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
값이 정상적으로 변경되었다면 true
, 그 밖의 경우는 false
를 반환한다.
atomic_thread_fence
- cppreference.com: std::atomic_thread_fence
- cplusplus.com: atomic_thread_fence
- MSDN: 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
Correct. std::atomic may be implemented using locks.
std::atomic is atomic whether it has been implemented using locks, or without. std::atomic_flag is guaranteed to be implemented without using locks.
The primary difference besides the lock-free guarantee is:
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
특정 크기이상의 Trivial type을 Atomic 템플릿 인자로 전달할 경우 아래와 같은 링커 에러가 발생될 수 있다.
/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).
한마디로 링커에 atomic 라이브러리를 아래와 같이 추가해야 한다.
Libraries
See also
- C/C++
- Synchronization
- Multi Thread
- std::mutex
- 메모리 장벽 (Memory barrier)
- 메모리 가시성 (Memory visibility)
- CppMem
- MOESI protocol
- Helgrind (Valgrind)
- ABA Problem
Favorite site
- std::atomic references
- [추천] 수까락의 프로그래밍 이야기 C++11 atomic (메모리 가시성과 장벽) 3
- C++11 atomic 객체 맛보기
- 메모리 가시성(memory visibility)과 메모리 장벽(memory barrier)
- [추천] Slideshare - Concurrency in action - chapter 5 (C++ 메모리 모델과, Atomic type 연산) 4
- Atomic - GCC Wiki
Atomic pointer
- Stackoverflow: Atomic pointers in c++ and passing objects between threads
- Stackoverflow: Is pointer assignment atomic in C++?
- Stackoverflow: Atomic exchange of two std::atomic
objects in a lock-free manner in C++11?
How to use
- Double-Checked Locking is Fixed In C++11
- The Purpose of memory_order_consume in C++11
- The Synchronizes-With Relation
- An Introduction to Lock-Free Programming
memory order
- Stackoverflow - Difference between memory_order_consume and memory_order_acquire (CppMem)
- Stackoverflow - What do each memory_order mean?
- Stackoverflow - C++11: the difference between memory_order_relaxed and memory_order_consume
- acquire / release fence의 핵심
- SlideShare - Concurrency in action - chapter 5
- Chapter 05, The Cpp memory model and operations on atomic types