$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r85609 - in branches/release: boost/smart_ptr libs/smart_ptr libs/smart_ptr/test
From: andrey.semashev_at_[hidden]
Date: 2013-09-08 13:17:18
Author: andysem
Date: 2013-09-08 13:17:18 EDT (Sun, 08 Sep 2013)
New Revision: 85609
URL: http://svn.boost.org/trac/boost/changeset/85609
Log:
Merged changes from trunk: added intrusive_ref_counter.
Added:
   branches/release/boost/smart_ptr/intrusive_ref_counter.hpp
      - copied unchanged from r85605, trunk/boost/smart_ptr/intrusive_ref_counter.hpp
   branches/release/libs/smart_ptr/intrusive_ref_counter.html
      - copied unchanged from r85605, trunk/libs/smart_ptr/intrusive_ref_counter.html
   branches/release/libs/smart_ptr/test/intrusive_ref_counter_test.cpp
      - copied unchanged from r85605, trunk/libs/smart_ptr/test/intrusive_ref_counter_test.cpp
Properties modified: 
   branches/release/boost/smart_ptr/   (props changed)
   branches/release/boost/smart_ptr/enable_shared_from_raw.hpp   (props changed)
   branches/release/libs/smart_ptr/   (props changed)
Text files modified: 
   branches/release/boost/smart_ptr/intrusive_ref_counter.hpp          |   187 ++++++++++++++++++++++++++++++++++++++++
   branches/release/libs/smart_ptr/intrusive_ptr.html                  |     4                                         
   branches/release/libs/smart_ptr/intrusive_ref_counter.html          |    95 ++++++++++++++++++++                    
   branches/release/libs/smart_ptr/test/Jamfile.v2                     |     1                                         
   branches/release/libs/smart_ptr/test/intrusive_ref_counter_test.cpp |   156 +++++++++++++++++++++++++++++++++       
   5 files changed, 442 insertions(+), 1 deletions(-)
Copied: branches/release/boost/smart_ptr/intrusive_ref_counter.hpp (from r85605, trunk/boost/smart_ptr/intrusive_ref_counter.hpp)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/boost/smart_ptr/intrusive_ref_counter.hpp	2013-09-08 13:17:18 EDT (Sun, 08 Sep 2013)	(r85609, copy of r85605, trunk/boost/smart_ptr/intrusive_ref_counter.hpp)
@@ -0,0 +1,187 @@
+/*
+ *          Copyright Andrey Semashev 2007 - 2013.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file   intrusive_ref_counter.hpp
+ * \author Andrey Semashev
+ * \date   12.03.2009
+ *
+ * This header contains a reference counter class for \c intrusive_ptr.
+ */
+
+#ifndef BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
+#define BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
+
+#include <boost/config.hpp>
+#include <boost/smart_ptr/detail/atomic_count.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+// This is a bogus MSVC warning, which is flagged by friend declarations of intrusive_ptr_add_ref and intrusive_ptr_release in intrusive_ref_counter:
+// 'name' : the inline specifier cannot be used when a friend declaration refers to a specialization of a function template
+// Note that there is no inline specifier in the declarations.
+#pragma warning(disable: 4396)
+#endif
+
+namespace boost {
+
+namespace sp_adl_block {
+
+/*!
+ * \brief Thread unsafe reference counter policy for \c intrusive_ref_counter
+ *
+ * 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.
+ */
+struct thread_unsafe_counter
+{
+    typedef unsigned int type;
+
+    static unsigned int load(unsigned int const& counter) BOOST_NOEXCEPT
+    {
+        return counter;
+    }
+
+    static void increment(unsigned int& counter) BOOST_NOEXCEPT
+    {
+        ++counter;
+    }
+
+    static unsigned int decrement(unsigned int& counter) BOOST_NOEXCEPT
+    {
+        return --counter;
+    }
+};
+
+/*!
+ * \brief Thread safe reference counter policy for \c intrusive_ref_counter
+ *
+ * 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
+{
+    typedef boost::detail::atomic_count type;
+
+    static unsigned int load(boost::detail::atomic_count const& counter) BOOST_NOEXCEPT
+    {
+        return static_cast< unsigned int >(static_cast< long >(counter));
+    }
+
+    static void increment(boost::detail::atomic_count& counter) BOOST_NOEXCEPT
+    {
+        ++counter;
+    }
+
+    static unsigned int decrement(boost::detail::atomic_count& counter) BOOST_NOEXCEPT
+    {
+        return --counter;
+    }
+};
+
+template< typename DerivedT, typename CounterPolicyT = thread_safe_counter >
+class intrusive_ref_counter;
+
+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.
+ * Upon releasing the last \c intrusive_ptr referencing the object
+ * 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 DerivedT, typename CounterPolicyT >
+class intrusive_ref_counter
+{
+private:
+    //! Reference counter type
+    typedef typename CounterPolicyT::type counter_type;
+    //! Reference counter
+    mutable counter_type m_ref_counter;
+
+public:
+    /*!
+     * Default constructor
+     *
+     * \post <tt>use_count() == 0</tt>
+     */
+    intrusive_ref_counter() BOOST_NOEXCEPT : m_ref_counter(0)
+    {
+    }
+
+    /*!
+     * Copy constructor
+     *
+     * \post <tt>use_count() == 0</tt>
+     */
+    intrusive_ref_counter(intrusive_ref_counter const&) BOOST_NOEXCEPT : m_ref_counter(0)
+    {
+    }
+
+    /*!
+     * Assignment
+     *
+     * \post The reference counter is not modified after assignment
+     */
+    intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_NOEXCEPT { return *this; }
+
+    /*!
+     * \return The reference counter
+     */
+    unsigned int use_count() const BOOST_NOEXCEPT
+    {
+        return CounterPolicyT::load(m_ref_counter);
+    }
+
+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 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 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 static_cast< const DerivedT* >(p);
+}
+
+} // namespace sp_adl_block
+
+using sp_adl_block::intrusive_ref_counter;
+using sp_adl_block::thread_unsafe_counter;
+using sp_adl_block::thread_safe_counter;
+
+} // namespace boost
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
Modified: branches/release/libs/smart_ptr/intrusive_ptr.html
==============================================================================
--- branches/release/libs/smart_ptr/intrusive_ptr.html	Sun Sep  8 13:13:40 2013	(r85608)
+++ branches/release/libs/smart_ptr/intrusive_ptr.html	2013-09-08 13:17:18 EDT (Sun, 08 Sep 2013)	(r85609)
@@ -24,7 +24,9 @@
                         compilers that support argument-dependent lookup, <STRONG>intrusive_ptr_add_ref</STRONG>
                         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>.</p>
