Consider the following code snippet taken from Herb Sutter's talk on atomics:

The smart\_ptr class contains a pimpl object called control\_block\_ptr containing the reference count **refs**.

```
// Thread A:
// smart_ptr copy ctor
smart_ptr(const smart_ptr& other) {
  ...
  control_block_ptr = other->control_block_ptr;
  control_block_ptr->refs.fetch_add(1, memory_order_relaxed);
  ...
}

// Thread D:
// smart_ptr destructor
~smart_ptr() {
  if (control_block_ptr->refs.fetch_sub(1, memory_order_acq_rel) == 1) {
    delete control_block_ptr;
  }
}

```

Herb Sutter says the increment of **refs** in Thread A can use memory\_order\_relaxed because "nobody does anything based on the action". Now as I understand memory\_order\_relaxed, if **refs** equals N at some point and two threads A and B execute the following code:

```
control_block_ptr->refs.fetch_add(1, memory_order_relaxed);

```

then it may happen that both threads see the value of **refs** 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?

EDIT1: Consider the following 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 > t1
refs.fetch_add(1, memory_order_relaxed);
n = refs.load(memory_order_relaxed);

```

What is the value of **refs** 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?

[Talk URL: C++ & Beyond 2012 - <http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2> (@ 1:20:00)]