root / lab4 / .minix-src / include / c++ / mutex @ 14
History | View | Annotate | Download (13.8 KB)
1 |
// -*- C++ -*- |
---|---|
2 |
//===--------------------------- mutex ------------------------------------===// |
3 |
// |
4 |
// The LLVM Compiler Infrastructure |
5 |
// |
6 |
// This file is dual licensed under the MIT and the University of Illinois Open |
7 |
// Source Licenses. See LICENSE.TXT for details. |
8 |
// |
9 |
//===----------------------------------------------------------------------===// |
10 |
|
11 |
#ifndef _LIBCPP_MUTEX |
12 |
#define _LIBCPP_MUTEX |
13 |
|
14 |
/* |
15 |
mutex synopsis |
16 |
|
17 |
namespace std |
18 |
{ |
19 |
|
20 |
class mutex |
21 |
{ |
22 |
public: |
23 |
constexpr mutex() noexcept; |
24 |
~mutex(); |
25 |
|
26 |
mutex(const mutex&) = delete; |
27 |
mutex& operator=(const mutex&) = delete; |
28 |
|
29 |
void lock(); |
30 |
bool try_lock(); |
31 |
void unlock(); |
32 |
|
33 |
typedef pthread_mutex_t* native_handle_type; |
34 |
native_handle_type native_handle(); |
35 |
}; |
36 |
|
37 |
class recursive_mutex |
38 |
{ |
39 |
public: |
40 |
recursive_mutex(); |
41 |
~recursive_mutex(); |
42 |
|
43 |
recursive_mutex(const recursive_mutex&) = delete; |
44 |
recursive_mutex& operator=(const recursive_mutex&) = delete; |
45 |
|
46 |
void lock(); |
47 |
bool try_lock() noexcept; |
48 |
void unlock(); |
49 |
|
50 |
typedef pthread_mutex_t* native_handle_type; |
51 |
native_handle_type native_handle(); |
52 |
}; |
53 |
|
54 |
class timed_mutex |
55 |
{ |
56 |
public: |
57 |
timed_mutex(); |
58 |
~timed_mutex(); |
59 |
|
60 |
timed_mutex(const timed_mutex&) = delete; |
61 |
timed_mutex& operator=(const timed_mutex&) = delete; |
62 |
|
63 |
void lock(); |
64 |
bool try_lock(); |
65 |
template <class Rep, class Period> |
66 |
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); |
67 |
template <class Clock, class Duration> |
68 |
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); |
69 |
void unlock(); |
70 |
}; |
71 |
|
72 |
class recursive_timed_mutex |
73 |
{ |
74 |
public: |
75 |
recursive_timed_mutex(); |
76 |
~recursive_timed_mutex(); |
77 |
|
78 |
recursive_timed_mutex(const recursive_timed_mutex&) = delete; |
79 |
recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; |
80 |
|
81 |
void lock(); |
82 |
bool try_lock() noexcept; |
83 |
template <class Rep, class Period> |
84 |
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); |
85 |
template <class Clock, class Duration> |
86 |
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); |
87 |
void unlock(); |
88 |
}; |
89 |
|
90 |
struct defer_lock_t {}; |
91 |
struct try_to_lock_t {}; |
92 |
struct adopt_lock_t {}; |
93 |
|
94 |
constexpr defer_lock_t defer_lock{}; |
95 |
constexpr try_to_lock_t try_to_lock{}; |
96 |
constexpr adopt_lock_t adopt_lock{}; |
97 |
|
98 |
template <class Mutex> |
99 |
class lock_guard |
100 |
{ |
101 |
public: |
102 |
typedef Mutex mutex_type; |
103 |
|
104 |
explicit lock_guard(mutex_type& m); |
105 |
lock_guard(mutex_type& m, adopt_lock_t); |
106 |
~lock_guard(); |
107 |
|
108 |
lock_guard(lock_guard const&) = delete; |
109 |
lock_guard& operator=(lock_guard const&) = delete; |
110 |
}; |
111 |
|
112 |
template <class Mutex> |
113 |
class unique_lock |
114 |
{ |
115 |
public: |
116 |
typedef Mutex mutex_type; |
117 |
unique_lock() noexcept; |
118 |
explicit unique_lock(mutex_type& m); |
119 |
unique_lock(mutex_type& m, defer_lock_t) noexcept; |
120 |
unique_lock(mutex_type& m, try_to_lock_t); |
121 |
unique_lock(mutex_type& m, adopt_lock_t); |
122 |
template <class Clock, class Duration> |
123 |
unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); |
124 |
template <class Rep, class Period> |
125 |
unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); |
126 |
~unique_lock(); |
127 |
|
128 |
unique_lock(unique_lock const&) = delete; |
129 |
unique_lock& operator=(unique_lock const&) = delete; |
130 |
|
131 |
unique_lock(unique_lock&& u) noexcept; |
132 |
unique_lock& operator=(unique_lock&& u) noexcept; |
133 |
|
134 |
void lock(); |
135 |
bool try_lock(); |
136 |
|
137 |
template <class Rep, class Period> |
138 |
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); |
139 |
template <class Clock, class Duration> |
140 |
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); |
141 |
|
142 |
void unlock(); |
143 |
|
144 |
void swap(unique_lock& u) noexcept; |
145 |
mutex_type* release() noexcept; |
146 |
|
147 |
bool owns_lock() const noexcept; |
148 |
explicit operator bool () const noexcept; |
149 |
mutex_type* mutex() const noexcept; |
150 |
}; |
151 |
|
152 |
template <class Mutex> |
153 |
void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept; |
154 |
|
155 |
template <class L1, class L2, class... L3> |
156 |
int try_lock(L1&, L2&, L3&...); |
157 |
template <class L1, class L2, class... L3> |
158 |
void lock(L1&, L2&, L3&...); |
159 |
|
160 |
struct once_flag |
161 |
{ |
162 |
constexpr once_flag() noexcept; |
163 |
|
164 |
once_flag(const once_flag&) = delete; |
165 |
once_flag& operator=(const once_flag&) = delete; |
166 |
}; |
167 |
|
168 |
template<class Callable, class ...Args> |
169 |
void call_once(once_flag& flag, Callable&& func, Args&&... args); |
170 |
|
171 |
} // std |
172 |
|
173 |
*/ |
174 |
|
175 |
#include <__config> |
176 |
#if !defined(_LIBCPP_HAS_NO_THREADS) && defined(__minix) |
177 |
#include <__mutex_base> |
178 |
#endif // !defined(_LIBCPP_HAS_NO_THREADS) && defined(__minix) |
179 |
#include <functional> |
180 |
#include <memory> |
181 |
#ifndef _LIBCPP_HAS_NO_VARIADICS |
182 |
#include <tuple> |
183 |
#endif |
184 |
#include <sched.h> |
185 |
|
186 |
#include <__undef_min_max> |
187 |
|
188 |
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
189 |
#pragma GCC system_header |
190 |
#endif |
191 |
|
192 |
_LIBCPP_BEGIN_NAMESPACE_STD |
193 |
|
194 |
#ifndef _LIBCPP_HAS_NO_THREADS |
195 |
|
196 |
class _LIBCPP_TYPE_VIS recursive_mutex |
197 |
{ |
198 |
pthread_mutex_t __m_; |
199 |
|
200 |
public: |
201 |
recursive_mutex(); |
202 |
~recursive_mutex(); |
203 |
|
204 |
private: |
205 |
recursive_mutex(const recursive_mutex&); // = delete; |
206 |
recursive_mutex& operator=(const recursive_mutex&); // = delete; |
207 |
|
208 |
public: |
209 |
void lock(); |
210 |
bool try_lock() _NOEXCEPT; |
211 |
void unlock() _NOEXCEPT; |
212 |
|
213 |
typedef pthread_mutex_t* native_handle_type; |
214 |
_LIBCPP_INLINE_VISIBILITY |
215 |
native_handle_type native_handle() {return &__m_;} |
216 |
}; |
217 |
|
218 |
class _LIBCPP_TYPE_VIS timed_mutex |
219 |
{ |
220 |
mutex __m_; |
221 |
condition_variable __cv_; |
222 |
bool __locked_; |
223 |
public: |
224 |
timed_mutex(); |
225 |
~timed_mutex(); |
226 |
|
227 |
private: |
228 |
timed_mutex(const timed_mutex&); // = delete; |
229 |
timed_mutex& operator=(const timed_mutex&); // = delete; |
230 |
|
231 |
public: |
232 |
void lock(); |
233 |
bool try_lock() _NOEXCEPT; |
234 |
template <class _Rep, class _Period> |
235 |
_LIBCPP_INLINE_VISIBILITY |
236 |
bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) |
237 |
{return try_lock_until(chrono::steady_clock::now() + __d);} |
238 |
template <class _Clock, class _Duration> |
239 |
bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); |
240 |
void unlock() _NOEXCEPT; |
241 |
}; |
242 |
|
243 |
template <class _Clock, class _Duration> |
244 |
bool |
245 |
timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) |
246 |
{ |
247 |
using namespace chrono; |
248 |
unique_lock<mutex> __lk(__m_); |
249 |
bool no_timeout = _Clock::now() < __t; |
250 |
while (no_timeout && __locked_) |
251 |
no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; |
252 |
if (!__locked_) |
253 |
{ |
254 |
__locked_ = true; |
255 |
return true; |
256 |
} |
257 |
return false; |
258 |
} |
259 |
|
260 |
class _LIBCPP_TYPE_VIS recursive_timed_mutex |
261 |
{ |
262 |
mutex __m_; |
263 |
condition_variable __cv_; |
264 |
size_t __count_; |
265 |
pthread_t __id_; |
266 |
public: |
267 |
recursive_timed_mutex(); |
268 |
~recursive_timed_mutex(); |
269 |
|
270 |
private: |
271 |
recursive_timed_mutex(const recursive_timed_mutex&); // = delete; |
272 |
recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete; |
273 |
|
274 |
public: |
275 |
void lock(); |
276 |
bool try_lock() _NOEXCEPT; |
277 |
template <class _Rep, class _Period> |
278 |
_LIBCPP_INLINE_VISIBILITY |
279 |
bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) |
280 |
{return try_lock_until(chrono::steady_clock::now() + __d);} |
281 |
template <class _Clock, class _Duration> |
282 |
bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); |
283 |
void unlock() _NOEXCEPT; |
284 |
}; |
285 |
|
286 |
template <class _Clock, class _Duration> |
287 |
bool |
288 |
recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) |
289 |
{ |
290 |
using namespace chrono; |
291 |
pthread_t __id = pthread_self(); |
292 |
unique_lock<mutex> lk(__m_); |
293 |
if (pthread_equal(__id, __id_)) |
294 |
{ |
295 |
if (__count_ == numeric_limits<size_t>::max()) |
296 |
return false; |
297 |
++__count_; |
298 |
return true; |
299 |
} |
300 |
bool no_timeout = _Clock::now() < __t; |
301 |
while (no_timeout && __count_ != 0) |
302 |
no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout; |
303 |
if (__count_ == 0) |
304 |
{ |
305 |
__count_ = 1; |
306 |
__id_ = __id; |
307 |
return true; |
308 |
} |
309 |
return false; |
310 |
} |
311 |
|
312 |
template <class _L0, class _L1> |
313 |
int |
314 |
try_lock(_L0& __l0, _L1& __l1) |
315 |
{ |
316 |
unique_lock<_L0> __u0(__l0, try_to_lock); |
317 |
if (__u0.owns_lock()) |
318 |
{ |
319 |
if (__l1.try_lock()) |
320 |
{ |
321 |
__u0.release(); |
322 |
return -1; |
323 |
} |
324 |
else |
325 |
return 1; |
326 |
} |
327 |
return 0; |
328 |
} |
329 |
|
330 |
#ifndef _LIBCPP_HAS_NO_VARIADICS |
331 |
|
332 |
template <class _L0, class _L1, class _L2, class... _L3> |
333 |
int |
334 |
try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) |
335 |
{ |
336 |
int __r = 0; |
337 |
unique_lock<_L0> __u0(__l0, try_to_lock); |
338 |
if (__u0.owns_lock()) |
339 |
{ |
340 |
__r = try_lock(__l1, __l2, __l3...); |
341 |
if (__r == -1) |
342 |
__u0.release(); |
343 |
else |
344 |
++__r; |
345 |
} |
346 |
return __r; |
347 |
} |
348 |
|
349 |
#endif // _LIBCPP_HAS_NO_VARIADICS |
350 |
|
351 |
template <class _L0, class _L1> |
352 |
void |
353 |
lock(_L0& __l0, _L1& __l1) |
354 |
{ |
355 |
while (true) |
356 |
{ |
357 |
{ |
358 |
unique_lock<_L0> __u0(__l0); |
359 |
if (__l1.try_lock()) |
360 |
{ |
361 |
__u0.release(); |
362 |
break; |
363 |
} |
364 |
} |
365 |
sched_yield(); |
366 |
{ |
367 |
unique_lock<_L1> __u1(__l1); |
368 |
if (__l0.try_lock()) |
369 |
{ |
370 |
__u1.release(); |
371 |
break; |
372 |
} |
373 |
} |
374 |
sched_yield(); |
375 |
} |
376 |
} |
377 |
|
378 |
#ifndef _LIBCPP_HAS_NO_VARIADICS |
379 |
|
380 |
template <class _L0, class _L1, class _L2, class ..._L3> |
381 |
void |
382 |
__lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) |
383 |
{ |
384 |
while (true) |
385 |
{ |
386 |
switch (__i) |
387 |
{ |
388 |
case 0: |
389 |
{ |
390 |
unique_lock<_L0> __u0(__l0); |
391 |
__i = try_lock(__l1, __l2, __l3...); |
392 |
if (__i == -1) |
393 |
{ |
394 |
__u0.release(); |
395 |
return; |
396 |
} |
397 |
} |
398 |
++__i; |
399 |
sched_yield(); |
400 |
break; |
401 |
case 1: |
402 |
{ |
403 |
unique_lock<_L1> __u1(__l1); |
404 |
__i = try_lock(__l2, __l3..., __l0); |
405 |
if (__i == -1) |
406 |
{ |
407 |
__u1.release(); |
408 |
return; |
409 |
} |
410 |
} |
411 |
if (__i == sizeof...(_L3) + 1) |
412 |
__i = 0; |
413 |
else |
414 |
__i += 2; |
415 |
sched_yield(); |
416 |
break; |
417 |
default: |
418 |
__lock_first(__i - 2, __l2, __l3..., __l0, __l1); |
419 |
return; |
420 |
} |
421 |
} |
422 |
} |
423 |
|
424 |
template <class _L0, class _L1, class _L2, class ..._L3> |
425 |
inline _LIBCPP_INLINE_VISIBILITY |
426 |
void |
427 |
lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) |
428 |
{ |
429 |
__lock_first(0, __l0, __l1, __l2, __l3...); |
430 |
} |
431 |
|
432 |
#endif // _LIBCPP_HAS_NO_VARIADICS |
433 |
|
434 |
#endif // !_LIBCPP_HAS_NO_THREADS |
435 |
|
436 |
struct _LIBCPP_TYPE_VIS_ONLY once_flag; |
437 |
|
438 |
#ifndef _LIBCPP_HAS_NO_VARIADICS |
439 |
|
440 |
template<class _Callable, class... _Args> |
441 |
_LIBCPP_INLINE_VISIBILITY |
442 |
void call_once(once_flag&, _Callable&&, _Args&&...); |
443 |
|
444 |
#else // _LIBCPP_HAS_NO_VARIADICS |
445 |
|
446 |
template<class _Callable> |
447 |
_LIBCPP_INLINE_VISIBILITY |
448 |
void call_once(once_flag&, _Callable&); |
449 |
|
450 |
template<class _Callable> |
451 |
_LIBCPP_INLINE_VISIBILITY |
452 |
void call_once(once_flag&, const _Callable&); |
453 |
|
454 |
#endif // _LIBCPP_HAS_NO_VARIADICS |
455 |
|
456 |
struct _LIBCPP_TYPE_VIS_ONLY once_flag |
457 |
{ |
458 |
_LIBCPP_INLINE_VISIBILITY |
459 |
_LIBCPP_CONSTEXPR |
460 |
once_flag() _NOEXCEPT : __state_(0) {} |
461 |
|
462 |
private: |
463 |
once_flag(const once_flag&); // = delete; |
464 |
once_flag& operator=(const once_flag&); // = delete; |
465 |
|
466 |
unsigned long __state_; |
467 |
|
468 |
#ifndef _LIBCPP_HAS_NO_VARIADICS |
469 |
template<class _Callable, class... _Args> |
470 |
friend |
471 |
void call_once(once_flag&, _Callable&&, _Args&&...); |
472 |
#else // _LIBCPP_HAS_NO_VARIADICS |
473 |
template<class _Callable> |
474 |
friend |
475 |
void call_once(once_flag&, _Callable&); |
476 |
|
477 |
template<class _Callable> |
478 |
friend |
479 |
void call_once(once_flag&, const _Callable&); |
480 |
#endif // _LIBCPP_HAS_NO_VARIADICS |
481 |
}; |
482 |
|
483 |
#ifndef _LIBCPP_HAS_NO_VARIADICS |
484 |
|
485 |
template <class _Fp> |
486 |
class __call_once_param |
487 |
{ |
488 |
_Fp& __f_; |
489 |
public: |
490 |
_LIBCPP_INLINE_VISIBILITY |
491 |
explicit __call_once_param(_Fp& __f) : __f_(__f) {} |
492 |
|
493 |
_LIBCPP_INLINE_VISIBILITY |
494 |
void operator()() |
495 |
{ |
496 |
typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index; |
497 |
__execute(_Index()); |
498 |
} |
499 |
|
500 |
private: |
501 |
template <size_t ..._Indices> |
502 |
_LIBCPP_INLINE_VISIBILITY |
503 |
void __execute(__tuple_indices<_Indices...>) |
504 |
{ |
505 |
__invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...); |
506 |
} |
507 |
}; |
508 |
|
509 |
#else |
510 |
|
511 |
template <class _Fp> |
512 |
class __call_once_param |
513 |
{ |
514 |
_Fp& __f_; |
515 |
public: |
516 |
_LIBCPP_INLINE_VISIBILITY |
517 |
explicit __call_once_param(_Fp& __f) : __f_(__f) {} |
518 |
|
519 |
_LIBCPP_INLINE_VISIBILITY |
520 |
void operator()() |
521 |
{ |
522 |
__f_(); |
523 |
} |
524 |
}; |
525 |
|
526 |
#endif |
527 |
|
528 |
template <class _Fp> |
529 |
void |
530 |
__call_once_proxy(void* __vp) |
531 |
{ |
532 |
__call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp); |
533 |
(*__p)(); |
534 |
} |
535 |
|
536 |
_LIBCPP_FUNC_VIS void __call_once(volatile unsigned long&, void*, void(*)(void*)); |
537 |
|
538 |
#ifndef _LIBCPP_HAS_NO_VARIADICS |
539 |
|
540 |
template<class _Callable, class... _Args> |
541 |
inline _LIBCPP_INLINE_VISIBILITY |
542 |
void |
543 |
call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) |
544 |
{ |
545 |
if (__libcpp_relaxed_load(&__flag.__state_) != ~0ul) |
546 |
{ |
547 |
typedef tuple<_Callable&&, _Args&&...> _Gp; |
548 |
_Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...); |
549 |
__call_once_param<_Gp> __p(__f); |
550 |
__call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>); |
551 |
} |
552 |
} |
553 |
|
554 |
#else // _LIBCPP_HAS_NO_VARIADICS |
555 |
|
556 |
template<class _Callable> |
557 |
inline _LIBCPP_INLINE_VISIBILITY |
558 |
void |
559 |
call_once(once_flag& __flag, _Callable& __func) |
560 |
{ |
561 |
if (__libcpp_relaxed_load(&__flag.__state_) != ~0ul) |
562 |
{ |
563 |
__call_once_param<_Callable> __p(__func); |
564 |
__call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>); |
565 |
} |
566 |
} |
567 |
|
568 |
template<class _Callable> |
569 |
inline _LIBCPP_INLINE_VISIBILITY |
570 |
void |
571 |
call_once(once_flag& __flag, const _Callable& __func) |
572 |
{ |
573 |
if (__flag.__state_ != ~0ul) |
574 |
{ |
575 |
__call_once_param<const _Callable> __p(__func); |
576 |
__call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>); |
577 |
} |
578 |
} |
579 |
|
580 |
#endif // _LIBCPP_HAS_NO_VARIADICS |
581 |
|
582 |
_LIBCPP_END_NAMESPACE_STD |
583 |
|
584 |
#endif // _LIBCPP_MUTEX |