summaryrefslogtreecommitdiff
path: root/src/common/std_mutex.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/std_mutex.h')
-rw-r--r--src/common/std_mutex.h365
1 files changed, 365 insertions, 0 deletions
diff --git a/src/common/std_mutex.h b/src/common/std_mutex.h
new file mode 100644
index 000000000..26eb58b62
--- /dev/null
+++ b/src/common/std_mutex.h
@@ -0,0 +1,365 @@
1
2#ifndef MUTEX_H_
3#define MUTEX_H_
4
5#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
6#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
7
8#ifndef __has_include
9#define __has_include(s) 0
10#endif
11
12#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
13// GCC 4.4 provides <mutex>
14#include <mutex>
15#elif __has_include(<mutex>) && !ANDROID
16// Clang + libc++
17#include <mutex>
18#else
19
20// partial <mutex> implementation for win32/pthread
21
22#include <algorithm>
23
24#if defined(_WIN32)
25// WIN32
26#define WIN32_LEAN_AND_MEAN
27#include <Windows.h>
28
29#else
30// POSIX
31#include <pthread.h>
32
33#endif
34
35#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__)
36#define USE_RVALUE_REFERENCES
37#endif
38
39#if defined(_WIN32) && defined(_M_X64)
40#define USE_SRWLOCKS
41#endif
42
43namespace std
44{
45
46class recursive_mutex
47{
48#ifdef _WIN32
49 typedef CRITICAL_SECTION native_type;
50#else
51 typedef pthread_mutex_t native_type;
52#endif
53
54public:
55 typedef native_type* native_handle_type;
56
57 recursive_mutex(const recursive_mutex&) /*= delete*/;
58 recursive_mutex& operator=(const recursive_mutex&) /*= delete*/;
59
60 recursive_mutex()
61 {
62#ifdef _WIN32
63 InitializeCriticalSection(&m_handle);
64#else
65 pthread_mutexattr_t attr;
66 pthread_mutexattr_init(&attr);
67 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
68 pthread_mutex_init(&m_handle, &attr);
69#endif
70 }
71
72 ~recursive_mutex()
73 {
74#ifdef _WIN32
75 DeleteCriticalSection(&m_handle);
76#else
77 pthread_mutex_destroy(&m_handle);
78#endif
79 }
80
81 void lock()
82 {
83#ifdef _WIN32
84 EnterCriticalSection(&m_handle);
85#else
86 pthread_mutex_lock(&m_handle);
87#endif
88 }
89
90 void unlock()
91 {
92#ifdef _WIN32
93 LeaveCriticalSection(&m_handle);
94#else
95 pthread_mutex_unlock(&m_handle);
96#endif
97 }
98
99 bool try_lock()
100 {
101#ifdef _WIN32
102 return (0 != TryEnterCriticalSection(&m_handle));
103#else
104 return !pthread_mutex_trylock(&m_handle);
105#endif
106 }
107
108 native_handle_type native_handle()
109 {
110 return &m_handle;
111 }
112
113private:
114 native_type m_handle;
115};
116
117#if !defined(_WIN32) || defined(USE_SRWLOCKS)
118
119class mutex
120{
121#ifdef _WIN32
122 typedef SRWLOCK native_type;
123#else
124 typedef pthread_mutex_t native_type;
125#endif
126
127public:
128 typedef native_type* native_handle_type;
129
130 mutex(const mutex&) /*= delete*/;
131 mutex& operator=(const mutex&) /*= delete*/;
132
133 mutex()
134 {
135#ifdef _WIN32
136 InitializeSRWLock(&m_handle);
137#else
138 pthread_mutex_init(&m_handle, NULL);
139#endif
140 }
141
142 ~mutex()
143 {
144#ifdef _WIN32
145#else
146 pthread_mutex_destroy(&m_handle);
147#endif
148 }
149
150 void lock()
151 {
152#ifdef _WIN32
153 AcquireSRWLockExclusive(&m_handle);
154#else
155 pthread_mutex_lock(&m_handle);
156#endif
157 }
158
159 void unlock()
160 {
161#ifdef _WIN32
162 ReleaseSRWLockExclusive(&m_handle);
163#else
164 pthread_mutex_unlock(&m_handle);
165#endif
166 }
167
168 bool try_lock()
169 {
170#ifdef _WIN32
171 // XXX TryAcquireSRWLockExclusive requires Windows 7!
172 // return (0 != TryAcquireSRWLockExclusive(&m_handle));
173 return false;
174#else
175 return !pthread_mutex_trylock(&m_handle);
176#endif
177 }
178
179 native_handle_type native_handle()
180 {
181 return &m_handle;
182 }
183
184private:
185 native_type m_handle;
186};
187
188#else
189typedef recursive_mutex mutex; // just use CriticalSections
190
191#endif
192
193enum defer_lock_t { defer_lock };
194enum try_to_lock_t { try_to_lock };
195enum adopt_lock_t { adopt_lock };
196
197template <class Mutex>
198class lock_guard
199{
200public:
201 typedef Mutex mutex_type;
202
203 explicit lock_guard(mutex_type& m)
204 : pm(m)
205 {
206 m.lock();
207 }
208
209 lock_guard(mutex_type& m, adopt_lock_t)
210 : pm(m)
211 {
212 }
213
214 ~lock_guard()
215 {
216 pm.unlock();
217 }
218
219 lock_guard(lock_guard const&) /*= delete*/;
220 lock_guard& operator=(lock_guard const&) /*= delete*/;
221
222private:
223 mutex_type& pm;
224};
225
226template <class Mutex>
227class unique_lock
228{
229public:
230 typedef Mutex mutex_type;
231
232 unique_lock()
233 : pm(NULL), owns(false)
234 {}
235
236 /*explicit*/ unique_lock(mutex_type& m)
237 : pm(&m), owns(true)
238 {
239 m.lock();
240 }
241
242 unique_lock(mutex_type& m, defer_lock_t)
243 : pm(&m), owns(false)
244 {}
245
246 unique_lock(mutex_type& m, try_to_lock_t)
247 : pm(&m), owns(m.try_lock())
248 {}
249
250 unique_lock(mutex_type& m, adopt_lock_t)
251 : pm(&m), owns(true)
252 {}
253
254 //template <class Clock, class Duration>
255 //unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
256
257 //template <class Rep, class Period>
258 //unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
259
260 ~unique_lock()
261 {
262 if (owns_lock())
263 mutex()->unlock();
264 }
265
266#ifdef USE_RVALUE_REFERENCES
267 unique_lock& operator=(const unique_lock&) /*= delete*/;
268
269 unique_lock& operator=(unique_lock&& other)
270 {
271#else
272 unique_lock& operator=(const unique_lock& u)
273 {
274 // ugly const_cast to get around lack of rvalue references
275 unique_lock& other = const_cast<unique_lock&>(u);
276#endif
277 swap(other);
278 return *this;
279 }
280
281#ifdef USE_RVALUE_REFERENCES
282 unique_lock(const unique_lock&) /*= delete*/;
283
284 unique_lock(unique_lock&& other)
285 : pm(NULL), owns(false)
286 {
287#else
288 unique_lock(const unique_lock& u)
289 : pm(NULL), owns(false)
290 {
291 // ugly const_cast to get around lack of rvalue references
292 unique_lock& other = const_cast<unique_lock&>(u);
293#endif
294 swap(other);
295 }
296
297 void lock()
298 {
299 mutex()->lock();
300 owns = true;
301 }
302
303 bool try_lock()
304 {
305 owns = mutex()->try_lock();
306 return owns;
307 }
308
309 //template <class Rep, class Period>
310 //bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
311 //template <class Clock, class Duration>
312 //bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
313
314 void unlock()
315 {
316 mutex()->unlock();
317 owns = false;
318 }
319
320 void swap(unique_lock& u)
321 {
322 std::swap(pm, u.pm);
323 std::swap(owns, u.owns);
324 }
325
326 mutex_type* release()
327 {
328 auto const ret = mutex();
329
330 pm = NULL;
331 owns = false;
332
333 return ret;
334 }
335
336 bool owns_lock() const
337 {
338 return owns;
339 }
340
341 //explicit operator bool () const
342 //{
343 // return owns_lock();
344 //}
345
346 mutex_type* mutex() const
347 {
348 return pm;
349 }
350
351private:
352 mutex_type* pm;
353 bool owns;
354};
355
356template <class Mutex>
357void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y)
358{
359 x.swap(y);
360}
361
362}
363
364#endif
365#endif