]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libc++/include/mutex
Merge from vendor branch importing dtc 1.4.3
[FreeBSD/FreeBSD.git] / contrib / libc++ / include / mutex
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... MutexTypes> // Variadic lock_guard only provided in ABI V2.
113 class lock_guard
114 {
115 public:
116     explicit lock_guard(MutexTypes&... m);
117     lock_guard(MutexTypes&... m, adopt_lock_t);
118     ~lock_guard();
119     lock_guard(lock_guard const&) = delete;
120     lock_guard& operator=(lock_guard const&) = delete;
121 private:
122     tuple<MutexTypes&...> pm; // exposition only
123 };
124
125 template <class Mutex>
126 class unique_lock
127 {
128 public:
129     typedef Mutex mutex_type;
130     unique_lock() noexcept;
131     explicit unique_lock(mutex_type& m);
132     unique_lock(mutex_type& m, defer_lock_t) noexcept;
133     unique_lock(mutex_type& m, try_to_lock_t);
134     unique_lock(mutex_type& m, adopt_lock_t);
135     template <class Clock, class Duration>
136         unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
137     template <class Rep, class Period>
138         unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
139     ~unique_lock();
140
141     unique_lock(unique_lock const&) = delete;
142     unique_lock& operator=(unique_lock const&) = delete;
143
144     unique_lock(unique_lock&& u) noexcept;
145     unique_lock& operator=(unique_lock&& u) noexcept;
146
147     void lock();
148     bool try_lock();
149
150     template <class Rep, class Period>
151         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
152     template <class Clock, class Duration>
153         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
154
155     void unlock();
156
157     void swap(unique_lock& u) noexcept;
158     mutex_type* release() noexcept;
159
160     bool owns_lock() const noexcept;
161     explicit operator bool () const noexcept;
162     mutex_type* mutex() const noexcept;
163 };
164
165 template <class Mutex>
166   void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
167
168 template <class L1, class L2, class... L3>
169   int try_lock(L1&, L2&, L3&...);
170 template <class L1, class L2, class... L3>
171   void lock(L1&, L2&, L3&...);
172
173 struct once_flag
174 {
175     constexpr once_flag() noexcept;
176
177     once_flag(const once_flag&) = delete;
178     once_flag& operator=(const once_flag&) = delete;
179 };
180
181 template<class Callable, class ...Args>
182   void call_once(once_flag& flag, Callable&& func, Args&&... args);
183
184 }  // std
185
186 */
187
188 #include <__config>
189 #include <__mutex_base>
190 #include <functional>
191 #include <memory>
192 #ifndef _LIBCPP_HAS_NO_VARIADICS
193 #include <tuple>
194 #endif
195 #include <__threading_support>
196
197 #include <__undef_min_max>
198
199 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
200 #pragma GCC system_header
201 #endif
202
203 _LIBCPP_BEGIN_NAMESPACE_STD
204
205 #ifndef _LIBCPP_HAS_NO_THREADS
206
207 class _LIBCPP_TYPE_VIS recursive_mutex
208 {
209     __libcpp_recursive_mutex_t __m_;
210
211 public:
212      recursive_mutex();
213      ~recursive_mutex();
214
215 private:
216     recursive_mutex(const recursive_mutex&); // = delete;
217     recursive_mutex& operator=(const recursive_mutex&); // = delete;
218
219 public:
220     void lock();
221     bool try_lock() _NOEXCEPT;
222     void unlock()  _NOEXCEPT;
223
224     typedef __libcpp_recursive_mutex_t* native_handle_type;
225
226     _LIBCPP_INLINE_VISIBILITY
227     native_handle_type native_handle() {return &__m_;}
228 };
229
230 class _LIBCPP_TYPE_VIS timed_mutex
231 {
232     mutex              __m_;
233     condition_variable __cv_;
234     bool               __locked_;
235 public:
236      timed_mutex();
237      ~timed_mutex();
238
239 private:
240     timed_mutex(const timed_mutex&); // = delete;
241     timed_mutex& operator=(const timed_mutex&); // = delete;
242
243 public:
244     void lock();
245     bool try_lock() _NOEXCEPT;
246     template <class _Rep, class _Period>
247         _LIBCPP_INLINE_VISIBILITY
248         bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
249             {return try_lock_until(chrono::steady_clock::now() + __d);}
250     template <class _Clock, class _Duration>
251         bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
252     void unlock() _NOEXCEPT;
253 };
254
255 template <class _Clock, class _Duration>
256 bool
257 timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
258 {
259     using namespace chrono;
260     unique_lock<mutex> __lk(__m_);
261     bool no_timeout = _Clock::now() < __t;
262     while (no_timeout && __locked_)
263         no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
264     if (!__locked_)
265     {
266         __locked_ = true;
267         return true;
268     }
269     return false;
270 }
271
272 class _LIBCPP_TYPE_VIS recursive_timed_mutex
273 {
274     mutex              __m_;
275     condition_variable __cv_;
276     size_t             __count_;
277     __libcpp_thread_id __id_;
278 public:
279      recursive_timed_mutex();
280      ~recursive_timed_mutex();
281
282 private:
283     recursive_timed_mutex(const recursive_timed_mutex&); // = delete;
284     recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete;
285
286 public:
287     void lock();
288     bool try_lock() _NOEXCEPT;
289     template <class _Rep, class _Period>
290         _LIBCPP_INLINE_VISIBILITY
291         bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
292             {return try_lock_until(chrono::steady_clock::now() + __d);}
293     template <class _Clock, class _Duration>
294         bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
295     void unlock() _NOEXCEPT;
296 };
297
298 template <class _Clock, class _Duration>
299 bool
300 recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
301 {
302     using namespace chrono;
303     __libcpp_thread_id __id = __libcpp_thread_get_current_id();
304     unique_lock<mutex> lk(__m_);
305     if (__libcpp_thread_id_equal(__id, __id_))
306     {
307         if (__count_ == numeric_limits<size_t>::max())
308             return false;
309         ++__count_;
310         return true;
311     }
312     bool no_timeout = _Clock::now() < __t;
313     while (no_timeout && __count_ != 0)
314         no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout;
315     if (__count_ == 0)
316     {
317         __count_ = 1;
318         __id_ = __id;
319         return true;
320     }
321     return false;
322 }
323
324 template <class _L0, class _L1>
325 int
326 try_lock(_L0& __l0, _L1& __l1)
327 {
328     unique_lock<_L0> __u0(__l0, try_to_lock);
329     if (__u0.owns_lock())
330     {
331         if (__l1.try_lock())
332         {
333             __u0.release();
334             return -1;
335         }
336         else
337             return 1;
338     }
339     return 0;
340 }
341
342 #ifndef _LIBCPP_HAS_NO_VARIADICS
343
344 template <class _L0, class _L1, class _L2, class... _L3>
345 int
346 try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3)
347 {
348     int __r = 0;
349     unique_lock<_L0> __u0(__l0, try_to_lock);
350     if (__u0.owns_lock())
351     {
352         __r = try_lock(__l1, __l2, __l3...);
353         if (__r == -1)
354             __u0.release();
355         else
356             ++__r;
357     }
358     return __r;
359 }
360
361 #endif  // _LIBCPP_HAS_NO_VARIADICS
362
363 template <class _L0, class _L1>
364 void
365 lock(_L0& __l0, _L1& __l1)
366 {
367     while (true)
368     {
369         {
370             unique_lock<_L0> __u0(__l0);
371             if (__l1.try_lock())
372             {
373                 __u0.release();
374                 break;
375             }
376         }
377         __libcpp_thread_yield();
378         {
379             unique_lock<_L1> __u1(__l1);
380             if (__l0.try_lock())
381             {
382                 __u1.release();
383                 break;
384             }
385         }
386         __libcpp_thread_yield();
387     }
388 }
389
390 #ifndef _LIBCPP_HAS_NO_VARIADICS
391
392 template <class _L0, class _L1, class _L2, class ..._L3>
393 void
394 __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
395 {
396     while (true)
397     {
398         switch (__i)
399         {
400         case 0:
401             {
402                 unique_lock<_L0> __u0(__l0);
403                 __i = try_lock(__l1, __l2, __l3...);
404                 if (__i == -1)
405                 {
406                     __u0.release();
407                     return;
408                 }
409             }
410             ++__i;
411             __libcpp_thread_yield();
412             break;
413         case 1:
414             {
415                 unique_lock<_L1> __u1(__l1);
416                 __i = try_lock(__l2, __l3..., __l0);
417                 if (__i == -1)
418                 {
419                     __u1.release();
420                     return;
421                 }
422             }
423             if (__i == sizeof...(_L3) + 1)
424                 __i = 0;
425             else
426                 __i += 2;
427             __libcpp_thread_yield();
428             break;
429         default:
430             __lock_first(__i - 2, __l2, __l3..., __l0, __l1);
431             return;
432         }
433     }
434 }
435
436 template <class _L0, class _L1, class _L2, class ..._L3>
437 inline _LIBCPP_INLINE_VISIBILITY
438 void
439 lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
440 {
441     __lock_first(0, __l0, __l1, __l2, __l3...);
442 }
443
444 template <class _L0>
445 inline _LIBCPP_INLINE_VISIBILITY
446 void __unlock(_L0& __l0) {
447     __l0.unlock();
448 }
449
450 template <class _L0, class _L1>
451 inline _LIBCPP_INLINE_VISIBILITY
452 void __unlock(_L0& __l0, _L1& __l1) {
453     __l0.unlock();
454     __l1.unlock();
455 }
456
457 template <class _L0, class _L1, class _L2, class ..._L3>
458 inline _LIBCPP_INLINE_VISIBILITY
459 void __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
460     __l0.unlock();
461     __l1.unlock();
462     _VSTD::__unlock(__l2, __l3...);
463 }
464
465 #endif  // _LIBCPP_HAS_NO_VARIADICS
466
467 #endif // !_LIBCPP_HAS_NO_THREADS
468
469 struct _LIBCPP_TEMPLATE_VIS once_flag;
470
471 #ifndef _LIBCPP_HAS_NO_VARIADICS
472
473 template<class _Callable, class... _Args>
474 _LIBCPP_INLINE_VISIBILITY
475 void call_once(once_flag&, _Callable&&, _Args&&...);
476
477 #else  // _LIBCPP_HAS_NO_VARIADICS
478
479 template<class _Callable>
480 _LIBCPP_INLINE_VISIBILITY
481 void call_once(once_flag&, _Callable&);
482
483 template<class _Callable>
484 _LIBCPP_INLINE_VISIBILITY
485 void call_once(once_flag&, const _Callable&);
486
487 #endif  // _LIBCPP_HAS_NO_VARIADICS
488
489 struct _LIBCPP_TEMPLATE_VIS once_flag
490 {
491     _LIBCPP_INLINE_VISIBILITY
492     _LIBCPP_CONSTEXPR
493         once_flag() _NOEXCEPT : __state_(0) {}
494
495 private:
496     once_flag(const once_flag&); // = delete;
497     once_flag& operator=(const once_flag&); // = delete;
498
499     unsigned long __state_;
500
501 #ifndef _LIBCPP_HAS_NO_VARIADICS
502     template<class _Callable, class... _Args>
503     friend
504     void call_once(once_flag&, _Callable&&, _Args&&...);
505 #else  // _LIBCPP_HAS_NO_VARIADICS
506     template<class _Callable>
507     friend
508     void call_once(once_flag&, _Callable&);
509
510     template<class _Callable>
511     friend
512     void call_once(once_flag&, const _Callable&);
513 #endif  // _LIBCPP_HAS_NO_VARIADICS
514 };
515
516 #ifndef _LIBCPP_HAS_NO_VARIADICS
517
518 template <class _Fp>
519 class __call_once_param
520 {
521     _Fp& __f_;
522 public:
523     _LIBCPP_INLINE_VISIBILITY
524     explicit __call_once_param(_Fp& __f) : __f_(__f) {}
525
526     _LIBCPP_INLINE_VISIBILITY
527     void operator()()
528     {
529         typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
530         __execute(_Index());
531     }
532
533 private:
534     template <size_t ..._Indices>
535     _LIBCPP_INLINE_VISIBILITY
536     void __execute(__tuple_indices<_Indices...>)
537     {
538         __invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...);
539     }
540 };
541
542 #else
543
544 template <class _Fp>
545 class __call_once_param
546 {
547     _Fp& __f_;
548 public:
549     _LIBCPP_INLINE_VISIBILITY
550     explicit __call_once_param(_Fp& __f) : __f_(__f) {}
551
552     _LIBCPP_INLINE_VISIBILITY
553     void operator()()
554     {
555         __f_();
556     }
557 };
558
559 #endif
560
561 template <class _Fp>
562 void
563 __call_once_proxy(void* __vp)
564 {
565     __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);
566     (*__p)();
567 }
568
569 _LIBCPP_FUNC_VIS void __call_once(volatile unsigned long&, void*, void(*)(void*));
570
571 #ifndef _LIBCPP_HAS_NO_VARIADICS
572
573 template<class _Callable, class... _Args>
574 inline _LIBCPP_INLINE_VISIBILITY
575 void
576 call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args)
577 {
578     if (__libcpp_acquire_load(&__flag.__state_) != ~0ul)
579     {
580         typedef tuple<_Callable&&, _Args&&...> _Gp;
581         _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...);
582         __call_once_param<_Gp> __p(__f);
583         __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
584     }
585 }
586
587 #else  // _LIBCPP_HAS_NO_VARIADICS
588
589 template<class _Callable>
590 inline _LIBCPP_INLINE_VISIBILITY
591 void
592 call_once(once_flag& __flag, _Callable& __func)
593 {
594     if (__libcpp_acquire_load(&__flag.__state_) != ~0ul)
595     {
596         __call_once_param<_Callable> __p(__func);
597         __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>);
598     }
599 }
600
601 template<class _Callable>
602 inline _LIBCPP_INLINE_VISIBILITY
603 void
604 call_once(once_flag& __flag, const _Callable& __func)
605 {
606     if (__flag.__state_ != ~0ul)
607     {
608         __call_once_param<const _Callable> __p(__func);
609         __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>);
610     }
611 }
612
613 #endif  // _LIBCPP_HAS_NO_VARIADICS
614
615
616 #if defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD) \
617     && !defined(_LIBCPP_CXX03_LANG)
618 template <>
619 class _LIBCPP_TEMPLATE_VIS lock_guard<> {
620 public:
621     explicit lock_guard() {}
622     ~lock_guard() = default;
623
624     _LIBCPP_INLINE_VISIBILITY
625     explicit lock_guard(adopt_lock_t) {}
626
627     lock_guard(lock_guard const&) = delete;
628     lock_guard& operator=(lock_guard const&) = delete;
629 };
630
631 template <class ..._MArgs>
632 class _LIBCPP_TEMPLATE_VIS lock_guard
633 {
634     static_assert(sizeof...(_MArgs) >= 2, "At least 2 lock types required");
635     typedef tuple<_MArgs&...> _MutexTuple;
636
637 public:
638     _LIBCPP_INLINE_VISIBILITY
639     explicit lock_guard(_MArgs&... __margs)
640       : __t_(__margs...)
641     {
642         _VSTD::lock(__margs...);
643     }
644
645     _LIBCPP_INLINE_VISIBILITY
646     lock_guard(_MArgs&... __margs, adopt_lock_t)
647         : __t_(__margs...)
648     {
649     }
650
651     _LIBCPP_INLINE_VISIBILITY
652     ~lock_guard() {
653         typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
654         __unlock_unpack(_Indices{}, __t_);
655     }
656
657     lock_guard(lock_guard const&) = delete;
658     lock_guard& operator=(lock_guard const&) = delete;
659
660 private:
661     template <size_t ..._Indx>
662     _LIBCPP_INLINE_VISIBILITY
663     static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) {
664         _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...);
665     }
666
667     _MutexTuple __t_;
668 };
669
670 #endif // _LIBCPP_ABI_VARIADIC_LOCK_GUARD
671
672 _LIBCPP_END_NAMESPACE_STD
673
674 #endif  // _LIBCPP_MUTEX