Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r85547 - in trunk: boost/log/attributes boost/log/utility boost/smart_ptr libs/smart_ptr libs/smart_ptr/test
From: andrey.semashev_at_[hidden]
Date: 2013-09-01 17:05:14


Author: andysem
Date: 2013-09-01 17:05:14 EDT (Sun, 01 Sep 2013)
New Revision: 85547
URL: http://svn.boost.org/trac/boost/changeset/85547

Log:
Changed intrusive_ref_counter to follow CRTP design.

Properties modified:
   trunk/libs/smart_ptr/intrusive_ref_counter.html (contents, props changed)
Text files modified:
   trunk/boost/log/attributes/attribute.hpp | 7 +++
   trunk/boost/log/utility/intrusive_ref_counter.hpp | 11 +++++
   trunk/boost/smart_ptr/intrusive_ref_counter.hpp | 67 +++++++++++++++++++--------------------
   trunk/libs/smart_ptr/intrusive_ptr.html | 2
   trunk/libs/smart_ptr/intrusive_ref_counter.html | 51 ++++++++++++++++--------------
   trunk/libs/smart_ptr/test/intrusive_ref_counter_test.cpp | 40 ++++++++++++++--------
   6 files changed, 102 insertions(+), 76 deletions(-)

Modified: trunk/boost/log/attributes/attribute.hpp
==============================================================================
--- trunk/boost/log/attributes/attribute.hpp Sun Sep 1 15:07:06 2013 (r85546)
+++ trunk/boost/log/attributes/attribute.hpp 2013-09-01 17:05:14 EDT (Sun, 01 Sep 2013) (r85547)
@@ -67,9 +67,14 @@
      * All attributes must derive their implementation from this class.
      */
     struct BOOST_LOG_NO_VTABLE BOOST_SYMBOL_VISIBLE impl :
- public boost::intrusive_ref_counter
+ public boost::intrusive_ref_counter< impl >
     {
         /*!
+ * \brief Virtual destructor
+ */
+ virtual ~impl() {}
+
+ /*!
          * \return The actual attribute value. It shall not return empty values (exceptions
          * shall be used to indicate errors).
          */

Modified: trunk/boost/log/utility/intrusive_ref_counter.hpp
==============================================================================
--- trunk/boost/log/utility/intrusive_ref_counter.hpp Sun Sep 1 15:07:06 2013 (r85546)
+++ trunk/boost/log/utility/intrusive_ref_counter.hpp 2013-09-01 17:05:14 EDT (Sun, 01 Sep 2013) (r85547)
@@ -35,7 +35,16 @@
 
 BOOST_LOG_OPEN_NAMESPACE
 
-using boost::intrusive_ref_counter;
+namespace aux {
+
+struct legacy_intrusive_ref_counter_root
+{
+ virtual ~legacy_intrusive_ref_counter_root() {}
+};
+
+} // namespace aux
+
+typedef boost::intrusive_ref_counter< aux::legacy_intrusive_ref_counter_root > intrusive_ref_counter;
 
 BOOST_LOG_CLOSE_NAMESPACE // namespace log
 

Modified: trunk/boost/smart_ptr/intrusive_ref_counter.hpp
==============================================================================
--- trunk/boost/smart_ptr/intrusive_ref_counter.hpp Sun Sep 1 15:07:06 2013 (r85546)
+++ trunk/boost/smart_ptr/intrusive_ref_counter.hpp 2013-09-01 17:05:14 EDT (Sun, 01 Sep 2013) (r85547)
@@ -27,9 +27,9 @@
 namespace sp_adl_block {
 
 /*!
- * \brief Thread unsafe reference counter policy for \c basic_intrusive_ref_counter
+ * \brief Thread unsafe reference counter policy for \c intrusive_ref_counter
  *
- * The policy instructs the \c basic_intrusive_ref_counter base class to implement
+ * The policy instructs the \c intrusive_ref_counter base class to implement
  * a reference counter suitable for single threaded use only. Pointers to the same
  * object with this kind of reference counter must not be used by different threads.
  */
@@ -54,9 +54,9 @@
 };
 
 /*!
- * \brief Thread safe reference counter policy for \c basic_intrusive_ref_counter
+ * \brief Thread safe reference counter policy for \c intrusive_ref_counter
  *
- * The policy instructs the \c basic_intrusive_ref_counter base class to implement
+ * The policy instructs the \c intrusive_ref_counter base class to implement
  * a thread-safe reference counter, if the target platform supports multithreading.
  */
 struct thread_safe_counter
@@ -79,26 +79,27 @@
     }
 };
 
