$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r86494 - in trunk: boost/sync boost/sync/detail/mutexes boost/sync/mutexes libs/sync/test/run
From: tim_at_[hidden]
Date: 2013-10-28 06:05:25
Author: timblechmann
Date: 2013-10-28 06:05:25 EDT (Mon, 28 Oct 2013)
New Revision: 86494
URL: http://svn.boost.org/trac/boost/changeset/86494
Log:
sync: add shared_spin_mutex
Added:
   trunk/boost/sync/detail/mutexes/shared_spin_mutex.hpp   (contents, props changed)
   trunk/boost/sync/mutexes/shared_spin_mutex.hpp   (contents, props changed)
Text files modified: 
   trunk/boost/sync/detail/mutexes/shared_spin_mutex.hpp |   132 ++++++++++++++++++++++++++++++++++++++++
   trunk/boost/sync/detail/mutexes/spin_mutex.hpp        |     2                                         
   trunk/boost/sync/mutexes.hpp                          |     1                                         
   trunk/boost/sync/mutexes/shared_spin_mutex.hpp        |   110 +++++++++++++++++++++++++++++++++       
   trunk/boost/sync/mutexes/spin_mutex.hpp               |     2                                         
   trunk/libs/sync/test/run/mutex_test.cpp               |     5 +                                       
   6 files changed, 250 insertions(+), 2 deletions(-)
Added: trunk/boost/sync/detail/mutexes/shared_spin_mutex.hpp
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/boost/sync/detail/mutexes/shared_spin_mutex.hpp	2013-10-28 06:05:25 EDT (Mon, 28 Oct 2013)	(r86494)
@@ -0,0 +1,132 @@
+/*
+ * 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)
+ *
+ * (C) Copyright 2013 Tim Blechmann
+ */
+
+/*!
+ * \file   detail/mutexes/shared_spin_mutex.hpp
+ *
+ * \brief  This header is the Boost.Sync library implementation, see the library documentation
+ *         at http://www.boost.org/doc/libs/release/libs/sync/doc/html/index.html.
+ */
+
+
+/** \file shared_spin_mutex.hpp */
+
+#ifndef BOOST_SYNC_DETAIL_MUTEXES_SHARED_SPIN_MUTEX_HPP_INCLUDED_
+#define BOOST_SYNC_DETAIL_MUTEXES_SHARED_SPIN_MUTEX_HPP_INCLUDED_
+
+#include <boost/cstdint.hpp>
+
+#include <boost/sync/detail/atomic.hpp>
+#include <boost/sync/detail/pause.hpp>
+
+#include <boost/sync/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+namespace sync  {
+
+class shared_spin_mutex
+{
+    enum {
+        unlocked_state = 0,
+        reader_mask    = 0x7fffffff,
+        locked_state   = 0x80000000
+    };
+
+    BOOST_DELETED_FUNCTION(shared_spin_mutex(shared_spin_mutex const&))
+    BOOST_DELETED_FUNCTION(shared_spin_mutex& operator= (shared_spin_mutex const&))
+
+public:
+    shared_spin_mutex() BOOST_NOEXCEPT:
+        state(uint32_t(unlocked_state))
+    {}
+
+    ~shared_spin_mutex() BOOST_NOEXCEPT
+    {
+        BOOST_ASSERT(state == unlocked_state);
+    }
+
+    void lock() BOOST_NOEXCEPT
+    {
+        for (;;) {
+            while( state.load(detail::atomic_ns::memory_order_relaxed) != unlocked_state )
+                detail::pause();
+
+            uint32_t expected = unlocked_state;
+            if( state.compare_exchange_weak(expected, locked_state,
+                                            detail::atomic_ns::memory_order_acquire,
+                                            detail::atomic_ns::memory_order_relaxed) )
+                break;
+        }
+    }
+
+    bool try_lock() BOOST_NOEXCEPT
+    {
+        uint32_t expected = unlocked_state;
+        if ( state.compare_exchange_strong(expected, locked_state, detail::atomic_ns::memory_order_acquire,
+                                           detail::atomic_ns::memory_order_relaxed) )
+            return true;
+        else
+            return false;
+    }
+
+    void unlock() BOOST_NOEXCEPT
+    {
+        BOOST_ASSERT( state.load(detail::atomic_ns::memory_order_relaxed) == locked_state );
+        state.store( unlocked_state, detail::atomic_ns::memory_order_release );
+    }
+
+    void lock_shared() BOOST_NOEXCEPT
+    {
+        for(;;) {
+            while( state.load(detail::atomic_ns::memory_order_relaxed) == locked_state )
+                detail::pause();
+
+
+            /* with the mask, the cas will fail, locked exclusively */
+            uint32_t current_state    = state.load(detail::atomic_ns::memory_order_acquire) & reader_mask;
+            const uint32_t next_state = current_state + 1;
+
+            if ( state.compare_exchange_weak(current_state, next_state, detail::atomic_ns::memory_order_acquire,
+                                             detail::atomic_ns::memory_order_relaxed) )
+                break;
+            detail::pause();
+        }
+    }
+
+    bool try_lock_shared() BOOST_NOEXCEPT
+    {
+        /* with the mask, the cas will fail, locked exclusively */
+        uint32_t current_state    = state.load(detail::atomic_ns::memory_order_acquire) & reader_mask;
+        const uint32_t next_state = current_state + 1;
+
+        if ( state.compare_exchange_strong(current_state, next_state, detail::atomic_ns::memory_order_acquire,
+                                           detail::atomic_ns::memory_order_relaxed) )
+            return true;
+        else
+            return false;
+    }
+
+    void unlock_shared() BOOST_NOEXCEPT
+    {
+        state.fetch_sub( 1, detail::atomic_ns::memory_order_release );
+    }
+
+private:
+    detail::atomic_ns::atomic<uint32_t> state;
+};
+
+} // namespace sync
+} // namespace boost
+
+#include <boost/sync/detail/footer.hpp>
+
+#endif /* BOOST_SYNC_DETAIL_MUTEXES_SHARED_SPIN_MUTEX_HPP_INCLUDED_ */
Modified: trunk/boost/sync/detail/mutexes/spin_mutex.hpp
==============================================================================
--- trunk/boost/sync/detail/mutexes/spin_mutex.hpp	Sun Oct 27 22:31:55 2013	(r86493)
+++ trunk/boost/sync/detail/mutexes/spin_mutex.hpp	2013-10-28 06:05:25 EDT (Mon, 28 Oct 2013)	(r86494)
@@ -67,7 +67,7 @@
 
     bool try_lock() BOOST_NOEXCEPT
     {
-        return state.exchange( locked_state, detail::atomic_ns::memory_order_acquire) == (bool)unlocked_state;
+        return state.exchange( locked_state, detail::atomic_ns::memory_order_acquire ) == (bool)unlocked_state;
     }
 
     void unlock() BOOST_NOEXCEPT
