$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r51643 - in trunk: boost/smart_ptr libs/smart_ptr/test
From: pdimov_at_[hidden]
Date: 2009-03-07 17:21:57
Author: pdimov
Date: 2009-03-07 17:21:56 EST (Sat, 07 Mar 2009)
New Revision: 51643
URL: http://svn.boost.org/trac/boost/changeset/51643
Log:
De-optimize assignment into this_type(r).swap(*this) - turns out that they were not equivalent, leading to leaks in contrived cases. Refs #2813.
Added:
   trunk/libs/smart_ptr/test/sp_recursive_assign2_rv_test.cpp   (contents, props changed)
   trunk/libs/smart_ptr/test/sp_recursive_assign2_test.cpp   (contents, props changed)
   trunk/libs/smart_ptr/test/sp_recursive_assign_rv_test.cpp   (contents, props changed)
   trunk/libs/smart_ptr/test/sp_recursive_assign_test.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/smart_ptr/shared_ptr.hpp |    27 +++++++++++----------------             
   trunk/libs/smart_ptr/test/Jamfile.v2 |     4 ++++                                    
   2 files changed, 15 insertions(+), 16 deletions(-)
Modified: trunk/boost/smart_ptr/shared_ptr.hpp
==============================================================================
--- trunk/boost/smart_ptr/shared_ptr.hpp	(original)
+++ trunk/boost/smart_ptr/shared_ptr.hpp	2009-03-07 17:21:56 EST (Sat, 07 Mar 2009)
@@ -198,19 +198,7 @@
         boost::detail::sp_enable_shared_from_this( this, p, p );
     }
 
-//  generated copy constructor, assignment, destructor are fine...
-
-//  except that Borland C++ has a bug, and g++ with -Wsynth warns
-#if defined(__BORLANDC__) || defined(__GNUC__)
-
-    shared_ptr & operator=(shared_ptr const & r) // never throws
-    {
-        px = r.px;
-        pn = r.pn; // shared_count::op= doesn't throw
-        return *this;
-    }
-
-#endif
+//  generated copy constructor, destructor are fine
 
     template<class Y>
     explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
@@ -301,13 +289,20 @@
 
 #endif // BOOST_NO_AUTO_PTR
 
-#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
+    // assignment
+
+    shared_ptr & operator=( shared_ptr const & r ) // never throws
+    {
+        this_type(r).swap(*this);
+        return *this;
+    }
+
+#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
 
     template<class Y>
     shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
     {
-        px = r.px;
-        pn = r.pn; // shared_count::op= doesn't throw
+        this_type(r).swap(*this);
         return *this;
     }
 
Modified: trunk/libs/smart_ptr/test/Jamfile.v2
==============================================================================
--- trunk/libs/smart_ptr/test/Jamfile.v2	(original)
+++ trunk/libs/smart_ptr/test/Jamfile.v2	2009-03-07 17:21:56 EST (Sat, 07 Mar 2009)
@@ -52,5 +52,9 @@
           [ run esft_second_ptr_test.cpp ]
           [ run make_shared_esft_test.cpp ]
           [ run allocate_shared_esft_test.cpp ]
+          [ run sp_recursive_assign_test.cpp ]
+          [ run sp_recursive_assign2_test.cpp ]
+          [ run sp_recursive_assign_rv_test.cpp ]
+          [ run sp_recursive_assign2_rv_test.cpp ]
         ;
 }
