29 #ifndef _GLIBCXX_MUTEX
30 #define _GLIBCXX_MUTEX 1
32 #pragma GCC system_header
34 #if __cplusplus < 201103L
45 #include <bits/gthr.h>
48 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
50 namespace std _GLIBCXX_VISIBILITY(default)
52 _GLIBCXX_BEGIN_NAMESPACE_VERSION
58 typedef __gthread_mutex_t __native_type;
60 #ifdef __GTHREAD_MUTEX_INIT
61 __native_type _M_mutex = __GTHREAD_MUTEX_INIT;
63 constexpr __mutex_base() noexcept = default;
65 __native_type _M_mutex;
67 __mutex_base() noexcept
70 __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
73 ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); }
76 __mutex_base(
const __mutex_base&) =
delete;
77 __mutex_base& operator=(
const __mutex_base&) =
delete;
81 class __recursive_mutex_base
84 typedef __gthread_recursive_mutex_t __native_type;
86 __recursive_mutex_base(
const __recursive_mutex_base&) =
delete;
87 __recursive_mutex_base& operator=(
const __recursive_mutex_base&) =
delete;
89 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
90 __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
92 __recursive_mutex_base() =
default;
94 __native_type _M_mutex;
96 __recursive_mutex_base()
99 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
102 ~__recursive_mutex_base()
103 { __gthread_recursive_mutex_destroy(&_M_mutex); }
119 typedef __native_type* native_handle_type;
121 #ifdef __GTHREAD_MUTEX_INIT
124 mutex() noexcept =
default;
133 int __e = __gthread_mutex_lock(&_M_mutex);
137 __throw_system_error(__e);
144 return !__gthread_mutex_trylock(&_M_mutex);
151 __gthread_mutex_unlock(&_M_mutex);
156 {
return &_M_mutex; }
163 typedef __native_type* native_handle_type;
174 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
178 __throw_system_error(__e);
185 return !__gthread_recursive_mutex_trylock(&_M_mutex);
192 __gthread_recursive_mutex_unlock(&_M_mutex);
197 {
return &_M_mutex; }
200 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
202 class timed_mutex :
private __mutex_base
204 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
211 typedef __native_type* native_handle_type;
213 timed_mutex() =
default;
214 ~timed_mutex() =
default;
216 timed_mutex(
const timed_mutex&) =
delete;
217 timed_mutex& operator=(
const timed_mutex&) =
delete;
222 int __e = __gthread_mutex_lock(&_M_mutex);
226 __throw_system_error(__e);
233 return !__gthread_mutex_trylock(&_M_mutex);
236 template <
class _Rep,
class _Period>
238 try_lock_for(
const chrono::duration<_Rep, _Period>& __rtime)
239 {
return __try_lock_for_impl(__rtime); }
241 template <
class _Clock,
class _Duration>
243 try_lock_until(
const chrono::time_point<_Clock, _Duration>& __atime)
245 chrono::time_point<_Clock, chrono::seconds> __s =
251 __gthread_time_t __ts = {
252 static_cast<std::time_t
>(__s.time_since_epoch().count()),
253 static_cast<long>(__ns.count())
256 return !__gthread_mutex_timedlock(&_M_mutex, &__ts);
263 __gthread_mutex_unlock(&_M_mutex);
268 {
return &_M_mutex; }
271 template<
typename _Rep,
typename _Period>
273 ratio_less_equal<__clock_t::period, _Period>::value,
bool>::type
274 __try_lock_for_impl(
const chrono::duration<_Rep, _Period>& __rtime)
276 __clock_t::time_point __atime = __clock_t::now()
279 return try_lock_until(__atime);
282 template <
typename _Rep,
typename _Period>
284 !ratio_less_equal<__clock_t::period, _Period>::value,
bool>::type
285 __try_lock_for_impl(
const chrono::duration<_Rep, _Period>& __rtime)
287 __clock_t::time_point __atime = __clock_t::now()
290 return try_lock_until(__atime);
295 class recursive_timed_mutex :
private __recursive_mutex_base
297 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
298 typedef chrono::steady_clock __clock_t;
300 typedef chrono::high_resolution_clock __clock_t;
304 typedef __native_type* native_handle_type;
306 recursive_timed_mutex() =
default;
307 ~recursive_timed_mutex() =
default;
309 recursive_timed_mutex(
const recursive_timed_mutex&) =
delete;
310 recursive_timed_mutex& operator=(
const recursive_timed_mutex&) =
delete;
315 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
319 __throw_system_error(__e);
326 return !__gthread_recursive_mutex_trylock(&_M_mutex);
329 template <
class _Rep,
class _Period>
331 try_lock_for(
const chrono::duration<_Rep, _Period>& __rtime)
332 {
return __try_lock_for_impl(__rtime); }
334 template <
class _Clock,
class _Duration>
336 try_lock_until(
const chrono::time_point<_Clock, _Duration>& __atime)
338 chrono::time_point<_Clock, chrono::seconds> __s =
344 __gthread_time_t __ts = {
345 static_cast<std::time_t
>(__s.time_since_epoch().count()),
346 static_cast<long>(__ns.count())
349 return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts);
356 __gthread_recursive_mutex_unlock(&_M_mutex);
361 {
return &_M_mutex; }
364 template<
typename _Rep,
typename _Period>
366 ratio_less_equal<__clock_t::period, _Period>::value,
bool>::type
367 __try_lock_for_impl(
const chrono::duration<_Rep, _Period>& __rtime)
369 __clock_t::time_point __atime = __clock_t::now()
372 return try_lock_until(__atime);
375 template <
typename _Rep,
typename _Period>
377 !ratio_less_equal<__clock_t::period, _Period>::value,
bool>::type
378 __try_lock_for_impl(
const chrono::duration<_Rep, _Period>& __rtime)
380 __clock_t::time_point __atime = __clock_t::now()
383 return try_lock_until(__atime);
399 constexpr try_to_lock_t try_to_lock { };
400 constexpr adopt_lock_t adopt_lock { };
405 template<
typename _Mutex>
409 typedef _Mutex mutex_type;
411 explicit lock_guard(mutex_type& __m) : _M_device(__m)
412 { _M_device.lock(); }
418 { _M_device.unlock(); }
424 mutex_type& _M_device;
428 template<
typename _Mutex>
432 typedef _Mutex mutex_type;
435 : _M_device(0), _M_owns(
false)
439 : _M_device(&__m), _M_owns(
false)
446 : _M_device(&__m), _M_owns(
false)
450 : _M_device(&__m), _M_owns(_M_device->try_lock())
454 : _M_device(&__m), _M_owns(
true)
459 template<
typename _Clock,
typename _Duration>
462 : _M_device(&__m), _M_owns(_M_device->try_lock_until(__atime))
465 template<
typename _Rep,
typename _Period>
468 : _M_device(&__m), _M_owns(_M_device->try_lock_for(__rtime))
481 : _M_device(__u._M_device), _M_owns(__u._M_owns)
504 __throw_system_error(
int(errc::operation_not_permitted));
506 __throw_system_error(
int(errc::resource_deadlock_would_occur));
518 __throw_system_error(
int(errc::operation_not_permitted));
520 __throw_system_error(
int(errc::resource_deadlock_would_occur));
523 _M_owns = _M_device->try_lock();
528 template<
typename _Clock,
typename _Duration>
533 __throw_system_error(
int(errc::operation_not_permitted));
535 __throw_system_error(
int(errc::resource_deadlock_would_occur));
538 _M_owns = _M_device->try_lock_until(__atime);
543 template<
typename _Rep,
typename _Period>
548 __throw_system_error(
int(errc::operation_not_permitted));
550 __throw_system_error(
int(errc::resource_deadlock_would_occur));
553 _M_owns = _M_device->try_lock_for(__rtime);
562 __throw_system_error(
int(errc::operation_not_permitted));
573 std::swap(_M_device, __u._M_device);
574 std::swap(_M_owns, __u._M_owns);
580 mutex_type* __ret = _M_device;
587 owns_lock()
const noexcept
590 explicit operator bool()
const noexcept
591 {
return owns_lock(); }
594 mutex()
const noexcept
595 {
return _M_device; }
598 mutex_type* _M_device;
603 template<
typename _Mutex>
611 template<
typename... _Lock>
613 __do_unlock(tuple<_Lock&...>& __locks)
615 std::get<_Idx>(__locks).unlock();
616 __unlock_impl<_Idx - 1>::__do_unlock(__locks);
621 struct __unlock_impl<-1>
623 template<
typename... _Lock>
625 __do_unlock(tuple<_Lock&...>&)
629 template<
typename _Lock>
631 __try_to_lock(_Lock& __l)
632 {
return unique_lock<_Lock>(__l, try_to_lock); }
634 template<
int _Idx,
bool _Continue = true>
635 struct __try_lock_impl
637 template<
typename... _Lock>
639 __do_try_lock(tuple<_Lock&...>& __locks,
int& __idx)
642 auto __lock = __try_to_lock(std::get<_Idx>(__locks));
643 if (__lock.owns_lock())
645 __try_lock_impl<_Idx + 1, _Idx + 2 <
sizeof...(_Lock)>::
646 __do_try_lock(__locks, __idx);
654 struct __try_lock_impl<_Idx, false>
656 template<
typename... _Lock>
658 __do_try_lock(tuple<_Lock&...>& __locks,
int& __idx)
661 auto __lock = __try_to_lock(std::get<_Idx>(__locks));
662 if (__lock.owns_lock())
680 template<
typename _Lock1,
typename _Lock2,
typename... _Lock3>
682 try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
685 auto __locks =
std::tie(__l1, __l2, __l3...);
687 { __try_lock_impl<0>::__do_try_lock(__locks, __idx); }
704 template<
typename _L1,
typename _L2,
typename ..._L3>
706 lock(_L1& __l1, _L2& __l2, _L3&... __l3)
712 auto __locks =
std::tie(__l2, __l3...);
713 __try_lock_impl<0,
sizeof...(_L3)>::__do_try_lock(__locks, __idx);
726 typedef __gthread_once_t __native_type;
727 __native_type _M_once = __GTHREAD_ONCE_INIT;
731 constexpr
once_flag() noexcept =
default;
738 template<
typename _Callable,
typename... _Args>
743 #ifdef _GLIBCXX_HAVE_TLS
744 extern __thread
void* __once_callable;
745 extern __thread void (*__once_call)();
747 template<
typename _Callable>
751 (*(_Callable*)__once_callable)();
754 extern function<void()> __once_functor;
757 __set_once_functor_lock_ptr(unique_lock<mutex>*);
763 extern "C" void __once_proxy(
void);
766 template<
typename _Callable,
typename... _Args>
770 #ifdef _GLIBCXX_HAVE_TLS
771 auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f),
772 std::forward<_Args>(__args)...);
773 __once_callable = &__bound_functor;
774 __once_call = &__once_call_impl<decltype(__bound_functor)>;
777 auto __callable = std::__bind_simple(std::forward<_Callable>(__f),
778 std::forward<_Args>(__args)...);
779 __once_functor = [&]() { __callable(); };
780 __set_once_functor_lock_ptr(&__functor_lock);
783 int __e = __gthread_once(&(__once._M_once), &__once_proxy);
785 #ifndef _GLIBCXX_HAVE_TLS
787 __set_once_functor_lock_ptr(0);
791 __throw_system_error(__e);
795 _GLIBCXX_END_NAMESPACE_VERSION
798 #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
802 #endif // _GLIBCXX_MUTEX