+			namespace <STRONG>boost</STRONG>. The library provides a helper base class template
+			<STRONG>intrusive_ref_counter</STRONG> which may
+			help adding support for <STRONG>intrusive_ptr</STRONG> to user's types.</p>
                 <p>The class template is parameterized on <b>T</b>, the type of the object pointed 
                         to. <STRONG>intrusive_ptr<T></STRONG> can be implicitly converted to <STRONG>intrusive_ptr<U></STRONG>
                         whenever <STRONG>T*</STRONG> can be implicitly converted to <STRONG>U*</STRONG>.</p>
Copied: branches/release/libs/smart_ptr/intrusive_ref_counter.html (from r85605, trunk/libs/smart_ptr/intrusive_ref_counter.html)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/libs/smart_ptr/intrusive_ref_counter.html	2013-09-08 13:17:18 EDT (Sun, 08 Sep 2013)	(r85609, copy of r85605, trunk/libs/smart_ptr/intrusive_ref_counter.html)
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+    <head>
+        <title>intrusive_ref_counter</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+    </head>
+    <body text="#000000" bgColor="#ffffff">
+        <h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle"
+                    border="0"></A>basic_intrusive_ref_counter class template</h1>
+        <p>
+            Introduction<br>
+            Synopsis<br>
+            Members<br>
+        </p>
+        <h2><a name="Introduction">Introduction</a></h2>
+        <p>The <STRONG>intrusive_ref_counter</STRONG> class template implements a reference counter for a derived
+            user'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>DerivedT</STRONG> and <STRONG>CounterPolicyT</STRONG> parameters.
+            The first parameter is the user'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>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, the default counter policy is <STRONG>thread_safe_counter</STRONG>.</p>
+        <h2><a name="Synopsis">Synopsis</a></h2>
+        <pre>namespace boost {
+
+  struct thread_unsafe_counter;
+  struct thread_safe_counter;
+
+  template<class DerivedT, class CounterPolicyT = thread_safe_counter>
+  class intrusive_ref_counter
+  {
+  public:
+      intrusive_ref_counter() = noexcept;
+      intrusive_ref_counter(intrusive_ref_counter const & r) = noexcept;
+
+      intrusive_ref_counter & operator=(intrusive_ref_counter const & r) noexcept;
+
+      unsigned int use_count() const noexcept;
+
+  protected:
+      ~intrusive_ref_counter() = default;
+  };
+
+}</pre>
+        <h2><a name="Members">Members</a></h2>
+        <h3><a name="constructors">constructors</a></h3>
+        <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>intrusive_ref_counter(intrusive_ref_counter const &);</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>
+        <h3><a name="destructor">destructor</a></h3>
+        <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>intrusive_ref_counter & operator=(intrusive_ref_counter const & r) noexcept;</pre>
+        <BLOCKQUOTE>
+            <P><B>Effects:</B> Does nothing, reference counter is not modified.</P>
+            <P><B>Returns:</B> <code>*this</code>.</P>
+        </BLOCKQUOTE>
+        <H3><a name="use_count">use_count</a></H3>
+        <pre>unsigned int use_count() const noexcept;</pre>
+        <BLOCKQUOTE>
+            <p><b>Returns:</b> The current value of the reference counter.</p>
+            <p><b>Throws:</b> nothing.</p>
+            <P><B>Notes:</B> The returned value may not be actual in multi-threaded applications.</P>
+        </BLOCKQUOTE>
+        <hr>
+        <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 
+                copy at http://www.boost.org/LICENSE_1_0.txt.</small></p>
+    </body>
+</html>
Modified: branches/release/libs/smart_ptr/test/Jamfile.v2
==============================================================================
--- branches/release/libs/smart_ptr/test/Jamfile.v2	Sun Sep  8 13:13:40 2013	(r85608)
+++ branches/release/libs/smart_ptr/test/Jamfile.v2	2013-09-08 13:17:18 EDT (Sun, 08 Sep 2013)	(r85609)
@@ -21,6 +21,7 @@
           [ run get_deleter_test.cpp ]
           [ run intrusive_ptr_test.cpp ]
           [ run intrusive_ptr_move_test.cpp ]
