]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
2007-11-06 Jonathan Wakely <jwakely.gcc@gmail.com>
authorredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Nov 2007 14:28:28 +0000 (14:28 +0000)
committerredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Nov 2007 14:28:28 +0000 (14:28 +0000)
* include/tr1_impl/boost_shared_ptr.h: Avoid unnecessary memory
barriers in _S_atomic case.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@129927 138bc75d-0d04-0410-961f-82ee72b054a4

libstdc++-v3/ChangeLog
libstdc++-v3/include/tr1_impl/boost_shared_ptr.h

index 36c9f4bfb4f120a92eddcc5a0c0d465e2db158c8..6dcaed004d3ca47a7ccd05985360673a7341b0c0 100644 (file)
@@ -1,3 +1,8 @@
+2007-11-06  Jonathan Wakely  <jwakely.gcc@gmail.com>
+
+       * include/tr1_impl/boost_shared_ptr.h: Avoid unnecessary memory
+       barriers in _S_atomic case.
+
 2007-11-05  Chris Jefferson  <chris@bubblescope.net>
            Paolo Carlini  <pcarlini@suse.de>
 
index 55c60bc0e17d460289ed6e59d2a243bcb5860d8d..5d244aae3e70d57b4eb5abbdee11594ea4503341 100644 (file)
@@ -94,12 +94,22 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
   // Empty helper class except when the template argument is _S_mutex.
   template<_Lock_policy _Lp>
     class _Mutex_base
-    { };
+    {
+    protected:
+      // The atomic policy uses fully-fenced builtins, single doesn't care.
+      enum { _S_need_barriers = 0 };
+    };
 
   template<>
     class _Mutex_base<_S_mutex>
     : public __gnu_cxx::__mutex
-    { };
+    {
+    protected:
+      // This policy is used when atomic builtins are not available.
+      // The replacement atomic operations might not have the necessary
+      // memory barriers.
+      enum { _S_need_barriers = 1 };
+    };
 
   template<_Lock_policy _Lp = __default_lock_policy>
     class _Sp_counted_base
@@ -136,14 +146,19 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
       void
       _M_release() // nothrow
       {
-       if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count,
-                                                  -1) == 1)
+       if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
          {
            _M_dispose();
-#ifdef __GTHREADS
-           _GLIBCXX_READ_MEM_BARRIER;
-           _GLIBCXX_WRITE_MEM_BARRIER;
-#endif
+           // There must be a memory barrier between dispose() and destroy()
+           // to ensure that the effects of dispose() are observed in the
+           // thread that runs destroy().
+           // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html
+           if (_Mutex_base<_Lp>::_S_need_barriers)
+             {
+               _GLIBCXX_READ_MEM_BARRIER;
+               _GLIBCXX_WRITE_MEM_BARRIER;
+             }
+
            if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
                                                       -1) == 1)
              _M_destroy();
@@ -159,18 +174,25 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
       {
        if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
          {
-#ifdef __GTHREADS
-           _GLIBCXX_READ_MEM_BARRIER;
-           _GLIBCXX_WRITE_MEM_BARRIER;
-#endif
+           if (_Mutex_base<_Lp>::_S_need_barriers)
+             {
+               // See _M_release(),
+               // destroy() must observe results of dispose()
+               _GLIBCXX_READ_MEM_BARRIER;
+               _GLIBCXX_WRITE_MEM_BARRIER;
+             }
            _M_destroy();
          }
       }
   
       long
       _M_get_use_count() const // nothrow
-      { return _M_use_count; }  // XXX is this MT safe? 
-      
+      {
+        // No memory barrier is used here so there is no synchronization
+        // with other threads.
+        return const_cast<const volatile _Atomic_word&>(_M_use_count);
+      }
+
     private:  
       _Sp_counted_base(_Sp_counted_base const&);
       _Sp_counted_base& operator=(_Sp_counted_base const&);
@@ -525,7 +547,7 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
        }
 
       //
-      // Requirements: _Deleter' copy constructor and destructor must not throw
+      // Requirements: _Deleter's copy constructor and destructor must not throw
       //
       // __shared_ptr will release __p by calling __d(__p)
       //
@@ -552,7 +574,6 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
        *          with @a __r.
        *  @param  __r  A %__shared_ptr.
        *  @post   get() == __r.get() && use_count() == __r.use_count()
-       *  @throw  std::bad_alloc, in which case 
        */
       template<typename _Tp1>
         __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r)