-template< typename CounterPolicyT >
-class basic_intrusive_ref_counter;
+template< typename DerivedT, typename CounterPolicyT = thread_safe_counter >
+class intrusive_ref_counter;
 
-template< typename CounterPolicyT >
-void intrusive_ptr_add_ref(const basic_intrusive_ref_counter< CounterPolicyT >* p) BOOST_NOEXCEPT;
-template< typename CounterPolicyT >
-void intrusive_ptr_release(const basic_intrusive_ref_counter< CounterPolicyT >* p) BOOST_NOEXCEPT;
+template< typename DerivedT, typename CounterPolicyT >
+void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
+template< typename DerivedT, typename CounterPolicyT >
+void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
 
 /*!
  * \brief A reference counter base class
  *
  * This base class can be used with user-defined classes to add support
- * for \c intrusive_ptr. The class contains a reference counter defined by the \c CounterPolicyT
- * and a virtual destructor, which makes the derived class polymorphic.
+ * for \c intrusive_ptr. The class contains a reference counter defined by the \c CounterPolicyT.
  * Upon releasing the last \c intrusive_ptr referencing the object
- * derived from the \c basic_intrusive_ref_counter class, operator \c delete
+ * derived from the \c intrusive_ref_counter class, operator \c delete
  * is automatically called on the pointer to the object.
+ *
+ * The other template parameter, \c DerivedT, is the user's class that derives from \c intrusive_ref_counter.
  */
-template< typename CounterPolicyT >
-class basic_intrusive_ref_counter
+template< typename DerivedT, typename CounterPolicyT >
+class intrusive_ref_counter
 {
 private:
     //! Reference counter type
@@ -112,7 +113,7 @@
      *
      * \post <tt>use_count() == 0</tt>
      */
- basic_intrusive_ref_counter() : m_ref_counter(0)
+ intrusive_ref_counter() BOOST_NOEXCEPT : m_ref_counter(0)
     {
     }
 
@@ -121,21 +122,16 @@
      *
      * \post <tt>use_count() == 0</tt>
      */
- basic_intrusive_ref_counter(basic_intrusive_ref_counter const&) : m_ref_counter(0)
+ intrusive_ref_counter(intrusive_ref_counter const&) BOOST_NOEXCEPT : m_ref_counter(0)
     {
     }
 
     /*!
- * Virtual destructor
- */
- virtual ~basic_intrusive_ref_counter() {}
-
- /*!
      * Assignment
      *
      * \post The reference counter is not modified after assignment
      */
- basic_intrusive_ref_counter& operator= (basic_intrusive_ref_counter const&) BOOST_NOEXCEPT { return *this; }
+ intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_NOEXCEPT { return *this; }
 
     /*!
      * \return The reference counter
@@ -145,32 +141,35 @@
         return CounterPolicyT::load(m_ref_counter);
     }
 
- friend void intrusive_ptr_add_ref< CounterPolicyT >(const basic_intrusive_ref_counter< CounterPolicyT >* p) BOOST_NOEXCEPT;
- friend void intrusive_ptr_release< CounterPolicyT >(const basic_intrusive_ref_counter< CounterPolicyT >* p) BOOST_NOEXCEPT;
+protected:
+ /*!
+ * Destructor
+ */
+ BOOST_DEFAULTED_FUNCTION(~intrusive_ref_counter(), {})
+
+ friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
+ friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
 };
 
