Boost logo

Boost-Commit :

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);


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk