Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r86447 - in trunk: boost/sync boost/sync/detail/mutexes boost/sync/mutexes libs/sync/test/run
From: tim_at_[hidden]
Date: 2013-10-26 08:32:33


Author: timblechmann
Date: 2013-10-26 08:32:33 EDT (Sat, 26 Oct 2013)
New Revision: 86447
URL: http://svn.boost.org/trac/boost/changeset/86447

Log:
sync: introduce spin_mutex

Added:
   trunk/boost/sync/detail/mutexes/spin_mutex.hpp (contents, props changed)
   trunk/boost/sync/mutexes/spin_mutex.hpp (contents, props changed)
Text files modified:
   trunk/boost/sync/detail/mutexes/spin_mutex.hpp | 133 ++++++++++++++++++++++++++++++++++++++++
   trunk/boost/sync/mutexes.hpp | 1
   trunk/boost/sync/mutexes/spin_mutex.hpp | 86 +++++++++++++++++++++++++
   trunk/libs/sync/test/run/mutex_test.cpp | 6 +
   4 files changed, 226 insertions(+), 0 deletions(-)

Added: trunk/boost/sync/detail/mutexes/spin_mutex.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/boost/sync/detail/mutexes/spin_mutex.hpp 2013-10-26 08:32:33 EDT (Sat, 26 Oct 2013) (r86447)
@@ -0,0 +1,133 @@
+/*
+ * 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 detail/mutexes/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.
+ */
+
+#ifndef BOOST_SYNC_DETAIL_MUTEXES_SPIN_MUTEX_HPP_INCLUDED_
+#define BOOST_SYNC_DETAIL_MUTEXES_SPIN_MUTEX_HPP_INCLUDED_
+
+#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
+
+#if defined(BOOST_SYNC_USE_STD_ATOMIC) && ( ATOMIC_BOOL_LOCKFREE == 2 )
+#define BOOST_SYNC_DETAIL_SPINLOCK_BOOL
+#endif
+#if !defined(BOOST_SYNC_USE_STD_ATOMIC) && ( BOOST_ATOMIC_BOOL_LOCKFREE == 2 )
+#define BOOST_SYNC_DETAIL_SPINLOCK_BOOL
+#endif
+
+namespace boost {
+namespace sync {
+
+#ifdef BOOST_SYNC_DETAIL_SPINLOCK_BOOL
+
+// if we have lockfree booleans, we can make use of test-test-and-set locks
+class spin_mutex
+{
+ static const int locked_state = 0;
+ static const int unlocked_state = 1;
+ detail::atomic_ns::atomic<bool> state;
+
+public:
+ spin_mutex() BOOST_NOEXCEPT:
+ state((bool)unlocked_state)
+ {}
+
+ ~spin_mutex() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( state == unlocked_state );
+ }
+
+ void lock() BOOST_NOEXCEPT
+ {
+ for(;;) {
+ while( state.load(detail::atomic_ns::memory_order_relaxed) != (bool)unlocked_state )
+ detail::pause();
+
+ if (try_lock())
+ break;
+ }
+ }
+
+ bool try_lock() BOOST_NOEXCEPT
+ {
+ return state.exchange( locked_state, detail::atomic_ns::memory_order_acquire) == (bool)unlocked_state;
+ }
+
+ void unlock() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( state.load(detail::atomic_ns::memory_order_relaxed) == (bool)locked_state );
+ state.store( (bool)unlocked_state, detail::atomic_ns::memory_order_release );
+ }
+
+ BOOST_DELETED_FUNCTION(spin_mutex(spin_mutex const&))
+ BOOST_DELETED_FUNCTION(spin_mutex& operator= (spin_mutex const&))
+};
+
+#else
+
+// classic test-and-set lock
+class spin_mutex
+{
+ detail::atomic_ns::atomic_flag state;
+
+public:
+ spin_mutex() BOOST_NOEXCEPT
+ {
+ state.clear();
+ }
+
+ ~spin_mutex() BOOST_NOEXCEPT
+ {}
+
+ void lock() BOOST_NOEXCEPT
+ {
+ for(;;) {
+ if (try_lock())
+ break;
+ detail::pause();
+ }
+ }
+
+ bool try_lock() BOOST_NOEXCEPT
+ {
+ return state.test_and_set( detail::atomic_ns::memory_order_acquire ) == false;
+ }
+
+ void unlock() BOOST_NOEXCEPT
+ {
+ state.clear( detail::atomic_ns::memory_order_release );
+ }
+
+ BOOST_DELETED_FUNCTION(spin_mutex(spin_mutex const&))
+ BOOST_DELETED_FUNCTION(spin_mutex& operator= (spin_mutex const&))
+};
+
+#endif
+
+} // namespace sync
+} // namespace boost
+
+#ifdef BOOST_SYNC_DETAIL_SPINLOCK_BOOL
+#undef BOOST_SYNC_DETAIL_SPINLOCK_BOOL
+#endif
+
+#include <boost/sync/detail/footer.hpp>
+
+#endif // BOOST_SYNC_DETAIL_MUTEXES_SPIN_MUTEX_HPP_INCLUDED_

