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
This commit is contained in:
Jonathan Wakely 2007-11-06 14:28:28 +00:00 committed by Jonathan Wakely
parent 0eb7e7aa01
commit 3de36a09ac
2 changed files with 42 additions and 16 deletions

View 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> 2007-11-05 Chris Jefferson <chris@bubblescope.net>
Paolo Carlini <pcarlini@suse.de> Paolo Carlini <pcarlini@suse.de>

View File

@ -94,12 +94,22 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
// Empty helper class except when the template argument is _S_mutex. // Empty helper class except when the template argument is _S_mutex.
template<_Lock_policy _Lp> template<_Lock_policy _Lp>
class _Mutex_base class _Mutex_base
{ }; {
protected:
// The atomic policy uses fully-fenced builtins, single doesn't care.
enum { _S_need_barriers = 0 };
};
template<> template<>
class _Mutex_base<_S_mutex> class _Mutex_base<_S_mutex>
: public __gnu_cxx::__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> template<_Lock_policy _Lp = __default_lock_policy>
class _Sp_counted_base class _Sp_counted_base
@ -136,14 +146,19 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
void void
_M_release() // nothrow _M_release() // nothrow
{ {
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
-1) == 1)
{ {
_M_dispose(); _M_dispose();
#ifdef __GTHREADS // There must be a memory barrier between dispose() and destroy()
_GLIBCXX_READ_MEM_BARRIER; // to ensure that the effects of dispose() are observed in the
_GLIBCXX_WRITE_MEM_BARRIER; // thread that runs destroy().
#endif // 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, if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
-1) == 1) -1) == 1)
_M_destroy(); _M_destroy();
@ -159,18 +174,25 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
{ {
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1) if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
{ {
#ifdef __GTHREADS if (_Mutex_base<_Lp>::_S_need_barriers)
_GLIBCXX_READ_MEM_BARRIER; {
_GLIBCXX_WRITE_MEM_BARRIER; // See _M_release(),
#endif // destroy() must observe results of dispose()
_GLIBCXX_READ_MEM_BARRIER;
_GLIBCXX_WRITE_MEM_BARRIER;
}
_M_destroy(); _M_destroy();
} }
} }
long long
_M_get_use_count() const // nothrow _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: private:
_Sp_counted_base(_Sp_counted_base const&); _Sp_counted_base(_Sp_counted_base const&);
_Sp_counted_base& operator=(_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) // __shared_ptr will release __p by calling __d(__p)
// //
@ -552,7 +574,6 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
* with @a __r. * with @a __r.
* @param __r A %__shared_ptr. * @param __r A %__shared_ptr.
* @post get() == __r.get() && use_count() == __r.use_count() * @post get() == __r.get() && use_count() == __r.use_count()
* @throw std::bad_alloc, in which case
*/ */
template<typename _Tp1> template<typename _Tp1>
__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r)