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