Boost C++ Libraries: Ticket #1109: intrusive_ptr needs a helper base class https://svn.boost.org/trac10/ticket/1109 <p> <a class="ext-link" href="http://lists.boost.org/Archives/boost/2006/04/103182.php"><span class="icon">​</span>http://lists.boost.org/Archives/boost/2006/04/103182.php</a> <a class="ext-link" href="http://lists.boost.org/Archives/boost/2006/04/103203.php"><span class="icon">​</span>http://lists.boost.org/Archives/boost/2006/04/103203.php</a> <a class="ext-link" href="http://lists.boost.org/Archives/boost/2006/04/103267.php"><span class="icon">​</span>http://lists.boost.org/Archives/boost/2006/04/103267.php</a> <a class="ext-link" href="http://lists.boost.org/Archives/boost/2006/04/103273.php"><span class="icon">​</span>http://lists.boost.org/Archives/boost/2006/04/103273.php</a> </p> <pre class="wiki">class counted_base { private: mutable detail::atomic_count count_; protected: counted_base(): count_( 0 ) {} virtual ~counted_base() {} counted_base( counted_base const &amp; ): count_( 0 ) {} counted_base&amp; operator=( counted_base const &amp; ) { return *this; } public: inline friend void intrusive_ptr_add_ref( counted_base const * p ) { ++p-&gt;count_; } inline friend void intrusive_ptr_release( counted_base const * p ) { if( --p-&gt;count_ == 0 ) delete p; } long use_count() const { return count_; } }; </pre><p> <a class="ext-link" href="http://lists.boost.org/Archives/boost/2006/04/103306.php"><span class="icon">​</span>http://lists.boost.org/Archives/boost/2006/04/103306.php</a> </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/1109 Trac 1.4.3 Peter Dimov Sat, 21 Jul 2007 23:34:13 GMT status changed; owner set https://svn.boost.org/trac10/ticket/1109#comment:1 https://svn.boost.org/trac10/ticket/1109#comment:1 <ul> <li><strong>owner</strong> set to <span class="trac-author">Peter Dimov</span> </li> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> </ul> Ticket Peter Dimov Thu, 21 Aug 2008 15:13:40 GMT milestone changed https://svn.boost.org/trac10/ticket/1109#comment:2 https://svn.boost.org/trac10/ticket/1109#comment:2 <ul> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.37.0</span> </li> </ul> Ticket Peter Dimov Sat, 28 Feb 2009 16:59:40 GMT milestone changed https://svn.boost.org/trac10/ticket/1109#comment:3 https://svn.boost.org/trac10/ticket/1109#comment:3 <ul> <li><strong>milestone</strong> <span class="trac-field-old">Boost 1.37.0</span> → <span class="trac-field-new">To Be Determined</span> </li> </ul> Ticket Peter Dimov Thu, 24 Feb 2011 22:07:08 GMT status changed https://svn.boost.org/trac10/ticket/1109#comment:4 https://svn.boost.org/trac10/ticket/1109#comment:4 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">new</span> </li> </ul> Ticket NN Tue, 31 May 2011 12:55:13 GMT <link>https://svn.boost.org/trac10/ticket/1109#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/1109#comment:5</guid> <description> <p> Virtual destructor is not necessary here: </p> <div class="wiki-code"><div class="code"><pre><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">class</span> <span class="nc">counted_base</span> <span class="p">{</span> <span class="k">private</span><span class="o">:</span> <span class="k">mutable</span> <span class="n">detail</span><span class="o">::</span><span class="n">atomic_count</span> <span class="n">count_</span><span class="p">;</span> <span class="k">protected</span><span class="o">:</span> <span class="n">counted_base</span><span class="p">()</span><span class="o">:</span> <span class="n">count_</span><span class="p">(</span> <span class="mi">0</span> <span class="p">)</span> <span class="p">{}</span> <span class="o">~</span><span class="n">counted_base</span><span class="p">()</span> <span class="p">{}</span> <span class="n">counted_base</span><span class="p">(</span> <span class="n">counted_base</span> <span class="k">const</span> <span class="o">&amp;</span> <span class="p">)</span><span class="o">:</span> <span class="n">count_</span><span class="p">(</span> <span class="mi">0</span> <span class="p">)</span> <span class="p">{}</span> <span class="n">counted_base</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span> <span class="n">counted_base</span> <span class="k">const</span> <span class="o">&amp;</span> <span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="o">*</span><span class="k">this</span><span class="p">;</span> <span class="p">}</span> <span class="k">public</span><span class="o">:</span> <span class="kr">inline</span> <span class="k">friend</span> <span class="kt">void</span> <span class="n">intrusive_ptr_add_ref</span><span class="p">(</span> <span class="n">T</span> <span class="k">const</span> <span class="o">*</span> <span class="n">p</span> <span class="p">)</span> <span class="p">{</span> <span class="o">++</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">counted_base</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">count_</span><span class="p">;</span> <span class="p">}</span> <span class="kr">inline</span> <span class="k">friend</span> <span class="kt">void</span> <span class="n">intrusive_ptr_release</span><span class="p">(</span> <span class="n">T</span> <span class="k">const</span> <span class="o">*</span> <span class="n">p</span> <span class="p">)</span> <span class="p">{</span> <span class="k">if</span><span class="p">(</span> <span class="o">--</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">counted_base</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">count_</span> <span class="o">==</span> <span class="mi">0</span> <span class="p">)</span> <span class="k">delete</span> <span class="n">p</span><span class="p">;</span> <span class="p">}</span> <span class="kt">long</span> <span class="n">use_count</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">count_</span><span class="p">;</span> <span class="p">}</span> <span class="p">};</span> </pre></div></div> </description> <category>Ticket</category> </item> <item> <author>Olaf van der Spek <olafvdspek@…></author> <pubDate>Mon, 03 Oct 2011 13:24:31 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/1109#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/1109#comment:6</guid> <description> <p> What's the advantage of intrusive over shared when make_shared is used? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>ArtemGr</dc:creator> <pubDate>Mon, 16 Sep 2013 13:38:16 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/1109#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/1109#comment:7</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/1109#comment:6" title="Comment 6">Olaf van der Spek &lt;olafvdspek@…&gt;</a>: </p> <blockquote class="citation"> <p> What's the advantage of intrusive over shared when make_shared is used? </p> </blockquote> <p> Olaf, one important advantage is that the class does not need to be fully defined,<br /> another advantage is that you can create intrusive_ptr anywhere, you don't have to pass it around in order to have it. </p> </description> <category>Ticket</category> </item> <item> <author>Tomas Kislan <pinkerik88@…></author> <pubDate>Mon, 07 Oct 2013 06:33:24 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/1109#comment:8 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/1109#comment:8</guid> <description> <p> I would also template the type of count_ variable, sometimes there's no need for thread-safe counter, and using long would give some performance boost </p> </description> <category>Ticket</category> </item> <item> <author>Jiří Havel <JSH@…></author> <pubDate>Thu, 07 Nov 2013 09:03:47 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/1109#comment:9 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/1109#comment:9</guid> <description> <p> I use this base class. It is inspired by boost.intrusive and uses the example reference counter from boost.atomic. </p> <p> If you want, I can improve this a bit. I think, it should be possible to select atomic/nonatomic internal counter and some checking policy (again inspired by boost.atomic). </p> <pre class="wiki">#ifndef INTRUSIVE_PTR_BASE_HOOK_H_INCLUDED #define INTRUSIVE_PTR_BASE_HOOK_H_INCLUDED #include &lt;memory&gt; #include &lt;utility&gt; #include &lt;boost/assert.hpp&gt; #include &lt;boost/atomic.hpp&gt; #include &lt;boost/intrusive_ptr.hpp&gt; #include &lt;boost/parameter/binding.hpp&gt; #include &lt;boost/parameter/name.hpp&gt; #include &lt;boost/parameter/parameters.hpp&gt; namespace utils { BOOST_PARAMETER_TEMPLATE_KEYWORD(deleter) BOOST_PARAMETER_TEMPLATE_KEYWORD(count_type) typedef boost::parameter::parameters&lt; boost::parameter::optional&lt;tag::deleter&gt;, boost::parameter::optional&lt;tag::count_type&gt; &gt; intrusive_ptr_base_hook_signature; template&lt;typename Derived, typename ... Params&gt; class intrusive_ptr_base_hook { typedef typename intrusive_ptr_base_hook_signature::bind&lt;Params...&gt;::type args; protected : typedef Derived derived_type; typedef typename boost::parameter::binding&lt; args, tag::deleter, std::default_delete&lt;derived_type&gt; &gt;::type deleter_type; typedef typename boost::parameter::binding&lt; args, tag::count_type, unsigned &gt;::type count_type; private: struct Data : public deleter_type { boost::atomic&lt;count_type&gt; count; constexpr Data(count_type c, deleter_type const &amp; d) : deleter_type(d) , count(c) {} } m_data; protected : constexpr intrusive_ptr_base_hook() : m_data(0, deleter_type()) {} intrusive_ptr_base_hook(intrusive_ptr_base_hook const &amp;) = delete; intrusive_ptr_base_hook &amp; operator=(intrusive_ptr_base_hook const &amp;) = delete; ~intrusive_ptr_base_hook() noexcept { BOOST_ASSERT(m_count.load(boost::memory_order::memory_order_relaxed) == 0); } public : friend void intrusive_ptr_add_ref( intrusive_ptr_base_hook const * p) { const_cast&lt;intrusive_ptr_base_hook*&gt;(p) -&gt;m_data.count.fetch_add(1, boost::memory_order_relaxed); } friend void intrusive_ptr_release( intrusive_ptr_base_hook const * pc) { intrusive_ptr_base_hook * p = const_cast&lt;intrusive_ptr_base_hook*&gt;(pc); if(p-&gt;m_data.count.fetch_sub(1, boost::memory_order_release) == 1) { boost::atomic_thread_fence(boost::memory_order_acquire); // call deleter hidden in m_data p-&gt;m_data(static_cast&lt;derived_type*&gt;(p)); } } }; template&lt;typename T, typename ... Args&gt; inline boost::intrusive_ptr&lt;T&gt; make_intrusive(Args &amp;&amp; ... args) { return boost::intrusive_ptr&lt;T&gt;(new T(std::forward&lt;Args&gt;(args)...)); } }//namespace utils #endif//INTRUSIVE_PTR_BASE_HOOK_H_INCLUDED </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>Peter Dimov</dc:creator> <pubDate>Wed, 11 Dec 2013 18:02:23 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/1109#comment:10 https://svn.boost.org/trac10/ticket/1109#comment:10 <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> There's boost/smart_ptr/intrusive_ref_counter.hpp now. </p> Ticket