From fcec20a7581be7e4a1aa34a4ce0f0316ba03d690 Mon Sep 17 00:00:00 2001
From: Jonathan Wakely <redi@gcc.gnu.org>
Date: Tue, 5 Apr 2005 12:08:55 +0100
Subject: [PATCH] memory, [...]: Use mutex to make
 _Sp_counted_base::add_ref_lock() thread-safe.

	* 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. Add
	empty critical sections to solve memory visibility issues.
	* 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.

From-SVN: r97620
---
 libstdc++-v3/ChangeLog                        | 23 +++++++++++++++++++
 libstdc++-v3/include/tr1/boost_shared_ptr.h   | 14 +++++++----
 libstdc++-v3/include/tr1/memory               |  1 +
 .../enable_shared_from_this/not_shared.cc     |  2 ++
 .../enable_shared_from_this/not_shared2.cc    |  5 ++++
 .../enable_shared_from_this/not_shared3.cc    |  5 ++++
 .../memory/shared_ptr/assign/auto_ptr_neg.cc  |  4 +---
 .../shared_ptr/assign/auto_ptr_rvalue_neg.cc  |  3 +--
 .../memory/shared_ptr/cons/auto_ptr_neg.cc    |  4 +---
 .../shared_ptr/cons/weak_ptr_expired.cc       |  5 ++--
 10 files changed, 52 insertions(+), 14 deletions(-)

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 110376e2c025..7461bd1e3189 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,26 @@
+2005-04-05  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. Add
+	empty critical sections to solve memory visibility issues.
+	* 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-04-05  Kelley Cook  <kcook@gcc.gnu.org>
 
 	* acconfig.h: Delete macros already ACDEFINED.
diff --git a/libstdc++-v3/include/tr1/boost_shared_ptr.h b/libstdc++-v3/include/tr1/boost_shared_ptr.h
index f55c05375865..3426a4acebe4 100644
--- a/libstdc++-v3/include/tr1/boost_shared_ptr.h
+++ b/libstdc++-v3/include/tr1/boost_shared_ptr.h
@@ -131,19 +131,22 @@ public:
   void
   add_ref_lock()
   {
-    if (_M_use_count <= 0) // TODO not yet MT safe XXX
+    __gnu_cxx::lock lock(_M_mutex);
+    if (__gnu_cxx::__exchange_and_add(&_M_use_count, 1) == 0)
     {
+      _M_use_count = 0;
       __throw_bad_weak_ptr();
     }
-    __gnu_cxx::__atomic_add(&_M_use_count, 1);
   }
 
   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();
+      __glibcxx_mutex_lock(_M_mutex);
+      __glibcxx_mutex_unlock(_M_mutex);
       weak_release();
     }
   }
@@ -157,8 +160,10 @@ 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)
     {
+      __glibcxx_mutex_lock(_M_mutex);
+      __glibcxx_mutex_unlock(_M_mutex);
       destroy();
     }
   }
@@ -176,6 +181,7 @@ private:
 
   _Atomic_word _M_use_count;        // #shared
   _Atomic_word _M_weak_count;       // #weak + (#shared != 0)
+  __gnu_cxx::mutex_type _M_mutex;
 };
 
 template <typename _Ptr, typename _Deleter>
diff --git a/libstdc++-v3/include/tr1/memory b/libstdc++-v3/include/tr1/memory
index 93d206e5c290..294d4868a472 100644
--- a/libstdc++-v3/include/tr1/memory
+++ b/libstdc++-v3/include/tr1/memory
@@ -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>
diff --git a/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared.cc b/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared.cc
index 493bd84a77c8..2c36c7ea08a4 100644
--- a/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared.cc
+++ b/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared.cc
@@ -39,10 +39,12 @@ test01()
   }
   catch (const std::tr1::bad_weak_ptr&)
   {
+    // Expected.
     __throw_exception_again;
   }
   catch (...)
   {
+    // Failed.
   }
 
   return 0;
diff --git a/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared2.cc b/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared2.cc
index a6ca74da389b..0043b33dfd4c 100644
--- a/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared2.cc
+++ b/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared2.cc
@@ -41,8 +41,13 @@ test01()
   }
   catch (const std::tr1::bad_weak_ptr&)
   {
+    // Expected.
     __throw_exception_again;
   }
+  catch (...)
+  {
+    // Failed.
+  }
 
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared3.cc b/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared3.cc
index 3bca336bc208..c5e10d1a73ca 100644
--- a/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared3.cc
+++ b/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/enable_shared_from_this/not_shared3.cc
@@ -42,8 +42,13 @@ test01()
   }
   catch (const std::tr1::bad_weak_ptr&)
   {
+    // Expected.
     __throw_exception_again;
   }
+  catch (...)
+  {
+    // Failed.
+  }
 
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/assign/auto_ptr_neg.cc b/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/assign/auto_ptr_neg.cc
index 433f951c1390..587e8e66b865 100644
--- a/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/assign/auto_ptr_neg.cc
+++ b/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/assign/auto_ptr_neg.cc
@@ -47,6 +47,4 @@ main()
   test01();
   return 0;
 }
-// { dg-error "In constructor" "" { target *-*-* } 0 }
-// { dg-error "cannot convert" "" { target *-*-* } 0 }
-// { dg-error "instantiated from" "" { target *-*-* } 0 }
+// { dg-excess-errors "In constructor" }
diff --git a/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/assign/auto_ptr_rvalue_neg.cc b/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/assign/auto_ptr_rvalue_neg.cc
index f119a59a9396..e9678b930092 100644
--- a/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/assign/auto_ptr_rvalue_neg.cc
+++ b/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/assign/auto_ptr_rvalue_neg.cc
@@ -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" }
diff --git a/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/auto_ptr_neg.cc b/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/auto_ptr_neg.cc
index ec219066aacc..9eafc88deb9c 100644
--- a/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/auto_ptr_neg.cc
+++ b/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/auto_ptr_neg.cc
@@ -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" }
diff --git a/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/weak_ptr_expired.cc b/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/weak_ptr_expired.cc
index 8b0213ec726e..63dcae492761 100644
--- a/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/weak_ptr_expired.cc
+++ b/libstdc++-v3/testsuite/tr1/2_general_utilities/memory/shared_ptr/cons/weak_ptr_expired.cc
@@ -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;
 }
-- 
GitLab