30#define _GLIBCXX_MUTEX 1
32#pragma GCC system_header
34#if __cplusplus < 201103L
45#if ! _GTHREAD_USE_MUTEX_TIMEDLOCK
51#if defined _GLIBCXX_HAS_GTHREADS && ! defined _GLIBCXX_HAVE_TLS
55namespace std _GLIBCXX_VISIBILITY(default)
57_GLIBCXX_BEGIN_NAMESPACE_VERSION
64#ifdef _GLIBCXX_HAS_GTHREADS
68 class __recursive_mutex_base
71 typedef __gthread_recursive_mutex_t __native_type;
73 __recursive_mutex_base(
const __recursive_mutex_base&) =
delete;
74 __recursive_mutex_base& operator=(
const __recursive_mutex_base&) =
delete;
76#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
77 __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
79 __recursive_mutex_base() =
default;
81 __native_type _M_mutex;
83 __recursive_mutex_base()
86 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
89 ~__recursive_mutex_base()
90 { __gthread_recursive_mutex_destroy(&_M_mutex); }
107 typedef __native_type* native_handle_type;
118 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
122 __throw_system_error(__e);
129 return !__gthread_recursive_mutex_trylock(&_M_mutex);
136 __gthread_recursive_mutex_unlock(&_M_mutex);
140 native_handle()
noexcept
141 {
return &_M_mutex; }
144#if _GTHREAD_USE_MUTEX_TIMEDLOCK
147 template<
typename _Derived>
148 class __timed_mutex_impl
151 template<
typename _Rep,
typename _Period>
155#if _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
161 auto __rt = chrono::duration_cast<__clock::duration>(__rtime);
164 return _M_try_lock_until(__clock::now() + __rt);
167 template<
typename _Duration>
169 _M_try_lock_until(
const chrono::time_point<chrono::system_clock,
172 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
173 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
175 __gthread_time_t __ts = {
176 static_cast<std::time_t
>(__s.time_since_epoch().count()),
177 static_cast<long>(__ns.count())
180 return static_cast<_Derived*
>(
this)->_M_timedlock(__ts);
183#ifdef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
184 template<
typename _Duration>
186 _M_try_lock_until(
const chrono::time_point<chrono::steady_clock,
189 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
190 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
192 __gthread_time_t __ts = {
193 static_cast<std::time_t
>(__s.time_since_epoch().count()),
194 static_cast<long>(__ns.count())
197 return static_cast<_Derived*
>(
this)->_M_clocklock(CLOCK_MONOTONIC,
202 template<
typename _Clock,
typename _Duration>
204 _M_try_lock_until(
const chrono::time_point<_Clock, _Duration>& __atime)
206#if __cplusplus > 201703L
207 static_assert(chrono::is_clock_v<_Clock>);
212 auto __now = _Clock::now();
214 auto __rtime = __atime - __now;
215 if (_M_try_lock_for(__rtime))
217 __now = _Clock::now();
218 }
while (__atime > __now);
233 :
private __mutex_base,
public __timed_mutex_impl<timed_mutex>
236 typedef __native_type* native_handle_type;
247 int __e = __gthread_mutex_lock(&_M_mutex);
251 __throw_system_error(__e);
258 return !__gthread_mutex_trylock(&_M_mutex);
261 template <
class _Rep,
class _Period>
264 {
return _M_try_lock_for(__rtime); }
266 template <
class _Clock,
class _Duration>
269 {
return _M_try_lock_until(__atime); }
275 __gthread_mutex_unlock(&_M_mutex);
279 native_handle()
noexcept
280 {
return &_M_mutex; }
286 _M_timedlock(
const __gthread_time_t& __ts)
287 {
return !__gthread_mutex_timedlock(&_M_mutex, &__ts); }
289#if _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
291 _M_clocklock(clockid_t clockid,
const __gthread_time_t& __ts)
292 {
return !pthread_mutex_clocklock(&_M_mutex, clockid, &__ts); }
307 :
private __recursive_mutex_base,
308 public __timed_mutex_impl<recursive_timed_mutex>
311 typedef __native_type* native_handle_type;
322 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
326 __throw_system_error(__e);
333 return !__gthread_recursive_mutex_trylock(&_M_mutex);
336 template <
class _Rep,
class _Period>
339 {
return _M_try_lock_for(__rtime); }
341 template <
class _Clock,
class _Duration>
344 {
return _M_try_lock_until(__atime); }
350 __gthread_recursive_mutex_unlock(&_M_mutex);
354 native_handle()
noexcept
355 {
return &_M_mutex; }
361 _M_timedlock(
const __gthread_time_t& __ts)
362 {
return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); }
364#ifdef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
366 _M_clocklock(clockid_t clockid,
const __gthread_time_t& __ts)
367 {
return !pthread_mutex_clocklock(&_M_mutex, clockid, &__ts); }
378 bool _M_locked =
false;
385 timed_mutex(
const timed_mutex&) =
delete;
386 timed_mutex& operator=(
const timed_mutex&) =
delete;
391 unique_lock<mutex> __lk(_M_mut);
392 _M_cv.wait(__lk, [&]{
return !_M_locked; });
399 lock_guard<mutex> __lk(_M_mut);
406 template<
typename _Rep,
typename _Period>
408 try_lock_for(
const chrono::duration<_Rep, _Period>& __rtime)
410 unique_lock<mutex> __lk(_M_mut);
411 if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; }))
417 template<
typename _Clock,
typename _Duration>
419 try_lock_until(
const chrono::time_point<_Clock, _Duration>& __atime)
421 unique_lock<mutex> __lk(_M_mut);
422 if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; }))
431 lock_guard<mutex> __lk(_M_mut);
432 __glibcxx_assert( _M_locked );
439 class recursive_timed_mutex
442 condition_variable _M_cv;
444 unsigned _M_count = 0;
451 operator()() const noexcept
452 {
return _M_mx->_M_count == 0 || _M_mx->_M_owner == _M_caller; }
454 const recursive_timed_mutex* _M_mx;
455 thread::id _M_caller;
460 recursive_timed_mutex() =
default;
461 ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); }
463 recursive_timed_mutex(
const recursive_timed_mutex&) =
delete;
464 recursive_timed_mutex& operator=(
const recursive_timed_mutex&) =
delete;
470 _Can_lock __can_lock{
this, __id};
471 unique_lock<mutex> __lk(_M_mut);
472 _M_cv.wait(__lk, __can_lock);
474 __throw_system_error(EAGAIN);
483 _Can_lock __can_lock{
this, __id};
484 lock_guard<mutex> __lk(_M_mut);
494 template<
typename _Rep,
typename _Period>
496 try_lock_for(
const chrono::duration<_Rep, _Period>& __rtime)
499 _Can_lock __can_lock{
this, __id};
500 unique_lock<mutex> __lk(_M_mut);
501 if (!_M_cv.wait_for(__lk, __rtime, __can_lock))
510 template<
typename _Clock,
typename _Duration>
512 try_lock_until(
const chrono::time_point<_Clock, _Duration>& __atime)
515 _Can_lock __can_lock{
this, __id};
516 unique_lock<mutex> __lk(_M_mut);
517 if (!_M_cv.wait_until(__lk, __atime, __can_lock))
529 lock_guard<mutex> __lk(_M_mut);
531 __glibcxx_assert( _M_count > 0 );
547 template<
typename _Lockable>
549 __try_lock_impl(_Lockable& __l)
551 if (unique_lock<_Lockable> __lock{__l,
try_to_lock})
562 template<
typename _L0,
typename... _Lockables>
564 __try_lock_impl(_L0& __l0, _Lockables&... __lockables)
566#if __cplusplus >= 201703L
567 if constexpr ((is_same_v<_L0, _Lockables> && ...))
569 constexpr int _Np = 1 +
sizeof...(_Lockables);
570 unique_lock<_L0> __locks[_Np] = {
573 for (
int __i = 0; __i < _Np; ++__i)
577 const int __failed = __i;
579 __locks[__i].unlock();
583 for (
auto& __l : __locks)
591 int __idx = __detail::__try_lock_impl(__lockables...);
616 template<
typename _L1,
typename _L2,
typename... _L3>
620 return __detail::__try_lock_impl(__l1, __l2, __l3...);
631 template<
typename _L0,
typename... _L1>
633 __lock_impl(
int& __i,
int __depth, _L0& __l0, _L1&... __l1)
635 while (__i >= __depth)
641 unique_lock<_L0> __first(__l0);
642 __failed += __detail::__try_lock_impl(__l1...);
650#if defined _GLIBCXX_HAS_GTHREADS && defined _GLIBCXX_USE_SCHED_YIELD
653 constexpr auto __n = 1 +
sizeof...(_L1);
654 __i = (__depth + __failed) % __n;
657 __detail::__lock_impl(__i, __depth + 1, __l1..., __l0);
675 template<
typename _L1,
typename _L2,
typename... _L3>
677 lock(_L1& __l1, _L2& __l2, _L3&... __l3)
679#if __cplusplus >= 201703L
680 if constexpr (is_same_v<_L1, _L2> && (is_same_v<_L1, _L3> && ...))
682 constexpr int _Np = 2 +
sizeof...(_L3);
688 __locks[__first].lock();
689 for (
int __j = 1; __j < _Np; ++__j)
691 const int __idx = (__first + __j) % _Np;
694 for (
int __k = __j; __k != 0; --__k)
695 __locks[(__first + __k - 1) % _Np].unlock();
700 }
while (!__locks[__first].owns_lock());
702 for (
auto& __l : __locks)
709 __detail::__lock_impl(__i, 0, __l1, __l2, __l3...);
713#if __cplusplus >= 201703L
714#define __cpp_lib_scoped_lock 201703L
723 template<
typename... _MutexTypes>
735 { std::apply([](
auto&... __m) { (__m.unlock(), ...); }, _M_devices); }
741 tuple<_MutexTypes&...> _M_devices;
750 ~scoped_lock() =
default;
752 scoped_lock(
const scoped_lock&) =
delete;
753 scoped_lock& operator=(
const scoped_lock&) =
delete;
756 template<
typename _Mutex>
757 class scoped_lock<_Mutex>
760 using mutex_type = _Mutex;
762 explicit scoped_lock(mutex_type& __m) : _M_device(__m)
763 { _M_device.lock(); }
765 explicit scoped_lock(adopt_lock_t, mutex_type& __m) noexcept
770 { _M_device.unlock(); }
772 scoped_lock(
const scoped_lock&) =
delete;
773 scoped_lock& operator=(
const scoped_lock&) =
delete;
776 mutex_type& _M_device;
780#ifdef _GLIBCXX_HAS_GTHREADS
784 constexpr once_flag()
noexcept =
default;
794 __gthread_once_t _M_once = __GTHREAD_ONCE_INIT;
796 struct _Prepare_execution;
798 template<
typename _Callable,
typename... _Args>
804# ifdef _GLIBCXX_HAVE_TLS
807 extern __thread
void* __once_callable;
808 extern __thread void (*__once_call)();
811 struct once_flag::_Prepare_execution
813 template<
typename _Callable>
815 _Prepare_execution(_Callable& __c)
820 __once_call = [] { (*
static_cast<_Callable*
>(__once_callable))(); };
823 ~_Prepare_execution()
826 __once_callable =
nullptr;
827 __once_call =
nullptr;
830 _Prepare_execution(
const _Prepare_execution&) =
delete;
831 _Prepare_execution& operator=(
const _Prepare_execution&) =
delete;
837 extern function<void()> __once_functor;
840 __set_once_functor_lock_ptr(unique_lock<mutex>*);
846 struct once_flag::_Prepare_execution
848 template<
typename _Callable>
850 _Prepare_execution(_Callable& __c)
853 __once_functor = __c;
854 __set_once_functor_lock_ptr(&_M_functor_lock);
857 ~_Prepare_execution()
860 __set_once_functor_lock_ptr(
nullptr);
865 unique_lock<mutex> _M_functor_lock{__get_once_mutex()};
867 _Prepare_execution(
const _Prepare_execution&) =
delete;
868 _Prepare_execution& operator=(
const _Prepare_execution&) =
delete;
875 extern "C" void __once_proxy(
void);
878 template<
typename _Callable,
typename... _Args>
883 auto __callable = [&] {
885 std::forward<_Args>(__args)...);
888 once_flag::_Prepare_execution __exec(__callable);
891 if (
int __e = __gthread_once(&__once._M_once, &__once_proxy))
892 __throw_system_error(__e);
900 constexpr once_flag() noexcept = default;
914 enum _Bits :
int { _Init = 0, _Active = 1, _Done = 2 };
916 int _M_once = _Bits::_Init;
920 _M_passive() const noexcept;
928 void _M_finish(
bool __returning) noexcept;
931 struct _Active_execution
933 explicit _Active_execution(once_flag& __flag) : _M_flag(__flag) { }
935 ~_Active_execution() { _M_flag._M_finish(_M_returning); }
937 _Active_execution(
const _Active_execution&) =
delete;
938 _Active_execution&
operator=(
const _Active_execution&) =
delete;
941 bool _M_returning =
false;
944 template<
typename _Callable,
typename... _Args>
946 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
952 once_flag::_M_passive() const noexcept
953 {
return _M_once == _Bits::_Done; }
956 once_flag::_M_activate()
958 if (_M_once == _Bits::_Init) [[__likely__]]
960 _M_once = _Bits::_Active;
963 else if (_M_passive())
966 __throw_system_error(EDEADLK);
970 once_flag::_M_finish(
bool __returning)
noexcept
971 { _M_once = __returning ? _Bits::_Done : _Bits::_Init; }
974 template<
typename _Callable,
typename... _Args>
976 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
978 if (__once._M_passive())
980 else if (__once._M_activate())
982 once_flag::_Active_execution __exec(__once);
987 std::forward<_Args>(__args)...);
990 __exec._M_returning =
true;
996_GLIBCXX_END_NAMESPACE_VERSION
constexpr __invoke_result< _Callable, _Args... >::type __invoke(_Callable &&__fn, _Args &&... __args) noexcept(__is_nothrow_invocable< _Callable, _Args... >::value)
Invoke a callable object.
constexpr tuple< _Elements &... > tie(_Elements &... __args) noexcept
Return a tuple of lvalue references bound to the arguments.
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
void lock(_L1 &__l1, _L2 &__l2, _L3 &... __l3)
Generic lock.
constexpr try_to_lock_t try_to_lock
Tag used to prevent a scoped lock from blocking if a mutex is locked.
int try_lock(_L1 &__l1, _L2 &__l2, _L3 &... __l3)
Generic try_lock.
constexpr defer_lock_t defer_lock
Tag used to prevent a scoped lock from acquiring ownership of a mutex.
void call_once(once_flag &__once, _Callable &&__f, _Args &&... __args)
Invoke a callable and synchronize with other calls using the same flag.
ISO C++ entities toplevel namespace is std.
thread::id get_id() noexcept
The unique identifier of the current thread.
A scoped lock type for multiple lockable objects.
Flag type used by std::call_once.
friend void call_once(once_flag &__once, _Callable &&__f, _Args &&... __args)
Invoke a callable and synchronize with other calls using the same flag.
once_flag(const once_flag &)=delete
Deleted copy constructor.
once_flag & operator=(const once_flag &)=delete
Deleted assignment operator.
Primary class template, tuple.
chrono::duration represents a distance between two points in time
chrono::time_point represents a point in time as measured by a clock
Assume the calling thread has already obtained mutex ownership and manage it.
A movable scoped lock type.