29

In boost's implementation of shared_ptr, it uses relaxed memory ordering to increment its reference count. This appears safe as decrements use acquire/release to make sure that any previous decrements are visible to the thread before releasing memory. This method seems correct and appears in Herb Sutters talk on atomics

In libc++'s implementation uses full memory barriers

template <class T>
inline T
increment(T& t) _NOEXCEPT
{
    return __sync_add_and_fetch(&t, 1);
}

template <class T>
inline T
decrement(T& t) _NOEXCEPT
{
    return __sync_add_and_fetch(&t, -1);
}

}  // name

Is there a reason for this decision? Are there any performance or safety differences between them?

Christopher Tarquini
  • 11,176
  • 16
  • 55
  • 73
  • 1
    According to [implementation details here](http://en.cppreference.com/w/cpp/memory/shared_ptr), it says "To satisfy thread safety requirements, the reference counters are typically incremented and decremented using an equivalent of std::atomic::fetch_add with std::memory_order_relaxed." I was hoping to find source for it to confirm the statement, but I am having trouble finding online documentation of the libc++ source code for gcc (albeit they are only naive Google searches, maybe someone can provide a link). I notice your link is for LLVM though. – Suedocode Jan 28 '15 at 20:18
  • 1
    Who wrote that code, when, why and what else did they write ... if only there was a way find out. ;) – Ulrich Eckhardt Jan 28 '15 at 20:56
  • @Aggieboy I think the mirror I linked is the source for libc++ on GCC as well, you just compile it with `-gcc-toolchain`. libstd++ (default standard library on GCC) uses `__gnu_cxx::__exchange_and_add`, which I believe is also a full barrier but I'm not sure. It seems like it's commonish knowledge that it should be implemented with relaxed barriers but I can't seem to find any library besides boost that does it – Christopher Tarquini Jan 28 '15 at 21:17
  • @UlrichEckhardt I'd settle for some decent comments :P. I'm just curious why any STL implementation would go against best practice for thread safe reference counting (for performance) when it obviously has the ability to use it (atomics are there, just use them!). Maybe it was just how they did it, but maybe someone more familiar with atomics can shed some light on whether not there is a good reason to do it this way – Christopher Tarquini Jan 28 '15 at 21:20
  • Just to not leave any bad vibes here, @ChrisT, I wanted to (ironically) suggest that you check the according version control system. That's what the "blame" or "annotate" commands can be used for in many such systems. I'm not sure if this irony came across though... – Ulrich Eckhardt Jan 29 '15 at 20:37

1 Answers1

43

Because when I wrote that code, the compiler (clang) had not yet implemented C++11 atomics. And I never got back to it to clean it up.

Nothing subtle here. :-)

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • 31
    Finally, an answer relating to atomics that I understand! – Christopher Tarquini Jan 28 '15 at 23:41
  • Hah, I just got a "You did't pass" when this answer was shown to "audit" my reviews... I had flagged this as spam, thinking that someone with no rep (it wasn't showing the _real_ user) was extremely unlikely to have written code, let alone an entire library, that someone else was now asking about :-D – Amos M. Carpenter Feb 26 '15 at 05:14
  • At first look, I thought this was a bad self-answer (the smiley in particular). I was on guard for audits, so I passed, but it's not a great audit choice. – Jeffrey Bosboom Feb 26 '15 at 16:32
  • 3
    For future visitors to this page, it looks like this was fixed: https://llvm.org/bugs/show_bug.cgi?id=22803 – Christopher Tarquini Oct 19 '16 at 15:04