Should std::atomic be volatile?
<p>I'm running a thread that runs until a flag is set.</p>

<pre><code>std::atomic&lt;bool&gt; stop(false);

void f() {
  while(!stop.load(std::memory_order_{relaxed,acquire})) {
    do_the_job();
  }
}
</code></pre>

<p>I wonder if the compiler can unroll loop like this (I don't want it to happen).</p>

<pre><code>void f() {
  while(!stop.load(std::memory_order_{relaxed,acquire})) {
    do_the_job();
    do_the_job();
    do_the_job();
    do_the_job();
    ... // unroll as many as the compiler wants
  }
}
</code></pre>

<p>It is said that volatility and atomicity are orthogonal, but I'm a bit confused. Is the compiler free to cache the value of the atomic variable and unroll the loop? If the compiler can unroll the loop, then I think I have to put <code>volatile</code> to the flag, and I want to be sure.</p>

<p>Should I put <code>volatile</code>?</p>

<hr>

<p>I'm sorry for being ambiguous. I (guess that I) understand what reordering is and what <code>memory_order_*</code>s mean, and I'm sure I fully understand what <code>volatile</code> is.</p>

<p>I think the <code>while()</code> loop can be transformed as an infinite <code>if</code> statements like this.</p>

<pre><code>void f() {
  if(stop.load(std::memory_order_{relaxed,acquire})) return;
  do_the_job();
  if(stop.load(std::memory_order_{relaxed,acquire})) return;
  do_the_job();
  if(stop.load(std::memory_order_{relaxed,acquire})) return;
  do_the_job();
  ...
}
</code></pre>

<p>Since the given memory orders don't prevent the sequenced-before operations from being moved past the atomic load, I think it can be rearranged if it's without volatile.</p>

<pre><code>void f() {
  if(stop.load(std::memory_order_{relaxed,acquire})) return;
  if(stop.load(std::memory_order_{relaxed,acquire})) return;
  if(stop.load(std::memory_order_{relaxed,acquire})) return;
  ...
  do_the_job();
  do_the_job();
  do_the_job();
  ...
}
</code></pre>

<p>If the atomic does not imply volatile, then I think the code can be even transformed like this at worst case.</p>

<pre><code>void f() {
  if(stop.load(std::memory_order_{relaxed,acquire})) return;

  while(true) {
    do_the_job();
  }
}
</code></pre>

<p>There will never be such an insane implementation, but I guess it's still a possible situation. I think the only way to prevent this is to put <code>volatile</code> to the atomic variable and am asking about it.</p>

<p>There are a lot of guesses that I made, please tell me if there's anything wrong among them.</p>