29 #ifndef _GLIBCXX_MUTEX
30 #define _GLIBCXX_MUTEX 1
32 #pragma GCC system_header
34 #if __cplusplus < 201103L
45 #include <bits/gthr.h>
48 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
50 namespace std _GLIBCXX_VISIBILITY(default)
52 _GLIBCXX_BEGIN_NAMESPACE_VERSION
54 #ifdef _GLIBCXX_HAS_GTHREADS
59 typedef __gthread_mutex_t __native_type;
61 #ifdef __GTHREAD_MUTEX_INIT
62 __native_type _M_mutex = __GTHREAD_MUTEX_INIT;
64 constexpr __mutex_base() noexcept = default;
66 __native_type _M_mutex;
68 __mutex_base() noexcept
71 __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
74 ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); }
77 __mutex_base(
const __mutex_base&) =
delete;
78 __mutex_base& operator=(
const __mutex_base&) =
delete;
82 class __recursive_mutex_base
85 typedef __gthread_recursive_mutex_t __native_type;
87 __recursive_mutex_base(
const __recursive_mutex_base&) =
delete;
88 __recursive_mutex_base& operator=(
const __recursive_mutex_base&) =
delete;
90 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
91 __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
93 __recursive_mutex_base() =
default;
95 __native_type _M_mutex;
97 __recursive_mutex_base()
100 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
103 ~__recursive_mutex_base()
104 { __gthread_recursive_mutex_destroy(&_M_mutex); }
120 typedef __native_type* native_handle_type;
122 #ifdef __GTHREAD_MUTEX_INIT
125 mutex() noexcept =
default;
134 int __e = __gthread_mutex_lock(&_M_mutex);
138 __throw_system_error(__e);
145 return !__gthread_mutex_trylock(&_M_mutex);
152 __gthread_mutex_unlock(&_M_mutex);
157 {
return &_M_mutex; }
164 typedef __native_type* native_handle_type;
175 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
179 __throw_system_error(__e);
186 return !__gthread_recursive_mutex_trylock(&_M_mutex);
193 __gthread_recursive_mutex_unlock(&_M_mutex);
198 {
return &_M_mutex; }
201 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
202 template<
typename _Derived>
203 class __timed_mutex_impl
206 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
207 typedef chrono::steady_clock __clock_t;
209 typedef chrono::high_resolution_clock __clock_t;
212 template<
typename _Rep,
typename _Period>
217 if (ratio_greater<__clock_t::period, _Period>())
220 return _M_try_lock_until(__clock_t::now() + __rt);
223 template<
typename _Duration>
225 _M_try_lock_until(
const chrono::time_point<__clock_t,
228 chrono::time_point<__clock_t, chrono::seconds> __s =
234 __gthread_time_t __ts = {
235 static_cast<std::time_t
>(__s.time_since_epoch().count()),
236 static_cast<long>(__ns.count())
239 auto __mutex =
static_cast<_Derived*
>(
this)->native_handle();
240 return !__gthread_mutex_timedlock(__mutex, &__ts);
243 template<
typename _Clock,
typename _Duration>
245 _M_try_lock_until(
const chrono::time_point<_Clock, _Duration>& __atime)
246 {
return _M_try_lock_for(__atime - _Clock::now()); }
251 :
private __mutex_base,
public __timed_mutex_impl<timed_mutex>
254 typedef __native_type* native_handle_type;
256 timed_mutex() =
default;
257 ~timed_mutex() =
default;
259 timed_mutex(
const timed_mutex&) =
delete;
260 timed_mutex& operator=(
const timed_mutex&) =
delete;
265 int __e = __gthread_mutex_lock(&_M_mutex);
269 __throw_system_error(__e);
276 return !__gthread_mutex_trylock(&_M_mutex);
279 template <
class _Rep,
class _Period>
281 try_lock_for(
const chrono::duration<_Rep, _Period>& __rtime)
282 {
return _M_try_lock_for(__rtime); }
284 template <
class _Clock,
class _Duration>
286 try_lock_until(
const chrono::time_point<_Clock, _Duration>& __atime)
287 {
return _M_try_lock_until(__atime); }
293 __gthread_mutex_unlock(&_M_mutex);
298 {
return &_M_mutex; }
302 class recursive_timed_mutex
303 :
private __recursive_mutex_base,
304 public __timed_mutex_impl<recursive_timed_mutex>
307 typedef __native_type* native_handle_type;
309 recursive_timed_mutex() =
default;
310 ~recursive_timed_mutex() =
default;
312 recursive_timed_mutex(
const recursive_timed_mutex&) =
delete;
313 recursive_timed_mutex& operator=(
const recursive_timed_mutex&) =
delete;
318 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
322 __throw_system_error(__e);
329 return !__gthread_recursive_mutex_trylock(&_M_mutex);
332 template <
class _Rep,
class _Period>
334 try_lock_for(
const chrono::duration<_Rep, _Period>& __rtime)
335 {
return _M_try_lock_for(__rtime); }
337 template <
class _Clock,
class _Duration>
339 try_lock_until(
const chrono::time_point<_Clock, _Duration>& __atime)
340 {
return _M_try_lock_until(__atime); }
346 __gthread_recursive_mutex_unlock(&_M_mutex);
351 {
return &_M_mutex; }
354 #endif // _GLIBCXX_HAS_GTHREADS
367 constexpr try_to_lock_t try_to_lock { };
368 constexpr adopt_lock_t adopt_lock { };
373 template<
typename _Mutex>
377 typedef _Mutex mutex_type;
379 explicit lock_guard(mutex_type& __m) : _M_device(__m)
380 { _M_device.lock(); }
386 { _M_device.unlock(); }
392 mutex_type& _M_device;
396 template<
typename _Mutex>
400 typedef _Mutex mutex_type;
403 : _M_device(0), _M_owns(
false)
407 : _M_device(&__m), _M_owns(
false)
414 : _M_device(&__m), _M_owns(
false)
418 : _M_device(&__m), _M_owns(_M_device->try_lock())
422 : _M_device(&__m), _M_owns(
true)
427 template<
typename _Clock,
typename _Duration>
430 : _M_device(&__m), _M_owns(_M_device->try_lock_until(__atime))
433 template<
typename _Rep,
typename _Period>
436 : _M_device(&__m), _M_owns(_M_device->try_lock_for(__rtime))
449 : _M_device(__u._M_device), _M_owns(__u._M_owns)
472 __throw_system_error(
int(errc::operation_not_permitted));
474 __throw_system_error(
int(errc::resource_deadlock_would_occur));
486 __throw_system_error(
int(errc::operation_not_permitted));
488 __throw_system_error(
int(errc::resource_deadlock_would_occur));
491 _M_owns = _M_device->try_lock();
496 template<
typename _Clock,
typename _Duration>
501 __throw_system_error(
int(errc::operation_not_permitted));
503 __throw_system_error(
int(errc::resource_deadlock_would_occur));
506 _M_owns = _M_device->try_lock_until(__atime);
511 template<
typename _Rep,
typename _Period>
516 __throw_system_error(
int(errc::operation_not_permitted));
518 __throw_system_error(
int(errc::resource_deadlock_would_occur));
521 _M_owns = _M_device->try_lock_for(__rtime);
530 __throw_system_error(
int(errc::operation_not_permitted));
541 std::swap(_M_device, __u._M_device);
542 std::swap(_M_owns, __u._M_owns);
548 mutex_type* __ret = _M_device;
555 owns_lock()
const noexcept
558 explicit operator bool()
const noexcept
559 {
return owns_lock(); }
562 mutex()
const noexcept
563 {
return _M_device; }
566 mutex_type* _M_device;
571 template<
typename _Mutex>
579 template<
typename... _Lock>
581 __do_unlock(tuple<_Lock&...>& __locks)
583 std::get<_Idx>(__locks).unlock();
584 __unlock_impl<_Idx - 1>::__do_unlock(__locks);
589 struct __unlock_impl<-1>
591 template<
typename... _Lock>
593 __do_unlock(tuple<_Lock&...>&)
597 template<
typename _Lock>
599 __try_to_lock(_Lock& __l)
600 {
return unique_lock<_Lock>(__l, try_to_lock); }
602 template<
int _Idx,
bool _Continue = true>
603 struct __try_lock_impl
605 template<
typename... _Lock>
607 __do_try_lock(tuple<_Lock&...>& __locks,
int& __idx)
610 auto __lock = __try_to_lock(std::get<_Idx>(__locks));
611 if (__lock.owns_lock())
613 __try_lock_impl<_Idx + 1, _Idx + 2 <
sizeof...(_Lock)>::
614 __do_try_lock(__locks, __idx);
622 struct __try_lock_impl<_Idx, false>
624 template<
typename... _Lock>
626 __do_try_lock(tuple<_Lock&...>& __locks,
int& __idx)
629 auto __lock = __try_to_lock(std::get<_Idx>(__locks));
630 if (__lock.owns_lock())
648 template<
typename _Lock1,
typename _Lock2,
typename... _Lock3>
650 try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
653 auto __locks =
std::tie(__l1, __l2, __l3...);
655 { __try_lock_impl<0>::__do_try_lock(__locks, __idx); }
672 template<
typename _L1,
typename _L2,
typename ..._L3>
674 lock(_L1& __l1, _L2& __l2, _L3&... __l3)
680 auto __locks =
std::tie(__l2, __l3...);
681 __try_lock_impl<0,
sizeof...(_L3)>::__do_try_lock(__locks, __idx);
690 #ifdef _GLIBCXX_HAS_GTHREADS
695 typedef __gthread_once_t __native_type;
696 __native_type _M_once = __GTHREAD_ONCE_INIT;
700 constexpr
once_flag() noexcept =
default;
707 template<
typename _Callable,
typename... _Args>
712 #ifdef _GLIBCXX_HAVE_TLS
713 extern __thread
void* __once_callable;
714 extern __thread void (*__once_call)();
716 template<
typename _Callable>
720 (*(_Callable*)__once_callable)();
723 extern function<void()> __once_functor;
726 __set_once_functor_lock_ptr(unique_lock<mutex>*);
732 extern "C" void __once_proxy(
void);
735 template<
typename _Callable,
typename... _Args>
739 #ifdef _GLIBCXX_HAVE_TLS
740 auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f),
741 std::forward<_Args>(__args)...);
742 __once_callable = &__bound_functor;
743 __once_call = &__once_call_impl<decltype(__bound_functor)>;
746 auto __callable = std::__bind_simple(std::forward<_Callable>(__f),
747 std::forward<_Args>(__args)...);
748 __once_functor = [&]() { __callable(); };
749 __set_once_functor_lock_ptr(&__functor_lock);
752 int __e = __gthread_once(&__once._M_once, &__once_proxy);
754 #ifndef _GLIBCXX_HAVE_TLS
756 __set_once_functor_lock_ptr(0);
760 __throw_system_error(__e);
762 #endif // _GLIBCXX_HAS_GTHREADS
765 _GLIBCXX_END_NAMESPACE_VERSION
767 #endif // _GLIBCXX_USE_C99_STDINT_TR1
771 #endif // _GLIBCXX_MUTEX