From 556b9fe563a73e0f710c5992bada5eef7cd5c921 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 16:18:05 +0000 Subject: [PATCH] Merge 47357 (atomic access N2674 edits) from trunk to release. [SVN r47358] --- include/boost/shared_ptr.hpp | 139 +++++++++++++++++++++-------------- test/sp_atomic_mt2_test.cpp | 6 +- test/sp_atomic_mt_test.cpp | 4 +- test/sp_atomic_test.cpp | 22 +++--- 4 files changed, 98 insertions(+), 73 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index ef0d398..ad2bc17 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -5,7 +5,7 @@ // shared_ptr.hpp // // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. -// Copyright (c) 2001-2007 Peter Dimov +// Copyright (c) 2001-2008 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -503,65 +503,11 @@ public: return pn.get_deleter( ti ); } - // atomic access - -#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) - - shared_ptr atomic_load( memory_order /*mo*/ = memory_order_seq_cst ) const + bool _internal_equiv( shared_ptr const & r ) const { - boost::detail::spinlock_pool<2>::scoped_lock lock( this ); - return *this; + return px == r.px && pn == r.pn; } - void atomic_store( shared_ptr r, memory_order /*mo*/ = memory_order_seq_cst ) - { - boost::detail::spinlock_pool<2>::scoped_lock lock( this ); - swap( r ); - } - - shared_ptr atomic_swap( shared_ptr r, memory_order /*mo*/ = memory_order_seq_cst ) - { - boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( this ); - - sp.lock(); - swap( r ); - sp.unlock(); - - return r; // return std::move(r) - } - - bool atomic_compare_swap( shared_ptr & v, shared_ptr w ) - { - boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( this ); - - sp.lock(); - - if( px == v.px && pn == v.pn ) - { - swap( w ); - - sp.unlock(); - - return true; - } - else - { - shared_ptr tmp( *this ); - - sp.unlock(); - - tmp.swap( v ); - return false; - } - } - - inline bool atomic_compare_swap( shared_ptr & v, shared_ptr w, memory_order /*success*/, memory_order /*failure*/ ) - { - return atomic_compare_swap( v, w ); // std::move( w ) - } - -#endif - // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) @@ -715,6 +661,85 @@ template D * get_deleter(shared_ptr const & p) #endif +// atomic access + +#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) + +template inline bool atomic_is_lock_free( shared_ptr const * /*p*/ ) +{ + return false; +} + +template shared_ptr atomic_load( shared_ptr const * p ) +{ + boost::detail::spinlock_pool<2>::scoped_lock lock( p ); + return *p; +} + +template inline shared_ptr atomic_load_explicit( shared_ptr const * p, memory_order /*mo*/ ) +{ + return atomic_load( p ); +} + +template void atomic_store( shared_ptr * p, shared_ptr r ) +{ + boost::detail::spinlock_pool<2>::scoped_lock lock( p ); + p->swap( r ); +} + +template inline void atomic_store_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) +{ + atomic_store( p, r ); // std::move( r ) +} + +template shared_ptr atomic_exchange( shared_ptr * p, shared_ptr r ) +{ + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); + + sp.lock(); + p->swap( r ); + sp.unlock(); + + return r; // return std::move( r ) +} + +template shared_ptr atomic_exchange_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) +{ + return atomic_exchange( p, r ); // std::move( r ) +} + +template bool atomic_compare_exchange( shared_ptr * p, shared_ptr * v, shared_ptr w ) +{ + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); + + sp.lock(); + + if( p->_internal_equiv( *v ) ) + { + p->swap( w ); + + sp.unlock(); + + return true; + } + else + { + shared_ptr tmp( *p ); + + sp.unlock(); + + tmp.swap( *v ); + return false; + } +} + +template inline bool atomic_compare_exchange_explicit( shared_ptr * p, shared_ptr * v, shared_ptr w, memory_order /*success*/, memory_order /*failure*/ ) +{ + return atomic_compare_exchange( p, v, w ); // std::move( w ) +} + +#endif + } // namespace boost #ifdef BOOST_MSVC diff --git a/test/sp_atomic_mt2_test.cpp b/test/sp_atomic_mt2_test.cpp index c865359..6a2e44e 100644 --- a/test/sp_atomic_mt2_test.cpp +++ b/test/sp_atomic_mt2_test.cpp @@ -83,7 +83,7 @@ int read_access( prim_type pt ) case pt_atomics: { - boost::shared_ptr p2 = ps.atomic_load(); + boost::shared_ptr p2 = boost::atomic_load( &ps ); return p2->get(); } } @@ -109,14 +109,14 @@ void write_access( prim_type pt ) case pt_atomics: { - boost::shared_ptr p1 = ps.atomic_load(); + boost::shared_ptr p1 = boost::atomic_load( &ps ); for( ;; ) { boost::shared_ptr p2( new X( *p1 ) ); p2->set(); - if( ps.atomic_compare_swap( p1, p2 ) ) break; + if( boost::atomic_compare_exchange( &ps, &p1, p2 ) ) break; } } break; diff --git a/test/sp_atomic_mt_test.cpp b/test/sp_atomic_mt_test.cpp index 143df98..0f0bf68 100644 --- a/test/sp_atomic_mt_test.cpp +++ b/test/sp_atomic_mt_test.cpp @@ -93,7 +93,7 @@ void reader( int r ) #else - boost::shared_ptr p2 = ps.atomic_load(); + boost::shared_ptr p2 = boost::atomic_load( &ps ); s += p2->get(); @@ -134,7 +134,7 @@ void writer() BOOST_TEST( p2->v_ == i ); p2->set(); - ps.atomic_store( p2 ); + boost::atomic_store( &ps, p2 ); #endif } diff --git a/test/sp_atomic_test.cpp b/test/sp_atomic_test.cpp index c1113da..c8c3586 100644 --- a/test/sp_atomic_test.cpp +++ b/test/sp_atomic_test.cpp @@ -25,31 +25,31 @@ int main() boost::shared_ptr px( new X ); { - boost::shared_ptr p2 = px.atomic_load(); + boost::shared_ptr p2 = boost::atomic_load( &px ); BOOST_TEST_SP_EQ( p2, px ); boost::shared_ptr px2( new X ); - px.atomic_store( px2 ); + boost::atomic_store( &px, px2 ); BOOST_TEST_SP_EQ( px, px2 ); - p2 = px.atomic_load(); + p2 = boost::atomic_load( &px ); BOOST_TEST_SP_EQ( p2, px ); BOOST_TEST_SP_EQ( p2, px2 ); boost::shared_ptr px3( new X ); - boost::shared_ptr p3 = px.atomic_swap( px3 ); + boost::shared_ptr p3 = boost::atomic_exchange( &px, px3 ); BOOST_TEST_SP_EQ( p3, px2 ); BOOST_TEST_SP_EQ( px, px3 ); boost::shared_ptr px4( new X ); boost::shared_ptr cmp; - bool r = px.atomic_compare_swap( cmp, px4 ); + bool r = boost::atomic_compare_exchange( &px, &cmp, px4 ); BOOST_TEST( !r ); BOOST_TEST_SP_EQ( px, px3 ); BOOST_TEST_SP_EQ( cmp, px3 ); - r = px.atomic_compare_swap( cmp, px4 ); + r = boost::atomic_compare_exchange( &px, &cmp, px4 ); BOOST_TEST( r ); BOOST_TEST_SP_EQ( px, px4 ); } @@ -59,26 +59,26 @@ int main() px.reset(); { - boost::shared_ptr p2 = px.atomic_load( boost::memory_order_acquire ); + boost::shared_ptr p2 = boost::atomic_load_explicit( &px, boost::memory_order_acquire ); BOOST_TEST_SP_EQ( p2, px ); boost::shared_ptr px2( new X ); - px.atomic_store( px2, boost::memory_order_release ); + boost::atomic_store_explicit( &px, px2, boost::memory_order_release ); BOOST_TEST_SP_EQ( px, px2 ); - boost::shared_ptr p3 = px.atomic_swap( boost::shared_ptr(), boost::memory_order_acq_rel ); + boost::shared_ptr p3 = boost::atomic_exchange_explicit( &px, boost::shared_ptr(), boost::memory_order_acq_rel ); BOOST_TEST_SP_EQ( p3, px2 ); BOOST_TEST_SP_EQ( px, p2 ); boost::shared_ptr px4( new X ); boost::shared_ptr cmp( px2 ); - bool r = px.atomic_compare_swap( cmp, px4, boost::memory_order_acquire, boost::memory_order_relaxed ); + bool r = boost::atomic_compare_exchange_explicit( &px, &cmp, px4, boost::memory_order_acquire, boost::memory_order_relaxed ); BOOST_TEST( !r ); BOOST_TEST_SP_EQ( px, p2 ); BOOST_TEST_SP_EQ( cmp, p2 ); - r = px.atomic_compare_swap( cmp, px4, boost::memory_order_release, boost::memory_order_acquire ); + r = boost::atomic_compare_exchange_explicit( &px, &cmp, px4, boost::memory_order_release, boost::memory_order_acquire ); BOOST_TEST( r ); BOOST_TEST_SP_EQ( px, px4 ); }