Add a spinlock to atomic_shared_ptr

This commit is contained in:
Peter Dimov
2017-06-17 23:37:18 +03:00
parent e462f17c2d
commit 67d897a533
2 changed files with 58 additions and 32 deletions

View File

@@ -36,7 +36,7 @@ namespace boost {
public: public:
atomic_shared_ptr() noexcept = default; atomic_shared_ptr() noexcept = default;
constexpr atomic_shared_ptr( shared_ptr<T> p ) noexcept; atomic_shared_ptr( shared_ptr<T> p ) noexcept;
atomic_shared_ptr& operator=( shared_ptr<T> r ) noexcept; atomic_shared_ptr& operator=( shared_ptr<T> r ) noexcept;
@@ -65,7 +65,7 @@ namespace boost {
## Members ## Members
``` ```
constexpr atomic_shared_ptr( shared_ptr<T> p ) noexcept; atomic_shared_ptr( shared_ptr<T> p ) noexcept;
``` ```
[none] [none]
* {blank} * {blank}

View File

@@ -14,6 +14,8 @@
// //
#include <boost/smart_ptr/shared_ptr.hpp> #include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/detail/spinlock.hpp>
#include <cstring>
namespace boost namespace boost
{ {
@@ -24,35 +26,59 @@ private:
boost::shared_ptr<T> p_; boost::shared_ptr<T> p_;
mutable boost::detail::spinlock l_;
atomic_shared_ptr(const atomic_shared_ptr&); atomic_shared_ptr(const atomic_shared_ptr&);
atomic_shared_ptr& operator=(const atomic_shared_ptr&); atomic_shared_ptr& operator=(const atomic_shared_ptr&);
private:
bool compare_exchange( shared_ptr<T>& v, shared_ptr<T> w ) BOOST_SP_NOEXCEPT
{
l_.lock();
if( p_._internal_equiv( v ) )
{
p_.swap( w );
l_.unlock();
return true;
}
else
{
shared_ptr<T> tmp( p_ );
l_.unlock();
tmp.swap( v );
return false;
}
}
public: public:
atomic_shared_ptr() BOOST_SP_NOEXCEPT atomic_shared_ptr() BOOST_SP_NOEXCEPT
{ {
boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT;
std::memcpy( &l_, &init, sizeof( init ) );
} }
BOOST_CONSTEXPR atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
: p_( std::move( p ) ) : p_( std::move( p ) )
#else #else
: p_( p ) : p_( p )
#endif #endif
{ {
boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT;
std::memcpy( &l_, &init, sizeof( init ) );
} }
atomic_shared_ptr& operator=( shared_ptr<T> r ) BOOST_SP_NOEXCEPT atomic_shared_ptr& operator=( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
{ {
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) boost::detail::spinlock::scoped_lock lock( l_ );
p_.swap( r );
atomic_store( &p_, std::move( r ) );
#else
atomic_store( &p_, r );
#endif
return *this; return *this;
} }
@@ -63,80 +89,80 @@ public:
shared_ptr<T> load( int = 0 ) const BOOST_SP_NOEXCEPT shared_ptr<T> load( int = 0 ) const BOOST_SP_NOEXCEPT
{ {
return atomic_load( &p_ ); boost::detail::spinlock::scoped_lock lock( l_ );
return p_;
} }
operator shared_ptr<T>() const BOOST_SP_NOEXCEPT operator shared_ptr<T>() const BOOST_SP_NOEXCEPT
{ {
return atomic_load( &p_ ); boost::detail::spinlock::scoped_lock lock( l_ );
return p_;
} }
void store( shared_ptr<T> r, int = 0 ) BOOST_SP_NOEXCEPT void store( shared_ptr<T> r, int = 0 ) BOOST_SP_NOEXCEPT
{ {
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) boost::detail::spinlock::scoped_lock lock( l_ );
p_.swap( r );
atomic_store( &p_, std::move( r ) );
#else
atomic_store( &p_, r );
#endif
} }
shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) BOOST_SP_NOEXCEPT shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) BOOST_SP_NOEXCEPT
{ {
{
boost::detail::spinlock::scoped_lock lock( l_ );
p_.swap( r );
}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
return atomic_exchange( &p_, std::move( r ) ); return std::move( r );
#else #else
return atomic_exchange( &p_, r ); return r;
#endif #endif
} }
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) BOOST_SP_NOEXCEPT bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) BOOST_SP_NOEXCEPT
{ {
return atomic_compare_exchange( &p_, &v, w ); return compare_exchange( v, w );
} }
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) BOOST_SP_NOEXCEPT bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) BOOST_SP_NOEXCEPT
{ {
return atomic_compare_exchange( &p_, &v, w ); return compare_exchange( v, w );
} }
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) BOOST_SP_NOEXCEPT bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) BOOST_SP_NOEXCEPT
{ {
return atomic_compare_exchange( &p_, &v, w ); return compare_exchange( v, w );
} }
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) BOOST_SP_NOEXCEPT bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) BOOST_SP_NOEXCEPT
{ {
return atomic_compare_exchange( &p_, &v, w ); return compare_exchange( v, w );
} }
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) BOOST_SP_NOEXCEPT bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) BOOST_SP_NOEXCEPT
{ {
return atomic_compare_exchange( &p_, &v, std::move( w ) ); return compare_exchange( v, std::move( w ) );
} }
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) BOOST_SP_NOEXCEPT bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) BOOST_SP_NOEXCEPT
{ {
return atomic_compare_exchange( &p_, &v, std::move( w ) ); return compare_exchange( v, std::move( w ) );
} }
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) BOOST_SP_NOEXCEPT bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) BOOST_SP_NOEXCEPT
{ {
return atomic_compare_exchange( &p_, &v, std::move( w ) ); return compare_exchange( v, std::move( w ) );
} }
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) BOOST_SP_NOEXCEPT bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) BOOST_SP_NOEXCEPT
{ {
return atomic_compare_exchange( &p_, &v, std::move( w ) ); return compare_exchange( v, std::move( w ) );
} }
#endif #endif