Boost C++ Libraries: Ticket #12309: Is "Reference counting" example misleading and wrong? https://svn.boost.org/trac10/ticket/12309 <p> Boost.Atomic in its documentation provides "Reference counting" example: <a href="http://www.boost.org/doc/libs/1_61_0/doc/html/atomic/usage_examples.html#boost_atomic.usage_examples.example_reference_counters">http://www.boost.org/doc/libs/1_61_0/doc/html/atomic/usage_examples.html#boost_atomic.usage_examples.example_reference_counters</a> </p> <p> The example itself is excellent. After all this is a typical use case so providing an example with brief discussion is mostly welcome. </p> <p> The problem is however whether the example is correct after all. I mean here the part about counter decrement. Example uses <code>release</code> order and then a fance with <code>acquire</code>: </p> <pre class="wiki">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; } } </pre><p> while description states later: </p> <blockquote> <p> It would be possible to use <code>memory_order_acq_rel</code> for the <code>fetch_sub</code> 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> At the same time <code>boost::shared_ptr</code> uses <code>acq_rel</code> in its <code>std::atomic</code> implementation in file <code>boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp</code> (<a href="http://www.boost.org/doc/libs/1_61_0/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp">http://www.boost.org/doc/libs/1_61_0/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp</a>). </p> <p> Also Herb Sutter in his "C++ and Beyond 2012: Herb Sutter - atomic&lt;&gt; Weapons, 2 of 2" (<a class="ext-link" href="https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2"><span class="icon">​</span>https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2</a>) lecture mentions reference counting topic (starting at 1:19:51) where he also calls for <code>acq_rel</code>. And it seems that he discourages use fences in this talk. </p> <p> So which one is good? Because either Boost.Atomic documentation should be updated or <code>boost::shared_ptr</code> should be improved. </p> <p> And let me note here that this Boost.Atomic documentation part seems to be quoted (or refereed to) at various places, including Stack Overflow, quite often. So it is important for it to be correct. </p> <hr /> <p> BTW (although beyond this ticket) it seems strange to me that <code>boost::shared_ptr</code> doesn't use <code>boost::atomic</code> and instead provides like 19 different implementations. It smells like code repetition to me. But maybe there are valid reasons for it... </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/12309 Trac 1.4.3 Andrey Semashev Wed, 14 Sep 2016 19:20:38 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/12309#comment:1 https://svn.boost.org/trac10/ticket/12309#comment:1 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> I think the code in the documentation is valid. </p> <p> The release semantics is needed to guarantee that any modifications made by a thread before it decrements the counter are visible to other threads. </p> <p> The acquire semantics is only needed if the object destructor is called. It makes sure that the destructor observes the actual state of the object that might have been modified by another thread that previously decremented the counter from 2 to 1. The standard (C++11, [atomics.fences]/4) says that in this code the <code>atomic_thread_fence(acquire)</code> synchronizes with <code>fetch_sub(1, release)</code> issued by other threads, so it should not be reordered with the <code>fetch_sub</code>. </p> <p> It is formally correct to merge this acquire fence with the <code>fetch_sub</code> operation, but depending on the CPU architecture it may or may not be slightly slower. </p> <p> As for <code>boost::shared_ptr</code>, you can propose the change to that library. Boost.<a class="missing wiki">SmartPtr</a> predates Boost.Atomic, so it contains its own implementation of atomic operations for many platforms. </p> Ticket