-template< typename CounterPolicyT >
-inline void intrusive_ptr_add_ref(const basic_intrusive_ref_counter< CounterPolicyT >* p) BOOST_NOEXCEPT
+template< typename DerivedT, typename CounterPolicyT >
+inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT
 {
     CounterPolicyT::increment(p->m_ref_counter);
 }
 
-template< typename CounterPolicyT >
-inline void intrusive_ptr_release(const basic_intrusive_ref_counter< CounterPolicyT >* p) BOOST_NOEXCEPT
+template< typename DerivedT, typename CounterPolicyT >
+inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT
 {
     if (CounterPolicyT::decrement(p->m_ref_counter) == 0)
- delete p;
+ delete static_cast< const DerivedT* >(p);
 }
 
 } // namespace sp_adl_block
 
-using sp_adl_block::basic_intrusive_ref_counter;
+using sp_adl_block::intrusive_ref_counter;
 using sp_adl_block::thread_unsafe_counter;
 using sp_adl_block::thread_safe_counter;
 
-//! Convenience typedef for the default reference counter type
-typedef basic_intrusive_ref_counter< thread_safe_counter > intrusive_ref_counter;
-
 } // namespace boost
 
 #endif // BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_

Modified: trunk/libs/smart_ptr/intrusive_ptr.html
==============================================================================
--- trunk/libs/smart_ptr/intrusive_ptr.html Sun Sep 1 15:07:06 2013 (r85546)
+++ trunk/libs/smart_ptr/intrusive_ptr.html 2013-09-01 17:05:14 EDT (Sun, 01 Sep 2013) (r85547)
@@ -25,7 +25,7 @@
                         and <STRONG>intrusive_ptr_release</STRONG> should be defined in the namespace
                         that corresponds to their parameter; otherwise, the definitions need to go in
                         namespace <STRONG>boost</STRONG>. The library provides a helper base class template
- <STRONG>basic_intrusive_ref_counter</STRONG> which may
+ <STRONG>intrusive_ref_counter</STRONG> which may
                         help adding support for <STRONG>intrusive_ptr</STRONG> to user&apos;s types.</p>
                 <p>The class template is parameterized on <b>T</b>, the type of the object pointed
                         to. <STRONG>intrusive_ptr&lt;T&gt;</STRONG> can be implicitly converted to <STRONG>intrusive_ptr&lt;U&gt;</STRONG>

Modified: trunk/libs/smart_ptr/intrusive_ref_counter.html
==============================================================================
--- trunk/libs/smart_ptr/intrusive_ref_counter.html Sun Sep 1 15:07:06 2013 (r85546)
+++ trunk/libs/smart_ptr/intrusive_ref_counter.html 2013-09-01 17:05:14 EDT (Sun, 01 Sep 2013) (r85547)
@@ -1,7 +1,7 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
     <head>
- <title>basic_intrusive_ref_counter</title>
+ <title>intrusive_ref_counter</title>
         <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
     </head>
     <body text="#000000" bgColor="#ffffff">
@@ -13,50 +13,51 @@
             <A href="#Members">Members</A><br>
         </p>
         <h2><a name="Introduction">Introduction</a></h2>
- <p>The <STRONG>basic_intrusive_ref_counter</STRONG> class template implements a reference counter for a defived
+ <p>The <STRONG>intrusive_ref_counter</STRONG> class template implements a reference counter for a derived
             user&apos;s class that is intended to be used with <STRONG>intrusive_ptr</STRONG>.
             The base class has associated <STRONG>intrusive_ptr_add_ref</STRONG> and <STRONG>intrusive_ptr_release</STRONG> functions
             which modify the reference counter as needed and destroy the user's object when the counter drops to zero.</p>
- <p>The class template is parameterized on <STRONG>CounterPolicyT</STRONG>, which is a policy that defines the nature of the reference counter.
+ <p>The class template is parameterized on <STRONG>DerivedT</STRONG> and <STRONG>CounterPolicyT</STRONG> parameters.
+ The first parameter is the user&apos;s class that derives from <STRONG>intrusive_ref_counter</STRONG>. This type
+ is needed in order to destroy the object correctly when there are no references to it left.</p>
+ <p>The second parameter is a policy that defines the nature of the reference counter.
             Boost.SmartPtr provides two such policies: <STRONG>thread_unsafe_counter</STRONG> and <STRONG>thread_safe_counter</STRONG>. The former
