1//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Stephen Cleary 2000
4// (C) Copyright Ion Gaztanaga 2015-2017.
5//
6// Distributed under the Boost
7// Software License, Version 1.0. (See accompanying file
8// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10// See http://www.boost.org/libs/container for documentation.
11//
12//////////////////////////////////////////////////////////////////////////////
13
14#ifndef BOOST_CONTAINER_MUTEX_HPP
15#define BOOST_CONTAINER_MUTEX_HPP
16
17#ifndef BOOST_CONFIG_HPP
18# include <boost/config.hpp>
19#endif
20
21#if defined(BOOST_HAS_PRAGMA_ONCE)
22# pragma once
23#endif
24
25//#define BOOST_CONTAINER_NO_MT
26//#define BOOST_CONTAINER_NO_SPINLOCKS
27
28#include <boost/container/detail/config_begin.hpp>
29#include <boost/container/detail/workaround.hpp>
30
31// Extremely Light-Weight wrapper classes for OS thread synchronization
32
33
34
35#define BOOST_MUTEX_HELPER_NONE 0
36#define BOOST_MUTEX_HELPER_WIN32 1
37#define BOOST_MUTEX_HELPER_PTHREAD 2
38#define BOOST_MUTEX_HELPER_SPINLOCKS 3
39
40#if !defined(BOOST_HAS_THREADS) && !defined(BOOST_NO_MT)
41# define BOOST_NO_MT
42#endif
43
44#if defined(BOOST_NO_MT) || defined(BOOST_CONTAINER_NO_MT)
45 // No multithreading -> make locks into no-ops
46 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_NONE
47#else
48 //Taken from dlmalloc
49 #if !defined(BOOST_CONTAINER_NO_SPINLOCKS) && \
50 ((defined(__GNUC__) && \
51 ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \
52 defined(__i386__) || defined(__x86_64__))) || \
53 (defined(_MSC_VER) && _MSC_VER>=1310))
54 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_SPINLOCKS
55 #elif defined(BOOST_HAS_UNISTD_H)
56 #include <unistd.h>
57 #if !defined(BOOST_MUTEX_HELPER) && (defined(_POSIX_THREADS) || defined(BOOST_HAS_PTHREADS))
58 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_PTHREAD
59 #endif
60 #endif
61#endif
62
63#ifndef BOOST_MUTEX_HELPER
64 #error Unable to determine platform mutex type; #define BOOST_NO_MT to assume single-threaded
65#endif
66
67#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
68 //...
69#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
70 #if defined(_MSC_VER)
71 #include <intrin.h>
72 #define interlockedexchange _InterlockedExchange
73 #elif defined(WIN32) && defined(__GNUC__)
74 #define interlockedexchange __sync_lock_test_and_set
75 #endif /* Win32 */
76
77 /* First, define CAS_LOCK and CLEAR_LOCK on ints */
78 /* Note CAS_LOCK defined to return 0 on success */
79
80 #if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
81 #define BOOST_CONTAINER_CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1)
82 #define BOOST_CONTAINER_CLEAR_LOCK(sl) __sync_lock_release(sl)
83
84 #elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
85 /* Custom spin locks for older gcc on x86 */
86 static inline int boost_container_x86_cas_lock(int *sl) {
87 int ret;
88 int val = 1;
89 int cmp = 0;
90 __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
91 : "=a" (ret)
92 : "r" (val), "m" (*(sl)), "0"(cmp)
93 : "memory", "cc");
94 return ret;
95 }
96
97 static inline void boost_container_x86_clear_lock(int* sl) {
98 assert(*sl != 0);
99 int prev = 0;
100 int ret;
101 __asm__ __volatile__ ("lock; xchgl %0, %1"
102 : "=r" (ret)
103 : "m" (*(sl)), "0"(prev)
104 : "memory");
105 }
106
107 #define BOOST_CONTAINER_CAS_LOCK(sl) boost_container_x86_cas_lock(sl)
108 #define BOOST_CONTAINER_CLEAR_LOCK(sl) boost_container_x86_clear_lock(sl)
109
110 #else /* Win32 MSC */
111 #define BOOST_CONTAINER_CAS_LOCK(sl) interlockedexchange((long volatile*)sl, (long)1)
112 #define BOOST_CONTAINER_CLEAR_LOCK(sl) interlockedexchange((long volatile*)sl, (long)0)
113 #endif
114
115 /* How to yield for a spin lock */
116 #define SPINS_PER_YIELD 63
117 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
118 #if !defined( BOOST_USE_WINDOWS_H )
119 #if defined (WIN32_PLATFORM_PSPC)
120 #define BOOST_CONTAINERWINAPI_IMPORT BOOST_SYMBOL_IMPORT
121 #elif defined (_WIN32_WCE)
122 #define BOOST_CONTAINERWINAPI_IMPORT
123 #else
124 #define BOOST_CONTAINERWINAPI_IMPORT BOOST_SYMBOL_IMPORT
125 #endif
126
127 #if defined(WINAPI)
128 #define BOOST_CONTAINERWINAPI_WINAPI_CC WINAPI
129 #else
130 #if defined(_M_IX86) || defined(__i386__)
131 #define BOOST_CONTAINERWINAPI_DETAIL_STDCALL __stdcall
132 #else
133 #define BOOST_CONTAINERWINAPI_DETAIL_STDCALL
134 #endif
135 #define BOOST_CONTAINERWINAPI_WINAPI_CC BOOST_CONTAINERWINAPI_DETAIL_STDCALL
136 #endif
137
138 #if !defined(__LP64__)
139 namespace boost {
140 namespace container_winapi {
141 typedef unsigned long DWORD_;
142 #else
143 typedef unsigned int DWORD_;
144 #endif
145 typedef int BOOL_;
146 }}
147
148 extern "C" {
149 BOOST_CONTAINERWINAPI_IMPORT boost::container_winapi::DWORD_ BOOST_CONTAINERWINAPI_WINAPI_CC
150 SleepEx(
151 boost::container_winapi::DWORD_ dwMilliseconds,
152 boost::container_winapi::BOOL_ bAlertable);
153 } // extern "C"
154 #endif
155
156 namespace boost {
157 namespace container_winapi {
158 using ::SleepEx;
159 }
160 }
161
162 #define SLEEP_EX_DURATION 50 /* delay for yield/sleep */
163 #define SPIN_LOCK_YIELD boost::container_winapi::SleepEx(SLEEP_EX_DURATION, 0)
164 #elif defined (__SVR4) && defined (__sun) /* solaris */
165 #include <thread.h>
166 #define SPIN_LOCK_YIELD thr_yield();
167 #elif !defined(LACKS_SCHED_H)
168 #include <sched.h>
169 #define SPIN_LOCK_YIELD sched_yield();
170 #else
171 #define SPIN_LOCK_YIELD
172 #endif /* ... yield ... */
173
174 #define BOOST_CONTAINER_SPINS_PER_YIELD 63
175 inline int boost_interprocess_spin_acquire_lock(int *sl) {
176 int spins = 0;
177 while (*(volatile int *)sl != 0 ||
178 BOOST_CONTAINER_CAS_LOCK(sl)) {
179 if ((++spins & BOOST_CONTAINER_SPINS_PER_YIELD) == 0) {
180 SPIN_LOCK_YIELD;
181 }
182 }
183 return 0;
184 }
185 #define BOOST_CONTAINER_MLOCK_T int
186 #define BOOST_CONTAINER_TRY_LOCK(sl) !BOOST_CONTAINER_CAS_LOCK(sl)
187 #define BOOST_CONTAINER_RELEASE_LOCK(sl) BOOST_CONTAINER_CLEAR_LOCK(sl)
188 #define BOOST_CONTAINER_ACQUIRE_LOCK(sl) (BOOST_CONTAINER_CAS_LOCK(sl)? boost_interprocess_spin_acquire_lock(sl) : 0)
189 #define BOOST_MOVE_INITIAL_LOCK(sl) (*sl = 0)
190 #define BOOST_CONTAINER_DESTROY_LOCK(sl) (0)
191#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
192 //
193#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
194 #include <pthread.h>
195#endif
196
197namespace boost {
198namespace container {
199namespace dtl {
200
201#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
202 class null_mutex
203 {
204 private:
205 null_mutex(const null_mutex &);
206 void operator=(const null_mutex &);
207
208 public:
209 null_mutex() { }
210
211 static void lock() { }
212 static void unlock() { }
213 };
214
215 typedef null_mutex default_mutex;
216#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
217
218 class spin_mutex
219 {
220 private:
221 BOOST_CONTAINER_MLOCK_T sl;
222 spin_mutex(const spin_mutex &);
223 void operator=(const spin_mutex &);
224
225 public:
226 spin_mutex() { BOOST_MOVE_INITIAL_LOCK(&sl); }
227
228 void lock() { BOOST_CONTAINER_ACQUIRE_LOCK(&sl); }
229 void unlock() { BOOST_CONTAINER_RELEASE_LOCK(&sl); }
230 };
231 typedef spin_mutex default_mutex;
232#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
233 class mutex
234 {
235 private:
236 CRITICAL_SECTION mtx;
237
238 mutex(const mutex &);
239 void operator=(const mutex &);
240
241 public:
242 mutex()
243 { InitializeCriticalSection(&mtx); }
244
245 ~mutex()
246 { DeleteCriticalSection(&mtx); }
247
248 void lock()
249 { EnterCriticalSection(&mtx); }
250
251 void unlock()
252 { LeaveCriticalSection(&mtx); }
253 };
254
255 typedef mutex default_mutex;
256#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
257 class mutex
258 {
259 private:
260 pthread_mutex_t mtx;
261
262 mutex(const mutex &);
263 void operator=(const mutex &);
264
265 public:
266 mutex()
267 { pthread_mutex_init(&mtx, 0); }
268
269 ~mutex()
270 { pthread_mutex_destroy(&mtx); }
271
272 void lock()
273 { pthread_mutex_lock(&mtx); }
274
275 void unlock()
276 { pthread_mutex_unlock(&mtx); }
277 };
278
279 typedef mutex default_mutex;
280#endif
281
282template<class Mutex>
283class scoped_lock
284{
285 public:
286 scoped_lock(Mutex &m)
287 : m_(m)
288 { m_.lock(); }
289 ~scoped_lock()
290 { m_.unlock(); }
291
292 private:
293 Mutex &m_;
294};
295
296} // namespace dtl
297} // namespace container
298} // namespace boost
299
300#undef BOOST_MUTEX_HELPER_WIN32
301#undef BOOST_MUTEX_HELPER_PTHREAD
302#undef BOOST_MUTEX_HELPER_NONE
303#undef BOOST_MUTEX_HELPER
304#undef BOOST_MUTEX_HELPER_SPINLOCKS
305
306#include <boost/container/detail/config_end.hpp>
307
308#endif
309

source code of boost/libs/container/include/boost/container/detail/mutex.hpp