$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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()