root / lab4 / .minix-src / include / c++ / mutex @ 13
History | View | Annotate | Download (13.8 KB)
1 | 13 | up20180614 | // -*- 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 |