- instructs the <STRONG>basic_intrusive_ref_counter</STRONG> base class to use a counter only suitable for a single-threaded use.
+ instructs the <STRONG>intrusive_ref_counter</STRONG> base class to use a counter only suitable for a single-threaded use.
             Pointers to a single object that uses this kind of reference counter must not be used in different threads. The latter policy
             makes the reference counter thread-safe, unless the target platform doesn't support threading. Since in modern systems support for
- threading is common, a shorthand <STRONG>intrusive_ref_counter</STRONG> is provided, which is an alias for
- <STRONG>basic_intrusive_ref_counter&lt;thread_safe_counter&gt;</STRONG>.</p>
+ threading is common, the default counter policy is <STRONG>thread_safe_counter</STRONG>.</p>
         <h2><a name="Synopsis">Synopsis</a></h2>
         <pre>namespace boost {
 
- template&lt;class CounterPolicyT&gt; class basic_intrusive_ref_counter {
-
- public:
-
- basic_intrusive_ref_counter();
- basic_intrusive_ref_counter(basic_intrusive_ref_counter const &amp; r);
+ struct thread_unsafe_counter;
+ struct thread_safe_counter;
 
- virtual ~basic_intrusive_ref_counter();
+ template&lt;class DerivedT, class CounterPolicyT = thread_safe_counter&gt;
+ class intrusive_ref_counter
+ {
+ public:
+ intrusive_ref_counter() = noexcept;
+ intrusive_ref_counter(intrusive_ref_counter const &amp; r) = noexcept;
 
- basic_intrusive_ref_counter &amp; operator=(basic_intrusive_ref_counter const &amp; r) noexcept;
+ intrusive_ref_counter &amp; operator=(intrusive_ref_counter const &amp; r) noexcept;
 
       unsigned int use_count() const noexcept;
- };
 
- struct thread_unsafe_counter;
- struct thread_safe_counter;
-
- typedef basic_intrusive_ref_counter&lt;thread_safe_counter&gt; intrusive_ref_counter;
+ protected:
+ ~intrusive_ref_counter() = default;
+ };
 
 }</pre>
         <h2><a name="Members">Members</a></h2>
         <h3><a name="constructors">constructors</a></h3>
- <pre>basic_intrusive_ref_counter();</pre>
+ <pre>intrusive_ref_counter();</pre>
         <blockquote>
             <p><b>Postconditions:</b> <code>use_count() == 0</code>.</p>
             <p><b>Throws:</b> nothing.</p>
             <P><B>Notes:</B> The pointer to the constructed object is expected to be passed to <STRONG>intrusive_ptr</STRONG>
             constructor, assignment operator or <STRONG>reset()</STRONG> method, which would increment the reference counter.</P>
         </blockquote>
- <pre>basic_intrusive_ref_counter(basic_intrusive_ref_counter const &amp;);</pre>
+ <pre>intrusive_ref_counter(intrusive_ref_counter const &amp;);</pre>
         <blockquote>
             <p><b>Postconditions:</b> <code>use_count() == 0</code>.</p>
             <p><b>Throws:</b> nothing.</p>
@@ -64,12 +65,14 @@
             constructor, assignment operator or <STRONG>reset()</STRONG> method, which would increment the reference counter.</P>
         </blockquote>
         <h3><a name="destructor">destructor</a></h3>
- <pre>virtual ~basic_intrusive_ref_counter();</pre>
+ <pre>~intrusive_ref_counter();</pre>
         <BLOCKQUOTE>
+ <p><b>Throws:</b> nothing.</p>
             <P><B>Effects:</B> Destroys the counter object.</P>
+ <P><B>Notes:</B> The destructor is protected so that the object can only be destroyed through the <STRONG>DerivedT</STRONG> class.</P>
         </BLOCKQUOTE>
         <H3><a name="assignment">assignment</a></H3>
