atomic<bool> vs bool protected by mutex
<p>Let's assume we have a memory area where some thread is writing data to. It then turns its attention elsewhere and allows arbitrary other threads to read the data. However, at some point in time, it wants to reuse that memory area and will write to it again.</p>

<p>The writer thread supplies a boolean flag (<code>valid</code>), which indicates that the memory is still valid to read from (i.e. he is not reusing it yet). At some point he will set this flag to false and never set it to true again (it just flips once and that is it).</p>

<p>With sequential consistency, it should be correct to use these two code snippets for the writer and the readers, respectively:</p>

<pre><code>...
valid = false;
&lt;write to shared memory&gt;
...
</code></pre>

<p>and</p>

<pre><code>...
&lt;read from shared memory&gt;
if (valid) {
    &lt;be happy and work with data read&gt;
} else {
    &lt;be sad and do something else&gt;
}
...
</code></pre>

<p>We obviously need to do something to ensure sequential consistency, namely insert the necessary acquire and release memory barriers. We want the flag to be set to false in the writer thread, <strong>before</strong> writing any data to the segment. And we want the data to be read from memory in the reader threads <strong>before</strong> checking <code>valid</code>. The later because we know valid to be <em>monotonic</em>, i.e., if it is still valid <strong>after</strong> reading, it was valid while reading.</p>

<p>Inserting a full fence between memory access and the access to <code>valid</code> will do the trick. I wonder, however, if making <code>valid</code> an atomic will be enough?</p>

<pre><code>std::atomic&lt;bool&gt; valid = true;
</code></pre>

<p>Then</p>

<pre><code>...
valid.store(false); // RELEASE
&lt;write to shared memory&gt;
...
</code></pre>

<p>and</p>

<pre><code>...
&lt;read from shared memory&gt;
if (valid.load()) { // ACQUIRE
    &lt;be happy and work with data read&gt;
} else {
    &lt;be sad and do something else&gt;
}
...
</code></pre>

<p>It seems that in this scenario, the implied release and acquire operations from using the the atomic store and read work against me. The RELEASE in the writer does <strong>not</strong> prevent the memory access to be moved up over it (just code from above may not be moved down). And similarly, the ACQUIRE in the readers does <strong>not</strong> prevent the memory access to be moved down over it (just code from below may not be moved up).</p>

<p>If this is true, to make this scenario work, I would need an ACQUIRE (i.e. a load) in the writer thread as well and a RELEASE (i.e. store) in the reader threads. Alternatively, I could just use a normal boolean flag and protect the write and read access (to it only!) in the threads with a shared mutex. By doing so I would effectively also have both an ACQUIRE and a RELEASE in both threads, separating the <code>valid</code> access from the memory access.</p>

<p>So this would be a very severe difference between <code>atomic&lt;bool&gt;</code> and a regular <code>bool</code> protected by a <code>mutex</code>, is this correct?</p>

<p><strong>Edit</strong>: There actually seems to be a difference in what is <em>implied</em> by a load and a store on atomics. The <code>std::atomic</code> of C++11 uses <code>memory_order_seq_cst</code> for both (!), rather than <code>memory_order_acquire</code> and <code>memory_order_release</code> for load and store respectively.</p>

<p>In contrast, the <code>tbb::atomic</code> uses <code>memory_semantics::acquire</code> and <code>memory_semantics::release</code> rather than <code>memory_semantics::full_fence</code>.</p>

<p>So if my understanding is correct, the code would be correct with standard C++11 atomics, but with tbb atomics one would need to add the explicit <code>memory_semantics::full_fence</code> template parameter to both load and store.</p>