aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely.gcc@gmail.com>2007-11-06 14:28:28 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2007-11-06 14:28:28 +0000
commit3de36a09ac124ff2b1bf50c822259ca206f88f23 (patch)
tree5ad6bad437076c580c15f9c56df178120a4ade51
parent0eb7e7aa011a0e47a022580c1bc15c10654cb9a2 (diff)
downloadgcc-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/ChangeLog5
-rw-r--r--libstdc++-v3/include/tr1_impl/boost_shared_ptr.h53
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)