1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | #ifndef _GLIBCXX_MUTEX_H |
31 | #define _GLIBCXX_MUTEX_H 1 |
32 | |
33 | #pragma GCC system_header |
34 | |
35 | #if __cplusplus < 201103L |
36 | # include <bits/c++0x_warning.h> |
37 | #else |
38 | |
39 | #include <system_error> |
40 | #include <bits/functexcept.h> |
41 | #include <bits/gthr.h> |
42 | #include <bits/move.h> |
43 | |
44 | #ifdef _GLIBCXX_USE_C99_STDINT_TR1 |
45 | |
46 | namespace std _GLIBCXX_VISIBILITY(default) |
47 | { |
48 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | #ifdef _GLIBCXX_HAS_GTHREADS |
59 | |
60 | class __mutex_base |
61 | { |
62 | protected: |
63 | typedef __gthread_mutex_t __native_type; |
64 | |
65 | #ifdef __GTHREAD_MUTEX_INIT |
66 | __native_type _M_mutex = __GTHREAD_MUTEX_INIT; |
67 | |
68 | constexpr __mutex_base() noexcept = default; |
69 | #else |
70 | __native_type _M_mutex; |
71 | |
72 | __mutex_base() noexcept |
73 | { |
74 | |
75 | __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); |
76 | } |
77 | |
78 | ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); } |
79 | #endif |
80 | |
81 | __mutex_base(const __mutex_base&) = delete; |
82 | __mutex_base& operator=(const __mutex_base&) = delete; |
83 | }; |
84 | |
85 | |
86 | class mutex : private __mutex_base |
87 | { |
88 | public: |
89 | typedef __native_type* native_handle_type; |
90 | |
91 | #ifdef __GTHREAD_MUTEX_INIT |
92 | constexpr |
93 | #endif |
94 | mutex() noexcept = default; |
95 | ~mutex() = default; |
96 | |
97 | mutex(const mutex&) = delete; |
98 | mutex& operator=(const mutex&) = delete; |
99 | |
100 | void |
101 | lock() |
102 | { |
103 | int __e = __gthread_mutex_lock(&_M_mutex); |
104 | |
105 | |
106 | if (__e) |
107 | __throw_system_error(__e); |
108 | } |
109 | |
110 | bool |
111 | try_lock() noexcept |
112 | { |
113 | |
114 | return !__gthread_mutex_trylock(&_M_mutex); |
115 | } |
116 | |
117 | void |
118 | unlock() |
119 | { |
120 | |
121 | __gthread_mutex_unlock(&_M_mutex); |
122 | } |
123 | |
124 | native_handle_type |
125 | native_handle() noexcept |
126 | { return &_M_mutex; } |
127 | }; |
128 | |
129 | #endif |
130 | |
131 | |
132 | struct defer_lock_t { explicit defer_lock_t() = default; }; |
133 | |
134 | |
135 | struct try_to_lock_t { explicit try_to_lock_t() = default; }; |
136 | |
137 | |
138 | |
139 | struct adopt_lock_t { explicit adopt_lock_t() = default; }; |
140 | |
141 | |
142 | _GLIBCXX17_INLINE constexpr defer_lock_t defer_lock { }; |
143 | |
144 | |
145 | _GLIBCXX17_INLINE constexpr try_to_lock_t try_to_lock { }; |
146 | |
147 | |
148 | _GLIBCXX17_INLINE constexpr adopt_lock_t adopt_lock { }; |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | template<typename _Mutex> |
156 | class lock_guard |
157 | { |
158 | public: |
159 | typedef _Mutex mutex_type; |
160 | |
161 | explicit lock_guard(mutex_type& __m) : _M_device(__m) |
162 | { _M_device.lock(); } |
163 | |
164 | lock_guard(mutex_type& __m, adopt_lock_t) noexcept : _M_device(__m) |
165 | { } |
166 | |
167 | ~lock_guard() |
168 | { _M_device.unlock(); } |
169 | |
170 | lock_guard(const lock_guard&) = delete; |
171 | lock_guard& operator=(const lock_guard&) = delete; |
172 | |
173 | private: |
174 | mutex_type& _M_device; |
175 | }; |
176 | |
177 | |
178 | |
179 | |
180 | |
181 | |
182 | |
183 | |
184 | template<typename _Mutex> |
185 | class unique_lock |
186 | { |
187 | public: |
188 | typedef _Mutex mutex_type; |
189 | |
190 | unique_lock() noexcept |
191 | : _M_device(0), _M_owns(false) |
192 | { } |
193 | |
194 | explicit unique_lock(mutex_type& __m) |
195 | : _M_device(std::__addressof(__m)), _M_owns(false) |
196 | { |
197 | lock(); |
198 | _M_owns = true; |
199 | } |
200 | |
201 | unique_lock(mutex_type& __m, defer_lock_t) noexcept |
202 | : _M_device(std::__addressof(__m)), _M_owns(false) |
203 | { } |
204 | |
205 | unique_lock(mutex_type& __m, try_to_lock_t) |
206 | : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock()) |
207 | { } |
208 | |
209 | unique_lock(mutex_type& __m, adopt_lock_t) noexcept |
210 | : _M_device(std::__addressof(__m)), _M_owns(true) |
211 | { |
212 | |
213 | } |
214 | |
215 | template<typename _Clock, typename _Duration> |
216 | unique_lock(mutex_type& __m, |
217 | const chrono::time_point<_Clock, _Duration>& __atime) |
218 | : _M_device(std::__addressof(__m)), |
219 | _M_owns(_M_device->try_lock_until(__atime)) |
220 | { } |
221 | |
222 | template<typename _Rep, typename _Period> |
223 | unique_lock(mutex_type& __m, |
224 | const chrono::duration<_Rep, _Period>& __rtime) |
225 | : _M_device(std::__addressof(__m)), |
226 | _M_owns(_M_device->try_lock_for(__rtime)) |
227 | { } |
228 | |
229 | ~unique_lock() |
230 | { |
231 | if (_M_owns) |
232 | unlock(); |
233 | } |
234 | |
235 | unique_lock(const unique_lock&) = delete; |
236 | unique_lock& operator=(const unique_lock&) = delete; |
237 | |
238 | unique_lock(unique_lock&& __u) noexcept |
239 | : _M_device(__u._M_device), _M_owns(__u._M_owns) |
240 | { |
241 | __u._M_device = 0; |
242 | __u._M_owns = false; |
243 | } |
244 | |
245 | unique_lock& operator=(unique_lock&& __u) noexcept |
246 | { |
247 | if(_M_owns) |
248 | unlock(); |
249 | |
250 | unique_lock(std::move(__u)).swap(*this); |
251 | |
252 | __u._M_device = 0; |
253 | __u._M_owns = false; |
254 | |
255 | return *this; |
256 | } |
257 | |
258 | void |
259 | lock() |
260 | { |
261 | if (!_M_device) |
262 | __throw_system_error(int(errc::operation_not_permitted)); |
263 | else if (_M_owns) |
264 | __throw_system_error(int(errc::resource_deadlock_would_occur)); |
265 | else |
266 | { |
267 | _M_device->lock(); |
268 | _M_owns = true; |
269 | } |
270 | } |
271 | |
272 | bool |
273 | try_lock() |
274 | { |
275 | if (!_M_device) |
276 | __throw_system_error(int(errc::operation_not_permitted)); |
277 | else if (_M_owns) |
278 | __throw_system_error(int(errc::resource_deadlock_would_occur)); |
279 | else |
280 | { |
281 | _M_owns = _M_device->try_lock(); |
282 | return _M_owns; |
283 | } |
284 | } |
285 | |
286 | template<typename _Clock, typename _Duration> |
287 | bool |
288 | try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) |
289 | { |
290 | if (!_M_device) |
291 | __throw_system_error(int(errc::operation_not_permitted)); |
292 | else if (_M_owns) |
293 | __throw_system_error(int(errc::resource_deadlock_would_occur)); |
294 | else |
295 | { |
296 | _M_owns = _M_device->try_lock_until(__atime); |
297 | return _M_owns; |
298 | } |
299 | } |
300 | |
301 | template<typename _Rep, typename _Period> |
302 | bool |
303 | try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) |
304 | { |
305 | if (!_M_device) |
306 | __throw_system_error(int(errc::operation_not_permitted)); |
307 | else if (_M_owns) |
308 | __throw_system_error(int(errc::resource_deadlock_would_occur)); |
309 | else |
310 | { |
311 | _M_owns = _M_device->try_lock_for(__rtime); |
312 | return _M_owns; |
313 | } |
314 | } |
315 | |
316 | void |
317 | unlock() |
318 | { |
319 | if (!_M_owns) |
320 | __throw_system_error(int(errc::operation_not_permitted)); |
321 | else if (_M_device) |
322 | { |
323 | _M_device->unlock(); |
324 | _M_owns = false; |
325 | } |
326 | } |
327 | |
328 | void |
329 | swap(unique_lock& __u) noexcept |
330 | { |
331 | std::swap(_M_device, __u._M_device); |
332 | std::swap(_M_owns, __u._M_owns); |
333 | } |
334 | |
335 | mutex_type* |
336 | release() noexcept |
337 | { |
338 | mutex_type* __ret = _M_device; |
339 | _M_device = 0; |
340 | _M_owns = false; |
341 | return __ret; |
342 | } |
343 | |
344 | bool |
345 | owns_lock() const noexcept |
346 | { return _M_owns; } |
347 | |
348 | explicit operator bool() const noexcept |
349 | { return owns_lock(); } |
350 | |
351 | mutex_type* |
352 | mutex() const noexcept |
353 | { return _M_device; } |
354 | |
355 | private: |
356 | mutex_type* _M_device; |
357 | bool _M_owns; |
358 | }; |
359 | |
360 | |
361 | template<typename _Mutex> |
362 | inline void |
363 | swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept |
364 | { __x.swap(__y); } |
365 | |
366 | |
367 | _GLIBCXX_END_NAMESPACE_VERSION |
368 | } |
369 | #endif |
370 | |
371 | #endif |
372 | |
373 | #endif |
374 | |