Added: trunk/libs/smart_ptr/test/sp_recursive_assign2_rv_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/smart_ptr/test/sp_recursive_assign2_rv_test.cpp	2009-03-07 17:21:56 EST (Sat, 07 Mar 2009)
@@ -0,0 +1,114 @@
+//
+//  sp_recursive_assign2_rv_test.cpp
+//
+//  Copyright 2009 Peter Dimov
+//
+//  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
+//
+
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X
+{
+public:
+
+    static int instances;
+
+    X()
+    {
+        ++instances;
+    }
+
+    ~X()
+    {
+        --instances;
+    }
+
+private:
+
+    X( X const& );
+};
+
+int X::instances = 0;
+
+class Y
+{
+public:
+
+    static int instances;
+
+    Y()
+    {
+        ++instances;
+    }
+
+    ~Y()
+    {
+        --instances;
+    }
+
+private:
+
+    Y( Y const& );
+};
+
+int Y::instances = 0;
+
+static boost::shared_ptr<void> s_pv;
+
+class Z
+{
+public:
+
+    static int instances;
+
+    Z()
+    {
+        ++instances;
+    }
+
+    ~Z()
+    {
+        --instances;
+        s_pv = boost::shared_ptr<Y>( new Y );
+    }
+
+private:
+
+    Z( Z const& );
+};
+
+int Z::instances = 0;
+
+int main()
+{
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 0 );
+    BOOST_TEST( Z::instances == 0 );
+
+    s_pv = boost::shared_ptr<Z>( new Z );
+
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 0 );
+    BOOST_TEST( Z::instances == 1 );
+
+    s_pv = boost::shared_ptr<X>( new X );
+
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 1 );
+    BOOST_TEST( Z::instances == 0 );
+
+    s_pv = boost::shared_ptr<Y>();
+
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 0 );
+    BOOST_TEST( Z::instances == 0 );
+
+    return boost::report_errors();
+}
Added: trunk/libs/smart_ptr/test/sp_recursive_assign2_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/smart_ptr/test/sp_recursive_assign2_test.cpp	2009-03-07 17:21:56 EST (Sat, 07 Mar 2009)
@@ -0,0 +1,122 @@
+//
+//  sp_recursive_assign2_test.cpp
+//
+//  Copyright 2009 Peter Dimov
+//
+//  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
+//
+
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X
+{
+public:
+
+    static int instances;
+
+    X()
+    {
+        ++instances;
+    }
+
+    ~X()
+    {
+        --instances;
+    }
+
+private:
+
+    X( X const& );
+};
+
+int X::instances = 0;
+
+class Y
+{
+public:
+
+    static int instances;
+
+    Y()
+    {
+        ++instances;
+    }
+
+    ~Y()
+    {
+        --instances;
+    }
+
+private:
+
+    Y( Y const& );
+};
+
+int Y::instances = 0;
+
+static boost::shared_ptr<void> s_pv;
+
+class Z
+{
+public:
+
+    static int instances;
+
+    Z()
+    {
+        ++instances;
+    }
+
+    ~Z()
+    {
+        --instances;
+
+        boost::shared_ptr<Y> pv( new Y );
+        s_pv = pv;
+    }
+
+private:
+
+    Z( Z const& );
+};
+
+int Z::instances = 0;
+
+int main()
+{
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 0 );
+    BOOST_TEST( Z::instances == 0 );
+
+    {
+        boost::shared_ptr<Z> pv( new Z );
+        s_pv = pv;
+    }
+
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 0 );
+    BOOST_TEST( Z::instances == 1 );
+
+    {
+        boost::shared_ptr<X> pv( new X );
+        s_pv = pv;
+    }
+
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 1 );
+    BOOST_TEST( Z::instances == 0 );
+
+    s_pv.reset();
+
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 0 );
+    BOOST_TEST( Z::instances == 0 );
+
+    return boost::report_errors();
+}
Added: trunk/libs/smart_ptr/test/sp_recursive_assign_rv_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/smart_ptr/test/sp_recursive_assign_rv_test.cpp	2009-03-07 17:21:56 EST (Sat, 07 Mar 2009)
@@ -0,0 +1,114 @@
+//
+//  sp_recursive_assign_rv_test.cpp
+//
+//  Copyright 2009 Peter Dimov
+//
+//  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
+//
+
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X
+{
+public:
+
+    static int instances;
+
+    X()
+    {
+        ++instances;
+    }
+
+    ~X()
+    {
+        --instances;
+    }
+
+private:
+
+    X( X const& );
+};
+
+int X::instances = 0;
+
+class Y
+{
+public:
+
+    static int instances;
+
+    Y()
+    {
+        ++instances;
+    }
+
+    ~Y()
+    {
+        --instances;
+    }
+
+private:
+
+    Y( Y const& );
+};
+
+int Y::instances = 0;
+
+static boost::shared_ptr<void> s_pv;
+
+class Z
+{
+public:
+
+    static int instances;
+
+    Z()
+    {
+        ++instances;
+    }
+
+    ~Z()
+    {
+        --instances;
+        s_pv = boost::shared_ptr<void>( new Y );
+    }
+
+private:
+
+    Z( Z const& );
+};
+
+int Z::instances = 0;
+
+int main()
+{
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 0 );
+    BOOST_TEST( Z::instances == 0 );
+
+    s_pv = boost::shared_ptr<void>( new Z );
+
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 0 );
+    BOOST_TEST( Z::instances == 1 );
+
+    s_pv = boost::shared_ptr<void>( new X );
+
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 1 );
+    BOOST_TEST( Z::instances == 0 );
+
+    s_pv = boost::shared_ptr<void>();
+
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 0 );
+    BOOST_TEST( Z::instances == 0 );
+
+    return boost::report_errors();
+}
Added: trunk/libs/smart_ptr/test/sp_recursive_assign_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/smart_ptr/test/sp_recursive_assign_test.cpp	2009-03-07 17:21:56 EST (Sat, 07 Mar 2009)
@@ -0,0 +1,122 @@
+//
+//  sp_recursive_assign_test.cpp
+//
+//  Copyright 2009 Peter Dimov
+//
+//  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
+//
+
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X
+{
+public:
+
+    static int instances;
+
+    X()
+    {
+        ++instances;
+    }
+
+    ~X()
+    {
+        --instances;
+    }
+
+private:
+
+    X( X const& );
+};
+
+int X::instances = 0;
+
+class Y
+{
+public:
+
+    static int instances;
+
+    Y()
+    {
+        ++instances;
+    }
+
+    ~Y()
+    {
+        --instances;
+    }
+
+private:
+
+    Y( Y const& );
+};
+
+int Y::instances = 0;
+
+static boost::shared_ptr<void> s_pv;
+
+class Z
+{
+public:
+
+    static int instances;
+
+    Z()
+    {
+        ++instances;
+    }
+
+    ~Z()
+    {
+        --instances;
+
+        boost::shared_ptr<void> pv( new Y );
+        s_pv = pv;
+    }
+
+private:
+
+    Z( Z const& );
+};
+
+int Z::instances = 0;
+
+int main()
+{
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 0 );
+    BOOST_TEST( Z::instances == 0 );
+
+    {
+        boost::shared_ptr<void> pv( new Z );
+        s_pv = pv;
+    }
+
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 0 );
+    BOOST_TEST( Z::instances == 1 );
+
+    {
+        boost::shared_ptr<void> pv( new X );
+        s_pv = pv;
+    }
+
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 1 );
+    BOOST_TEST( Z::instances == 0 );
+
+    s_pv.reset();
+
+    BOOST_TEST( X::instances == 0 );
+    BOOST_TEST( Y::instances == 0 );
+    BOOST_TEST( Z::instances == 0 );
+
+    return boost::report_errors();
+}