[v3 patch] __shared_ptr<T,_S_single> should never use atomic ops

Jonathan Wakely jwakely.gcc@gmail.com
Mon Nov 18 13:54:00 GMT 2013


This is something I've been meaning to change for years, see
http://gcc.gnu.org/ml/libstdc++/2007-10/msg00180.html for a prior
post. Currently __shared_ptr<T, _S_single> specializations still
dispatch through __gnu_cxx::__exchange_and_add_dispatch for ref-count
updates.  The attached patch means the _S_single policy is always
non-atomic, so that you can get a faster (but not threadsafe!) smart
pointer with:

template<typename T>
  using shared_ptr_unsynchronized
     = std::__shared_ptr<T, std::_S_single>;

This is something I've needed and I've seen others ask about it too e.g.
http://stackoverflow.com/q/15129263/981959
http://stackoverflow.com/q/9792668/981959

2013-11-18  Jonathan Wakely  <jwakely.gcc@gmail.com>

        * include/bits/shared_ptr_base.h (_Sp_counted_base<_S_single>): Use
        non-atomic operations.
        * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust line number.
        * testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise.

Tested x86_64-linux, with --enable-threads and --disable-threads,
committed to trunk.
-------------- next part --------------
commit 1f4fcb52da0e14389ffd53bca6dc060a30d180c2
Author: Jonathan Wakely <jwakely.gcc@gmail.com>
Date:   Mon Nov 18 11:50:19 2013 +0000

    	* include/bits/shared_ptr_base.h (_Sp_counted_base<_S_single>): Use
    	non-atomic operations.
    	* testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust line number.
    	* testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise.

diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
index cf90d7a..68ccc9e 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -209,11 +209,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _Sp_counted_base<_S_single>::
     _M_add_ref_lock()
     {
-      if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
-	{
-	  _M_use_count = 0;
-	  __throw_bad_weak_ptr();
-	}
+      if (_M_use_count == 0)
+	__throw_bad_weak_ptr();
+      ++_M_use_count;
     }
 
   template<>
@@ -248,6 +246,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 					  __ATOMIC_RELAXED));
     }
 
+  template<>
+    inline void
+    _Sp_counted_base<_S_single>::_M_add_ref_copy()
+    { ++_M_use_count; }
+
+  template<>
+    inline void
+    _Sp_counted_base<_S_single>::_M_release() noexcept
+    {
+      if (--_M_use_count == 0)
+        {
+          _M_dispose();
+          if (--_M_weak_count == 0)
+            _M_destroy();
+        }
+    }
+
+  template<>
+    inline void
+    _Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept
+    { ++_M_weak_count; }
+
+  template<>
+    inline void
+    _Sp_counted_base<_S_single>::_M_weak_release() noexcept
+    {
+      if (--_M_weak_count == 0)
+        _M_destroy();
+    }
+
+  template<>
+    inline long
+    _Sp_counted_base<_S_single>::_M_get_use_count() const noexcept
+    { return _M_use_count; }
+
 
   // Forward declarations.
   template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc
index db3fcac..01acca5 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc
@@ -32,7 +32,7 @@ void test01()
 {
   X* px = 0;
   std::shared_ptr<X> p1(px);   // { dg-error "here" }
-  // { dg-error "incomplete" "" { target *-*-* } 779 }
+  // { dg-error "incomplete" "" { target *-*-* } 812 }
 
   std::shared_ptr<X> p9(ap());  // { dg-error "here" }
   // { dg-error "incomplete" "" { target *-*-* } 307 }
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
index 3fd38cf..5389159 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
@@ -25,5 +25,5 @@
 void test01()
 {
   std::shared_ptr<void> p((void*)nullptr);   // { dg-error "here" }
-  // { dg-error "incomplete" "" { target *-*-* } 778 }
+  // { dg-error "incomplete" "" { target *-*-* } 811 }
 }


More information about the Libstdc++ mailing list