title: Why is an acquire barrier needed before deleting the data in an atomically reference counted smart pointer?
body: <p>Boost provides a <a href="http://www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html#boost_atomic.usage_examples.example_reference_counters" rel="noreferrer">sample atomically reference counted shared pointer</a></p>
  
  <p>Here is the relevant code snippet and the explanation for the various orderings used:</p>
  
  <pre><code>class X {
  public:
    typedef boost::intrusive_ptr&lt;X&gt; pointer;
    X() : refcount_(0) {}
  
  private:
    mutable boost::atomic&lt;int&gt; refcount_;
    friend void intrusive_ptr_add_ref(const X * x)
    {
      x-&gt;refcount_.fetch_add(1, boost::memory_order_relaxed);
    }
    friend void intrusive_ptr_release(const X * x)
    {
      if (x-&gt;refcount_.fetch_sub(1, boost::memory_order_release) == 1) {
        boost::atomic_thread_fence(boost::memory_order_acquire);
        delete x;
      }
    }
  };
  </code></pre>
  
  <blockquote>
    <p>Increasing the reference counter can always be done with
    memory_order_relaxed: New references to an object can only be formed
    from an existing reference, and passing an existing reference from one
    thread to another must already provide any required synchronization.</p>
    
    <p>It is important to enforce any possible access to the object in one
    thread (through an existing reference) to happen before deleting the
    object in a different thread. This is achieved by a "release"
    operation after dropping a reference (any access to the object through
    this reference must obviously happened before), and an "acquire"
    operation before deleting the object.</p>
    
    <p>It would be possible to use memory_order_acq_rel for the fetch_sub
    operation, but this results in unneeded "acquire" operations when the
    reference counter does not yet reach zero and may impose a performance
    penalty.</p>
  </blockquote>
  
  <p>I am not able to understand why the <code>memory_order_acquire</code> barrier is necessary before the <code>delete x</code> operation. Specifically, how is it safe for the compiler/processor to reorder the memory operations of <code>delete x</code> before the <code>fetch_sub</code> and the test on the value of <code>x == 1</code> without violating the single threaded semantics?</p>
  
  <p><strong>EDIT</strong> I guess, my question wasn't very clear. Here is a rephrased version:</p>
  
  <p>Will the control dependency between the read of x (<code>x-&gt;refcount_.fetch_sub(1, boost::memory_order_release) == 1</code>) and the <code>delete x</code> operation provide any ordering guarantee at all? Even considering a single threaded program, is it possible for the compiler/processor to reorder the instructions corresponding to the <code>delete x</code> operation before the <code>fetch_sub</code> and the comparison?. It would be really helpful if the answer was as low-level as possible and included an example scenario where the delete operation gets reordered (without affecting the single threaded semantics) thus illustrating the need to preserve ordering.</p>