$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: pdimov_at_[hidden]
Date: 2008-04-20 10:59:12
Author: pdimov
Date: 2008-04-20 10:59:12 EDT (Sun, 20 Apr 2008)
New Revision: 44636
URL: http://svn.boost.org/trac/boost/changeset/44636
Log:
Atomic access added.
Added:
   trunk/boost/memory_order.hpp   (contents, props changed)
   trunk/libs/smart_ptr/test/sp_atomic_test.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/shared_ptr.hpp           |    64 ++++++++++++++++++++++++++++++++++++++++
   trunk/libs/smart_ptr/test/Jamfile.v2 |     1                                         
   2 files changed, 65 insertions(+), 0 deletions(-)
Added: trunk/boost/memory_order.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/memory_order.hpp	2008-04-20 10:59:12 EDT (Sun, 20 Apr 2008)
@@ -0,0 +1,35 @@
+#ifndef BOOST_MEMORY_ORDER_HPP_INCLUDED
+#define BOOST_MEMORY_ORDER_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//  boost/memory_order.hpp
+//
+//  Defines enum boost::memory_order per the C++0x working draft
+//
+//  Copyright (c) 2008 Peter Dimov
+//
+//  Distributed under the Boost Software License, Version 1.0.
+//  See accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt)
+
+
+namespace boost
+{
+
+enum memory_order
+{
+    memory_order_relaxed = 0,
+    memory_order_acquire = 1,
+    memory_order_release = 2,
+    memory_order_acq_rel = 3, // acquire | release
+    memory_order_seq_cst = 7, // acq_rel | 4
+};
+
+} // namespace boost
+
+#endif // #ifndef BOOST_MEMORY_ORDER_HPP_INCLUDED
Modified: trunk/boost/shared_ptr.hpp
==============================================================================
--- trunk/boost/shared_ptr.hpp	(original)
+++ trunk/boost/shared_ptr.hpp	2008-04-20 10:59:12 EDT (Sun, 20 Apr 2008)
@@ -32,6 +32,11 @@
 #include <boost/detail/shared_count.hpp>
 #include <boost/detail/workaround.hpp>
 
+#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
+#include <boost/detail/spinlock_pool.hpp>
+#include <boost/memory_order.hpp>
+#endif
+
 #include <algorithm>            // for std::swap
 #include <functional>           // for std::less
 #include <typeinfo>             // for std::bad_cast
@@ -472,6 +477,65 @@
         return pn.get_deleter( ti );
     }
 
+    // atomic access
+
+#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
+
+    shared_ptr<T> atomic_load( memory_order /*mo*/ = memory_order_seq_cst ) const
+    {
+        boost::detail::spinlock_pool<2>::scoped_lock lock( this );
+        return *this;
+    }
+
+    void atomic_store( shared_ptr<T> r, memory_order /*mo*/ = memory_order_seq_cst )
+    {
+        boost::detail::spinlock_pool<2>::scoped_lock lock( this );
+        swap( r );
+    }
+
+    shared_ptr<T> atomic_swap( shared_ptr<T> 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<T> & v, shared_ptr<T> 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<T> & v, shared_ptr<T> 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)
 
Modified: trunk/libs/smart_ptr/test/Jamfile.v2
==============================================================================
--- trunk/libs/smart_ptr/test/Jamfile.v2	(original)
+++ trunk/libs/smart_ptr/test/Jamfile.v2	2008-04-20 10:59:12 EDT (Sun, 20 Apr 2008)
@@ -44,5 +44,6 @@
           [ run spinlock_try_test.cpp : : : <threading>multi : spinlock_try_test.mt ]
           [ run spinlock_pool_test.cpp ]
           [ run sp_accept_owner_test.cpp ]
+          [ run sp_atomic_test.cpp ]
         ;
 }
Added: trunk/libs/smart_ptr/test/sp_atomic_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/smart_ptr/test/sp_atomic_test.cpp	2008-04-20 10:59:12 EDT (Sun, 20 Apr 2008)
@@ -0,0 +1,87 @@
+#include <boost/config.hpp>
+
+//  sp_atomic_test.cpp
+//
+//  Copyright (c) 2008 Peter Dimov
+//
+//  Distributed under the Boost Software License, Version 1.0.
+//  See accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt
+
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/shared_ptr.hpp>
+
+//
+
+struct X
+{
+};
+
+#define BOOST_TEST_SP_EQ( p, q ) BOOST_TEST( p == q && !( p < q ) && !( q < p ) )
+
+int main()
+{
+    boost::shared_ptr<X> px( new X );
+
+    {
+        boost::shared_ptr<X> p2 = px.atomic_load();
+        BOOST_TEST_SP_EQ( p2, px );
+
+        boost::shared_ptr<X> px2( new X );
+        px.atomic_store( px2 );
+        BOOST_TEST_SP_EQ( px, px2 );
+
+        p2 = px.atomic_load();
+        BOOST_TEST_SP_EQ( p2, px );
+        BOOST_TEST_SP_EQ( p2, px2 );
+
+        boost::shared_ptr<X> px3( new X );
+        boost::shared_ptr<X> p3 = px.atomic_swap( px3 );
+        BOOST_TEST_SP_EQ( p3, px2 );
+        BOOST_TEST_SP_EQ( px, px3 );
+
+        boost::shared_ptr<X> px4( new X );
+        boost::shared_ptr<X> cmp;
+
+        bool r = px.atomic_compare_swap( cmp, px4 );
+        BOOST_TEST( !r );
+        BOOST_TEST_SP_EQ( px, px3 );
+        BOOST_TEST_SP_EQ( cmp, px3 );
+
+        r = px.atomic_compare_swap( cmp, px4 );
+        BOOST_TEST( r );
+        BOOST_TEST_SP_EQ( px, px4 );
+    }
+
+    //
+
+    px.reset();
+
+    {
+        boost::shared_ptr<X> p2 = px.atomic_load( boost::memory_order_acquire );
+        BOOST_TEST_SP_EQ( p2, px );
+
+        boost::shared_ptr<X> px2( new X );
+        px.atomic_store( px2, boost::memory_order_release );
+        BOOST_TEST_SP_EQ( px, px2 );
+
+        boost::shared_ptr<X> p3 = px.atomic_swap( boost::shared_ptr<X>(), boost::memory_order_acq_rel );
+        BOOST_TEST_SP_EQ( p3, px2 );
+        BOOST_TEST_SP_EQ( px, p2 );
+
+        boost::shared_ptr<X> px4( new X );
+        boost::shared_ptr<X> cmp( px2 );
+
+        bool r = px.atomic_compare_swap( 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 );
+        BOOST_TEST( r );
+        BOOST_TEST_SP_EQ( px, px4 );
+    }
+
+    return boost::report_errors();
+}