Can you give a real-world example where two memory_order parameter version of std::atomic::compare_exchange
is used for a reason (so the one memory_order parameter version is not adequate)?
相关问题
- Sorting 3 numbers without branching [closed]
- How to compile C++ code in GDB?
- Why does const allow implicit conversion of refere
- thread_local variables initialization
- What uses more memory in c++? An 2 ints or 2 funct
相关文章
- Class layout in C++: Why are members sometimes ord
- How to mock methods return object with deleted cop
- Which is the best way to multiply a large and spar
- C++ default constructor does not initialize pointe
- Difference between Thread#run and Thread#wakeup?
- Selecting only the first few characters in a strin
- Java/Spring MVC: provide request context to child
- What exactly do pointers store? (C++)
In many cases, the second memory orderering parameter on
compare_exchange
is set tomemory_order_relaxed
. In those cases, it is usually not wrong to omit it, just potentially less efficient.Here is an example of a simple, lock-free, list/stack that requires a second, different, ordering parameter on
compare_exchange_weak
in order to be data-race-free.Calls to
push
can be executed concurrently, but to avoid the complexities of lock-free data manipulation, the assumption is made that nodes cannot be removed from the stack while calls topush
are executed; i.e. to avoid dangling pointers.In
push
, the initialload
(at A) is a relaxed operation, meaning that even though thehead
pointer is loaded atomically, it may not be dereferenced since the memory it refers to is unordered in this thread.In case
compare_exchange_weak
returns success,newnode
is inserted at the head of the list and made available to other threads by setting a release barrier (at B). Another thread that accesses this data (later, viapop
) needs to set an acquire barrier.In case
compare_exchange_weak
returns failure (forget spuriously), another thread just inserted a newnode
instance andcurrent_head
is updated with the new value ofhead
. Sincecurrent_head
is now pointing at data that was allocated and released in another thread, an acquire barrier is necessary ifcurrent_head
is going to be dereferenced.This is true since the
cout
failure message includescurrent_head->id
.Had the last parameter been omitted, the first barrier parameter would have been used for the failure
load
scenario, but since this is a release barrier, the effective barrier would have decayed tomemory_order_relaxed
, causing a data race oncurrent_head->id
.