1 #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_STD_ATOMIC_HPP_INCLUDED
2 #define BOOST_SMART_PTR_DETAIL_SPINLOCK_STD_ATOMIC_HPP_INCLUDED
3 
4 // MS compatible compilers support #pragma once
5 
6 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
7 # pragma once
8 #endif
9 
10 //
11 //  Copyright (c) 2014 Peter Dimov
12 //
13 //  Distributed under the Boost Software License, Version 1.0.
14 //  See accompanying file LICENSE_1_0.txt or copy at
15 //  http://www.boost.org/LICENSE_1_0.txt)
16 //
17 
18 #include <boost/smart_ptr/detail/yield_k.hpp>
19 #include <atomic>
20 
21 namespace boost
22 {
23 
24 namespace detail
25 {
26 
27 class spinlock
28 {
29 public:
30 
31     std::atomic_flag v_;
32 
33 public:
34 
try_lock()35     bool try_lock()
36     {
37         return !v_.test_and_set( std::memory_order_acquire );
38     }
39 
lock()40     void lock()
41     {
42         for( unsigned k = 0; !try_lock(); ++k )
43         {
44             boost::detail::yield( k );
45         }
46     }
47 
unlock()48     void unlock()
49     {
50         v_ .clear( std::memory_order_release );
51     }
52 
53 public:
54 
55     class scoped_lock
56     {
57     private:
58 
59         spinlock & sp_;
60 
61         scoped_lock( scoped_lock const & );
62         scoped_lock & operator=( scoped_lock const & );
63 
64     public:
65 
scoped_lock(spinlock & sp)66         explicit scoped_lock( spinlock & sp ): sp_( sp )
67         {
68             sp.lock();
69         }
70 
~scoped_lock()71         ~scoped_lock()
72         {
73             sp_.unlock();
74         }
75     };
76 };
77 
78 } // namespace detail
79 } // namespace boost
80 
81 #define BOOST_DETAIL_SPINLOCK_INIT { ATOMIC_FLAG_INIT }
82 
83 #endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_STD_ATOMIC_HPP_INCLUDED
84