- <pre>basic_intrusive_ref_counter &amp; operator=(basic_intrusive_ref_counter const &amp; r) noexcept;</pre>
+ <pre>intrusive_ref_counter &amp; operator=(intrusive_ref_counter const &amp; r) noexcept;</pre>
         <BLOCKQUOTE>
             <P><B>Effects:</B> Does nothing, reference counter is not modified.</P>
             <P><B>Returns:</B> <code>*this</code>.</P>
@@ -83,7 +86,7 @@
         </BLOCKQUOTE>
         <hr>
         <p>
- $Date: 2013-08-31 23:37:43 +0400 (Sat, 31 Aug 2013) $</p>
+ $Date$</p>
         <p>
             <small>Copyright © 2013 Andrey Semashev. Distributed under the Boost Software License, Version
                 1.0. See accompanying file LICENSE_1_0.txt or

Modified: trunk/libs/smart_ptr/test/intrusive_ref_counter_test.cpp
==============================================================================
--- trunk/libs/smart_ptr/test/intrusive_ref_counter_test.cpp Sun Sep 1 15:07:06 2013 (r85546)
+++ trunk/libs/smart_ptr/test/intrusive_ref_counter_test.cpp 2013-09-01 17:05:14 EDT (Sun, 01 Sep 2013) (r85547)
@@ -38,7 +38,7 @@
 namespace N1 {
 
 class my_class :
- public boost::intrusive_ref_counter
+ public boost::intrusive_ref_counter< my_class >
 {
 public:
     static unsigned int destructor_count;
@@ -56,7 +56,7 @@
 namespace N2 {
 
 class my_class :
- public boost::basic_intrusive_ref_counter< boost::thread_unsafe_counter >
+ public boost::intrusive_ref_counter< my_class, boost::thread_unsafe_counter >
 {
 public:
     static unsigned int destructor_count;
@@ -73,17 +73,18 @@
 
 namespace N3 {
 
-struct X :
- public virtual boost::intrusive_ref_counter
+struct root :
+ public boost::intrusive_ref_counter< root >
 {
+ virtual ~root() {}
 };
 
 } // namespace N3
 
 namespace N4 {
 
-struct Y :
- public virtual boost::intrusive_ref_counter
+struct X :
+ public virtual N3::root
 {
 };
 
@@ -91,9 +92,18 @@
 
 namespace N5 {
 
+struct Y :
+ public virtual N3::root
+{
+};
+
+} // namespace N5
+
+namespace N6 {
+
 struct Z :
- public N3::X,
- public N4::Y
+ public N4::X,
+ public N5::Y
 {
     static unsigned int destructor_count;
 
@@ -105,7 +115,7 @@
 
 unsigned int Z::destructor_count = 0;
 
-} // namespace N5
+} // namespace N6
 
 
 int main()
@@ -130,16 +140,16 @@
 
     // The test checks that destroying through the base class works
     {
- boost::intrusive_ptr< N5::Z > p1 = new N5::Z();
+ boost::intrusive_ptr< N6::Z > p1 = new N6::Z();
         BOOST_TEST(p1->use_count() == 1);
- BOOST_TEST(N5::Z::destructor_count == 0);
- boost::intrusive_ptr< boost::intrusive_ref_counter > p2 = p1;
+ BOOST_TEST(N6::Z::destructor_count == 0);
+ boost::intrusive_ptr< N3::root > p2 = p1;
         BOOST_TEST(p1->use_count() == 2);
- BOOST_TEST(N5::Z::destructor_count == 0);
+ BOOST_TEST(N6::Z::destructor_count == 0);
         p1 = NULL;
- BOOST_TEST(N5::Z::destructor_count == 0);
+ BOOST_TEST(N6::Z::destructor_count == 0);
         p2 = NULL;
- BOOST_TEST(N5::Z::destructor_count == 1);
+ BOOST_TEST(N6::Z::destructor_count == 1);
     }
 
     return boost::report_errors();


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk