0

Consider the following code:

std::atomic<bool> flag(false);
//Thread 1
flag.store(true,std::memory_order_relaxed);
//Thread 2
while(!flag.load(std::memory_order_relaxed)) ; // stay in the loop
std::cout << "loaded";

Is there any gurantee that the last line ever gets executed? If the answer is no, how it should be fixed (with as minimum overhead as possible)?

Koosha
  • 1,492
  • 7
  • 19
  • 2
    Why not use [`std::conditional_variable`](https://en.cppreference.com/w/cpp/thread/condition_variable) instead? The waiting thread can `wait()` on the CV more efficiently than waiting on a `std::atomic` in a busy loop. The other thread can notify the CV when needed, waiting up the waiting thread. – Remy Lebeau Jan 07 '20 at 01:14
  • Edit: `atomic_relaxed` --> `memory_order_relaxed` As for not using CV, 1. I want to learn how things work, 2. This is a simplified example, only showing the core question – Koosha Jan 07 '20 at 01:29

1 Answers1

3

Yes, the last line is guaranteed to be executed eventually [intro.progress]/18

An implementation should ensure that the last value (in modification order) assigned by an atomic or synchronization operation will become visible to all other threads in a finite period of time.

Since your flag is atomic and is also the only thing any thread ever accesses in any way, there are no data races here. Since there are no loads or stores to objects other than your atomic to begin with, your program cannot possibly depend on any particular ordering of such non-existent loads or stores relative to the loads and stores to your atomic. Thus, relaxed memory order is perfectly sufficient. Since it is guaranteed that the atomic store in thread 1 will eventually become visible to thread 2, the loop is guaranteed to eventually terminate…

Michael Kenzel
  • 15,508
  • 2
  • 30
  • 39
  • Thanks, I don't understand why such a crutial point is not at `https://en.cppreference.com/w/cpp/atomic/memory_order`. – Koosha Jan 07 '20 at 01:41
  • 1
    I can only speculate that it is probably considered self-evident that atomic stores are guaranteed to eventually become visible as a lack of such guarantee would render the entire memory model completely and utterly useless… – Michael Kenzel Jan 07 '20 at 01:51
  • 1
    @Koosha It's not dependent on `memory_order`. Even `mo_relaxed` stores are "required" (with "should" language, not "must" unfortunately) to become globally visible promptly. On real implementations, this Just Works very simply because CPU caches are coherent. So loads can never read a "stale" value after the store buffer on the writing thread commits the store to L1d cache (which it always does as quickly as it can). – Peter Cordes Jan 07 '20 at 03:11