title: How can memory_order_relaxed work for incrementing atomic reference counts in smart pointers?
body: <p>Consider the following code snippet taken from Herb Sutter's talk on atomics:</p>
  
  <p>The smart_ptr class contains a pimpl object called control_block_ptr containing the reference count <strong>refs</strong>.</p>
  
  <pre><code>// Thread A:
  // smart_ptr copy ctor
  smart_ptr(const smart_ptr&amp; other) {
    ...
    control_block_ptr = other-&gt;control_block_ptr;
    control_block_ptr-&gt;refs.fetch_add(1, memory_order_relaxed);
    ...
  }
  
  // Thread D:
  // smart_ptr destructor
  ~smart_ptr() {
    if (control_block_ptr-&gt;refs.fetch_sub(1, memory_order_acq_rel) == 1) {
      delete control_block_ptr;
    }
  }
  </code></pre>
  
  <p>Herb Sutter says the increment of <strong>refs</strong> in Thread A can use memory_order_relaxed because "nobody does anything based on the action". Now as I understand memory_order_relaxed, if <strong>refs</strong> equals N at some point and two threads A and B execute the following code:</p>
  
  <pre><code>control_block_ptr-&gt;refs.fetch_add(1, memory_order_relaxed);
  </code></pre>
  
  <p>then it may happen that both threads see the value of <strong>refs</strong> to be N and both write N+1 back to it. That will clearly not work and memory_order_acq_rel should be used just as with the destructor. Where am I going wrong?</p>
  
  <p>EDIT1: Consider the following code.</p>
  
  <pre><code>atomic_int refs = N; // at time t0. 
  
  // [Thread 1]
  refs.fetch_add(1, memory_order_relaxed); // at time t1. 
  
  // [Thread 2]
  n = refs.load(memory_order_relaxed);   // starting at time t2 &gt; t1
  refs.fetch_add(1, memory_order_relaxed);
  n = refs.load(memory_order_relaxed);
  </code></pre>
  
  <p>What is the value of <strong>refs</strong> observed by Thread 2 before the call to fetch_add? Could it be either N or N+1? What is the value of refs observed by Thread 2 after the call to fetch_add? Must it be at least N+2?</p>
  
  <p>[Talk URL: C++ &amp; Beyond 2012 - <a href="http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2" rel="noreferrer">http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2</a> (@ 1:20:00)]</p>