[patch] Make std::tr1::shared_ptr thread-safe.

Jonathan Wakely cow@compsoc.man.ac.uk
Tue Mar 29 13:00:00 GMT 2005


These patches make std::tr1::shared_ptr thread-safe and change some
tests to check equality, not inequality, since we know what value we
expect and it's better to be precise about what we're checking.

I've also changed some tests so they use "dg-excess-errors" instead of
multiple "dg-error" lines which need their line numbers kept in sync.

Also made one test an XFAIL, so it behaves consistently when using
-fno-exceptions.

Tested x86_64 Linux on mainline, will check 4.0 shortly.

OK to commit to mainline and 4.0 (assuming 4.0 tests also pass) ?

jon


-------------- next part --------------
Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/ChangeLog,v
retrieving revision 1.2945
diff -u -p -r1.2945 ChangeLog
--- ChangeLog	25 Mar 2005 23:24:49 -0000	1.2945
+++ ChangeLog	29 Mar 2005 12:50:56 -0000
@@ -1,3 +1,25 @@
+2005-03-29  Jonathan Wakely  <redi@gcc.gnu.org>
+
+	* include/tr1/memory, include/tr1/boost_shared_ptr.h: Use mutex
+	to make _Sp_counted_base::add_ref_lock() thread-safe. Check whether
+	to destroy resources by testing for equality, not inequality.
+	* testsuite/tr1/2_general_utilities/memory/
+	shared_ptr/cons/auto_ptr_neg.cc: Use dg-excess-errors instead of
+	explicitly listing line numbers which need to be kept in sync.
+	* testsuite/tr1/2_general_utilities/memory/
+	shared_ptr/assign/auto_ptr_neg.cc: Same.
+	* testsuite/tr1/2_general_utilities/memory/
+	shared_ptr/assign/auto_ptr_rvalue_neg.cc: Same.
+	* testsuite/tr1/2_general_utilities/memory/
+	shared_ptr/cons/weak_ptr_expired.cc: Make XFAIL for consistency when
+	-fno-exceptions.
+	* testsuite/tr1/2_general_utilities/memory/
+	enable_shared_from_this/not_shared.cc: Add explanatory comments.
+	* testsuite/tr1/2_general_utilities/memory/
+	enable_shared_from_this/not_shared2.cc: Same.
+	* testsuite/tr1/2_general_utilities/memory/
+	enable_shared_from_this/not_shared3.cc: Same.
+
 2005-03-25  Mark Mitchell  <mark@codesourcery.com>
 
 	* testsuite/lib/libstdc++.exp (libstdc++_init): Define LOCALEDIR
-------------- next part --------------
Index: include/tr1/memory
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/tr1/memory,v
retrieving revision 1.4
diff -u -p -r1.4 memory
--- include/tr1/memory	24 Mar 2005 18:32:17 -0000	1.4
+++ include/tr1/memory	29 Mar 2005 12:28:45 -0000
@@ -43,6 +43,7 @@
 #include <bits/gthr.h>
 #include <bits/atomicity.h>
 #include <bits/functexcept.h>
+#include <bits/concurrence.h>
 #include <debug/debug.h>
 
 #include <tr1/boost_shared_ptr.h>
Index: include/tr1/boost_shared_ptr.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/tr1/boost_shared_ptr.h,v
retrieving revision 1.1
diff -u -p -r1.1 boost_shared_ptr.h
--- include/tr1/boost_shared_ptr.h	24 Mar 2005 18:32:17 -0000	1.1
+++ include/tr1/boost_shared_ptr.h	29 Mar 2005 12:28:45 -0000
@@ -131,17 +131,18 @@ public:
   void
   add_ref_lock()
   {
-    if (_M_use_count <= 0) // TODO not yet MT safe XXX
+    __gnu_cxx::lock lock(_M_mutex);
+    if (_M_use_count == 0)
     {
       __throw_bad_weak_ptr();
     }
-    __gnu_cxx::__atomic_add(&_M_use_count, 1);
+    ++_M_use_count;
   }
 
   void
   release() // nothrow
   {
-    if (__gnu_cxx::__exchange_and_add(&_M_use_count, -1) <= 1)
+    if (__gnu_cxx::__exchange_and_add(&_M_use_count, -1) == 1)
     {
       dispose();
       weak_release();
@@ -157,7 +158,7 @@ public:
   void
   weak_release() // nothrow
   {
-    if (__gnu_cxx::__exchange_and_add(&_M_weak_count, -1) <= 1)
+    if (__gnu_cxx::__exchange_and_add(&_M_weak_count, -1) == 1)
     {
       destroy();
     }
@@ -176,6 +177,7 @@ private:
 
   _Atomic_word _M_use_count;        // #shared
   _Atomic_word _M_weak_count;       // #weak + (#shared != 0)
+  __gnu_cxx::mutex_type _M_mutex;   // used by add_ref_lock()
 };
 
 template <typename _Ptr, typename _Deleter>
-------------- next part --------------
Index: testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared.cc,v
retrieving revision 1.1
diff -u -p -r1.1 not_shared.cc
--- testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared.cc	22 Feb 2005 00:10:19 -0000	1.1
+++ testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared.cc	29 Mar 2005 12:28:45 -0000
@@ -39,10 +39,12 @@ test01()
   }
   catch (const std::tr1::bad_weak_ptr&)
   {
+    // Expected.
     __throw_exception_again;
   }
   catch (...)
   {
+    // Failed.
   }
 
   return 0;
Index: testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared2.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared2.cc,v
retrieving revision 1.1
diff -u -p -r1.1 not_shared2.cc
--- testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared2.cc	22 Feb 2005 00:10:19 -0000	1.1
+++ testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared2.cc	29 Mar 2005 12:28:45 -0000
@@ -41,8 +41,13 @@ test01()
   }
   catch (const std::tr1::bad_weak_ptr&)
   {
+    // Expected.
     __throw_exception_again;
   }
