1#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ATOMIC_HPP_INCLUDED
2#define BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_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// Copyright 2008, 2020 Peter Dimov
11// Distributed under the Boost Software License, Version 1.0.
12// https://www.boost.org/LICENSE_1_0.txt
13
14#include <boost/smart_ptr/detail/yield_k.hpp>
15
16#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
17
18#include <boost/config/pragma_message.hpp>
19BOOST_PRAGMA_MESSAGE("Using __atomic spinlock")
20
21#endif
22
23namespace boost
24{
25
26namespace detail
27{
28
29class spinlock
30{
31public:
32
33 // `bool` alignment is required for Apple PPC32
34 // https://github.com/boostorg/smart_ptr/issues/105
35 // https://github.com/PurpleI2P/i2pd/issues/1726
36 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107590
37
38 union
39 {
40 unsigned char v_;
41 bool align_;
42 };
43
44public:
45
46 bool try_lock()
47 {
48 return __atomic_test_and_set( &v_, __ATOMIC_ACQUIRE ) == 0;
49 }
50
51 void lock()
52 {
53 for( unsigned k = 0; !try_lock(); ++k )
54 {
55 boost::detail::yield( k );
56 }
57 }
58
59 void unlock()
60 {
61 __atomic_clear( &v_, __ATOMIC_RELEASE );
62 }
63
64public:
65
66 class scoped_lock
67 {
68 private:
69
70 spinlock & sp_;
71
72 scoped_lock( scoped_lock const & );
73 scoped_lock & operator=( scoped_lock const & );
74
75 public:
76
77 explicit scoped_lock( spinlock & sp ): sp_( sp )
78 {
79 sp.lock();
80 }
81
82 ~scoped_lock()
83 {
84 sp_.unlock();
85 }
86 };
87};
88
89} // namespace detail
90} // namespace boost
91
92#define BOOST_DETAIL_SPINLOCK_INIT {{0}}
93
94#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ATOMIC_HPP_INCLUDED
95