diff options
author | Jonathan Wakely <jwakely.gcc@gmail.com> | 2007-11-06 14:28:28 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2007-11-06 14:28:28 +0000 |
commit | 3de36a09ac124ff2b1bf50c822259ca206f88f23 (patch) | |
tree | 5ad6bad437076c580c15f9c56df178120a4ade51 | |
parent | 0eb7e7aa011a0e47a022580c1bc15c10654cb9a2 (diff) | |
download | gcc-3de36a09ac124ff2b1bf50c822259ca206f88f23.zip gcc-3de36a09ac124ff2b1bf50c822259ca206f88f23.tar.gz gcc-3de36a09ac124ff2b1bf50c822259ca206f88f23.tar.bz2 |
boost_shared_ptr.h: Avoid unnecessary memory barriers in _S_atomic case.
2007-11-06 Jonathan Wakely <jwakely.gcc@gmail.com>
* include/tr1_impl/boost_shared_ptr.h: Avoid unnecessary memory
barriers in _S_atomic case.
From-SVN: r129927
-rw-r--r-- | libstdc++-v3/ChangeLog | 5 | ||||
-rw-r--r-- | libstdc++-v3/include/tr1_impl/boost_shared_ptr.h | 53 |
2 files changed, 42 insertions, 16 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 36c9f4b..6dcaed0 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -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> diff --git a/libstdc++-v3/include/tr1_impl/boost_shared_ptr.h b/libstdc++-v3/include/tr1_impl/boost_shared_ptr.h index 55c60bc..5d244aa 100644 --- a/libstdc++-v3/include/tr1_impl/boost_shared_ptr.h +++ b/libstdc++-v3/include/tr1_impl/boost_shared_ptr.h @@ -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) |