Modified: trunk/boost/sync/mutexes.hpp
==============================================================================
--- trunk/boost/sync/mutexes.hpp Sat Oct 26 07:59:52 2013 (r86446)
+++ trunk/boost/sync/mutexes.hpp 2013-10-26 08:32:33 EDT (Sat, 26 Oct 2013) (r86447)
@@ -21,6 +21,7 @@
 #endif
 
 #include <boost/sync/mutexes/mutex.hpp>
+#include <boost/sync/mutexes/spin_mutex.hpp>
 #include <boost/sync/mutexes/timed_mutex.hpp>
 
 #endif // BOOST_SYNC_MUTEXES_HPP_INCLUDED_

Added: trunk/boost/sync/mutexes/spin_mutex.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/boost/sync/mutexes/spin_mutex.hpp 2013-10-26 08:32:33 EDT (Sat, 26 Oct 2013) (r86447)
@@ -0,0 +1,86 @@
+/*
+ * 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/spin_mutex.hpp
+ *
+ * \brief This header defines a basic mutex primitive.
+ */
+
+#ifndef BOOST_SYNC_MUTEXES_SPIN_MUTEX_HPP_INCLUDED_
+#define BOOST_SYNC_MUTEXES_SPIN_MUTEX_HPP_INCLUDED_
+
+#if defined(BOOST_SYNC_DETAIL_DOXYGEN)
+
+namespace boost {
+
+namespace sync {
+
+class spin_mutex
+{
+public:
+ /*!
+ * \brief Default constructor
+ *
+ * Creates a mutual exclusion primitive in the unlocked state.
+ */
+ spin_mutex() noexcept;
+
+ /*!
+ * \brief Destructor
+ *
+ * Destroys the mutual exclusion primitive.
+ *
+ * \pre The primitive is in the unlocked state.
+ */
+ ~spin_mutex() noexcept;
+
+ spin_mutex(mutex const&) = delete;
+ spin_mutex& operator= (mutex const&) = delete;
+
+ /*!
+ * \brief Locks the mutex
+ *
+ * If the mutex is not locked, the method locks it and returns. Otherwise the method blocks until the mutex is unlocked.
+ */
+ void lock() noexcept;
+
+ /*!
+ * \brief Attempts to lock the mutex
+ *
+ * If the mutex is not locked, the method locks it and returns \c true. Otherwise the method returns \c false.
+ */
+ bool try_lock() noexcept;
+
+ /*!
+ * \brief Unlocks the mutex
+ *
+ * Releases the mutex that has been locked by the current thread.
+ *
+ * \pre The mutex is locked by the current thread.
+ */
+ void unlock() 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/spin_mutex.hpp>
+
+#endif // defined(BOOST_SYNC_DETAIL_DOXYGEN)
+
+#endif // BOOST_SYNC_MUTEXES_SPIN_MUTEX_HPP_INCLUDED_

Modified: trunk/libs/sync/test/run/mutex_test.cpp
==============================================================================
--- trunk/libs/sync/test/run/mutex_test.cpp Sat Oct 26 07:59:52 2013 (r86446)
+++ trunk/libs/sync/test/run/mutex_test.cpp 2013-10-26 08:32:33 EDT (Sat, 26 Oct 2013) (r86447)
@@ -287,9 +287,15 @@
     test_lock<boost::sync::mutex>()();
 }
 
+void do_test_spin_mutex()
+{
+ test_lock<boost::sync::spin_mutex>()();
+}
+
 BOOST_AUTO_TEST_CASE(test_mutex)
 {
     timed_test(&do_test_mutex, 3);
+ timed_test(&do_test_spin_mutex, 3);
 }
 
 void do_test_try_mutex()


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