Modified: trunk/boost/sync/mutexes.hpp
==============================================================================
--- trunk/boost/sync/mutexes.hpp	Sun Oct 27 22:31:55 2013	(r86493)
+++ trunk/boost/sync/mutexes.hpp	2013-10-28 06:05:25 EDT (Mon, 28 Oct 2013)	(r86494)
@@ -21,6 +21,7 @@
 #endif
 
 #include <boost/sync/mutexes/mutex.hpp>
+#include <boost/sync/mutexes/shared_spin_mutex.hpp>
 #include <boost/sync/mutexes/spin_mutex.hpp>
 #include <boost/sync/mutexes/timed_mutex.hpp>
 
Added: trunk/boost/sync/mutexes/shared_spin_mutex.hpp
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/boost/sync/mutexes/shared_spin_mutex.hpp	2013-10-28 06:05:25 EDT (Mon, 28 Oct 2013)	(r86494)
@@ -0,0 +1,110 @@
+/*
+ * 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)
+ *
+ * (C) Copyright 2013 Andrey Semashev
+ * (C) Copyright 2013 Tim Blechmann
+ */
+/*!
+ * \file   sync/mutexes/shared_shared_spin_mutex.hpp
+ *
+ * \brief  This header defines a shared spin mutex primitive.
+ */
+
+#ifndef BOOST_SYNC_MUTEXES_SHARED_SPIN_MUTEX_HPP_INCLUDED_
+#define BOOST_SYNC_MUTEXES_SHARED_SPIN_MUTEX_HPP_INCLUDED_
+
+#if defined(BOOST_SYNC_DETAIL_DOXYGEN)
+
+namespace boost {
+
+namespace sync {
+
+class shared_spin_mutex
+{
+public:
+    /*!
+     * \brief Default constructor
+     *
+     * Creates a mutual exclusion primitive in the unlocked state.
+     */
+    shared_spin_mutex() noexcept;
+
+    /*!
+     * \brief Destructor
+     *
+     * Destroys the mutual exclusion primitive.
+     *
+     * \pre The primitive is in the unlocked state.
+     */
+    ~shared_spin_mutex() noexcept;
+
+    shared_spin_mutex(mutex const&) = delete;
+    shared_spin_mutex& operator= (mutex const&) = delete;
+
+    /*!
+     * \brief Exclusively locks the mutex
+     *
+     * If the mutex is not locked, the method acquires an exclusive lock and returns. Otherwise the method blocks until the mutex is unlocked.
+     */
+    void lock() noexcept;
+
+    /*!
+     * \brief Attempts to exclusively lock the mutex
+     *
+     * If the mutex is not locked, the method acquires an exclusive lock and returns \c true. Otherwise the method returns \c false.
+     */
+    bool try_lock() noexcept;
+
+    /*!
+     * \brief Unlocks the mutex
+     *
+     * Releases the mutex that has been exclusively locked by the current thread.
+     *
+     * \pre The mutex is exclusively locked by the current thread.
+     */
+    void unlock() noexcept;
+
+    /*!
+     * \brief Shared locks the mutex
+     *
+     * If the mutex is not exclusively locked or shared locked, the method acquires a shared lock and returns. Otherwise the method blocks until the mutex is unlocked.
+     */
+    void lock_shared() noexcept;
+
+    /*!
+     * \brief Attempts to exclusively lock the mutex
+     *
+     * If the mutex is not exclusively locked or shared locked, the method acquires a shared lock and returns \c true. Otherwise the method returns \c false.
+     */
+    bool try_lock() noexcept;
+
+    /*!
+     * \brief Unlocks the mutex
+     *
+     * Releases the mutex that has been shared locked by the current thread.
+     *
+     * \pre The mutex is shared locked by the current thread.
+     */
+    void unlock_shared() noexcept;
+
+};
+
+} // namespace sync
+
+} // namespace boost
+
+#else // defined(BOOST_SYNC_DETAIL_DOXYGEN)
+
+#include <boost/sync/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#include <boost/sync/detail/mutexes/shared_spin_mutex.hpp>
+
+#endif // defined(BOOST_SYNC_DETAIL_DOXYGEN)
+
+#endif // BOOST_SYNC_MUTEXES_SHARED_SPIN_MUTEX_HPP_INCLUDED_
Modified: trunk/boost/sync/mutexes/spin_mutex.hpp
==============================================================================
--- trunk/boost/sync/mutexes/spin_mutex.hpp	Sun Oct 27 22:31:55 2013	(r86493)
+++ trunk/boost/sync/mutexes/spin_mutex.hpp	2013-10-28 06:05:25 EDT (Mon, 28 Oct 2013)	(r86494)
@@ -9,7 +9,7 @@
 /*!
  * \file   sync/mutexes/spin_mutex.hpp
  *
- * \brief  This header defines a basic mutex primitive.
+ * \brief  This header defines a spin mutex primitive.
  */
 
 #ifndef BOOST_SYNC_MUTEXES_SPIN_MUTEX_HPP_INCLUDED_
Modified: trunk/libs/sync/test/run/mutex_test.cpp
==============================================================================
--- trunk/libs/sync/test/run/mutex_test.cpp	Sun Oct 27 22:31:55 2013	(r86493)
+++ trunk/libs/sync/test/run/mutex_test.cpp	2013-10-28 06:05:25 EDT (Mon, 28 Oct 2013)	(r86494)
@@ -292,6 +292,11 @@
     test_lock<boost::sync::spin_mutex>()();
 }
 
+void do_test_shared_spin_mutex()
+{
+    test_lock<boost::sync::shared_spin_mutex>()();
+}
+
 BOOST_AUTO_TEST_CASE(test_mutex)
 {
     timed_test(&do_test_mutex, 3);