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:
parent
0eb7e7aa01
commit
3de36a09ac
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue