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