+          [ run intrusive_ref_counter_test.cpp ]
           [ run atomic_count_test.cpp ]
           [ run lw_mutex_test.cpp ]
           [ compile-fail shared_ptr_assign_fail.cpp ]
Copied: branches/release/libs/smart_ptr/test/intrusive_ref_counter_test.cpp (from r85605, trunk/libs/smart_ptr/test/intrusive_ref_counter_test.cpp)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/release/libs/smart_ptr/test/intrusive_ref_counter_test.cpp	2013-09-08 13:17:18 EDT (Sun, 08 Sep 2013)	(r85609, copy of r85605, trunk/libs/smart_ptr/test/intrusive_ref_counter_test.cpp)
@@ -0,0 +1,156 @@
+/*
+ *             Copyright Andrey Semashev 2013.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file   intrusive_ref_counter_test.cpp
+ * \author Andrey Semashev
+ * \date   31.08.2013
+ *
+ * This file contains tests for the \c intrusive_ref_counter base class.
+ */
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+
+#pragma warning(disable: 4786)  // identifier truncated in debug info
+#pragma warning(disable: 4710)  // function not inlined
+#pragma warning(disable: 4711)  // function selected for automatic inline expansion
+#pragma warning(disable: 4514)  // unreferenced inline removed
+#pragma warning(disable: 4355)  // 'this' : used in base member initializer list
+#pragma warning(disable: 4511)  // copy constructor could not be generated
+#pragma warning(disable: 4512)  // assignment operator could not be generated
+
+#if (BOOST_MSVC >= 1310)
+#pragma warning(disable: 4675)  // resolved overload found with Koenig lookup
+#endif
+
+#endif
+
+#include <cstddef>
+#include <boost/smart_ptr/intrusive_ref_counter.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+namespace N1 {
+
+class my_class :
+    public boost::intrusive_ref_counter< my_class >
+{
+public:
+    static unsigned int destructor_count;
+
+    ~my_class()
+    {
+        ++destructor_count;
+    }
+};
+
+unsigned int my_class::destructor_count = 0;
+
+} // namespace N1
+
+namespace N2 {
+
+class my_class :
+    public boost::intrusive_ref_counter< my_class, boost::thread_unsafe_counter >
+{
+public:
+    static unsigned int destructor_count;
+
+    ~my_class()
+    {
+        ++destructor_count;
+    }
+};
+
+unsigned int my_class::destructor_count = 0;
+
+} // namespace N2
+
+namespace N3 {
+
+struct root :
+    public boost::intrusive_ref_counter< root >
+{
+    virtual ~root() {}
+};
+
+} // namespace N3
+
+namespace N4 {
+
+struct X :
+    public virtual N3::root
+{
+};
+
+} // namespace N4
+
+namespace N5 {
+
+struct Y :
+    public virtual N3::root
+{
+};
+
+} // namespace N5
+
+namespace N6 {
+
+struct Z :
+    public N4::X,
+    public N5::Y
+{
+    static unsigned int destructor_count;
+
+    ~Z()
+    {
+        ++destructor_count;
+    }
+};
+
+unsigned int Z::destructor_count = 0;
+
+} // namespace N6
+
+
+int main()
+{
+    // The test check that ADL works
+    {
+        boost::intrusive_ptr< N1::my_class > p = new N1::my_class();
+        p = NULL;
+        BOOST_TEST(N1::my_class::destructor_count == 1);
+    }
+    {
+        boost::intrusive_ptr< N2::my_class > p = new N2::my_class();
+        p = NULL;
+        BOOST_TEST(N2::my_class::destructor_count == 1);
+    }
+    {
+        N1::my_class* p = new N1::my_class();
+        intrusive_ptr_add_ref(p);
+        intrusive_ptr_release(p);
+        BOOST_TEST(N1::my_class::destructor_count == 2);
+    }
+
+    // The test checks that destroying through the base class works
+    {
+        boost::intrusive_ptr< N6::Z > p1 = new N6::Z();
+        BOOST_TEST(p1->use_count() == 1);
+        BOOST_TEST(N6::Z::destructor_count == 0);
+        boost::intrusive_ptr< N3::root > p2 = p1;
+        BOOST_TEST(p1->use_count() == 2);
+        BOOST_TEST(N6::Z::destructor_count == 0);
+        p1 = NULL;
+        BOOST_TEST(N6::Z::destructor_count == 0);
+        p2 = NULL;
+        BOOST_TEST(N6::Z::destructor_count == 1);
+    }
+
+    return boost::report_errors();
+}