Quantcast
Channel: Recent Questions - Stack Overflow
Viewing all articles
Browse latest Browse all 12141

memory order with multiple stores

$
0
0

Consider the example below. Assume that barrier is initialized to 0.

There is one producer thread and two consumer threads that constantly check barrier. If the barrier is set, they decrease runcnt. The producer thread waits for runcnt to reach 0. I am confused about the order of multiple store operations inside the producer.

If the order is like it is written, I think the code would run as expected. But if the barrier store is reordered before runcnt store, it seems the assert check would fail.Am I missing anything? Is there a way to fix this?

extern atomic<int> barrier[2];atomic_int runcnt{0};void producer() {    runcnt.store(2, memory_order_relaxed);    barrier[0].store(1, memory_order_relaxed);    barrier[1].store(1, memory_order_relaxed);    while (runcnt.load(memory_order_relaxed)) {        cpu_pause();    }}void consumer(unsigned index) {   while (true) {    if (barrier[index].exchange(false, memory_order_relaxed)) {      int prev = runcnt.fetch_sub(1, memory_order_relaxed);      assert(prev > 0);    }   }}

Update

As @peter-cordes pointed out, unlike regular release stores that are uni-directional, std::atomic_thread_fence(release) serves as bidirectional barrier between stores (loads can still be reordered).

Therefore, this is the fixed code:

void producer() {    runcnt.store(2, memory_order_relaxed);    std::atomic_thread_fence(release);  // <- Prevents reordering of barrier stores before runcnt.store.     barrier[0].store(1, memory_order_relaxed);    barrier[1].store(1, memory_order_relaxed);    while (runcnt.load(memory_order_relaxed)) {        cpu_pause();    }}

Viewing all articles
Browse latest Browse all 12141

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>