+  catch (...)
+  {
+    // Failed.
+  }
 
   return 0;
 }
Index: testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared3.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared3.cc,v
retrieving revision 1.1
diff -u -p -r1.1 not_shared3.cc
--- testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared3.cc	22 Feb 2005 00:10:19 -0000	1.1
+++ testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared3.cc	29 Mar 2005 12:28:45 -0000
@@ -42,8 +42,13 @@ test01()
   }
   catch (const std::tr1::bad_weak_ptr&)
   {
+    // Expected.
     __throw_exception_again;
   }
+  catch (...)
+  {
+    // Failed.
+  }
 
   return 0;
 }
Index: testsuite/tr1/2_general_utilities/memory/shared_ptr/assign/auto_ptr_rvalue_neg.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/assign/auto_ptr_rvalue_neg.cc,v
retrieving revision 1.2
diff -u -p -r1.2 auto_ptr_rvalue_neg.cc
--- testsuite/tr1/2_general_utilities/memory/shared_ptr/assign/auto_ptr_rvalue_neg.cc	22 Feb 2005 12:50:55 -0000	1.2
+++ testsuite/tr1/2_general_utilities/memory/shared_ptr/assign/auto_ptr_rvalue_neg.cc	29 Mar 2005 12:28:45 -0000
@@ -46,5 +46,4 @@ main()
   test01();
   return 0;
 }
-// { dg-error "auto_ptr" "" { target *-*-* } 0 }
-// { dg-error "shared_ptr" "" { target *-*-* } 0 }
+// { dg-excess-errors "candidates are" }
Index: testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/auto_ptr_neg.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/auto_ptr_neg.cc,v
retrieving revision 1.4
diff -u -p -r1.4 auto_ptr_neg.cc
--- testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/auto_ptr_neg.cc	24 Mar 2005 18:32:18 -0000	1.4
+++ testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/auto_ptr_neg.cc	29 Mar 2005 12:28:45 -0000
@@ -45,6 +45,4 @@ main()
   test01();
   return 0;
 }
-// { dg-error "shared_ptr" "candidates are" { target *-*-* } 478 }
-
-// { dg-error "shared_ptr" "" { target *-*-* } 468 }
+// { dg-excess-errors "candidates are" }
Index: testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/weak_ptr_expired.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/weak_ptr_expired.cc,v
retrieving revision 1.1
diff -u -p -r1.1 weak_ptr_expired.cc
--- testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/weak_ptr_expired.cc	22 Feb 2005 00:10:20 -0000	1.1
+++ testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/weak_ptr_expired.cc	29 Mar 2005 12:28:45 -0000
@@ -1,3 +1,4 @@
+// { dg-do run { xfail *-*-* } }
 // Copyright (C) 2005 Free Software Foundation
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
@@ -34,6 +35,7 @@ test01()
   std::tr1::shared_ptr<A> a1(new A);
   std::tr1::weak_ptr<A> wa(a1);
   a1.reset();
+  VERIFY( wa.expired() );
   try
   {
     std::tr1::shared_ptr<A> a2(wa);
@@ -41,13 +43,12 @@ test01()
   catch (const std::tr1::bad_weak_ptr&)
   {
     // Expected.
+      __throw_exception_again;
   }
   catch (...)
   {
     // Failed.
-    __throw_exception_again;
   }
-  VERIFY( wa.expired() );
 
   return 0;
 }


More information about the Libstdc++ mailing list