3 // Copyright (C) 2003-2017 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file include/mutex
26 * This is a Standard C++ Library header.
29 #ifndef _GLIBCXX_MUTEX
30 #define _GLIBCXX_MUTEX 1
32 #pragma GCC system_header
34 #if __cplusplus < 201103L
35 # include <bits/c++0x_warning.h>
41 #include <type_traits>
42 #include <system_error>
43 #include <bits/std_mutex.h>
44 #if ! _GTHREAD_USE_MUTEX_TIMEDLOCK
45 # include <condition_variable>
48 #ifndef _GLIBCXX_HAVE_TLS
49 # include <bits/std_function.h>
52 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
54 namespace std _GLIBCXX_VISIBILITY(default)
56 _GLIBCXX_BEGIN_NAMESPACE_VERSION
63 #ifdef _GLIBCXX_HAS_GTHREADS
65 // Common base class for std::recursive_mutex and std::recursive_timed_mutex
66 class __recursive_mutex_base
69 typedef __gthread_recursive_mutex_t __native_type;
71 __recursive_mutex_base(const __recursive_mutex_base&) = delete;
72 __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
74 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
75 __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
77 __recursive_mutex_base() = default;
79 __native_type _M_mutex;
81 __recursive_mutex_base()
83 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
84 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
87 ~__recursive_mutex_base()
88 { __gthread_recursive_mutex_destroy(&_M_mutex); }
92 /// The standard recursive mutex type.
93 class recursive_mutex : private __recursive_mutex_base
96 typedef __native_type* native_handle_type;
98 recursive_mutex() = default;
99 ~recursive_mutex() = default;
101 recursive_mutex(const recursive_mutex&) = delete;
102 recursive_mutex& operator=(const recursive_mutex&) = delete;
107 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
109 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
111 __throw_system_error(__e);
117 // XXX EINVAL, EAGAIN, EBUSY
118 return !__gthread_recursive_mutex_trylock(&_M_mutex);
124 // XXX EINVAL, EAGAIN, EBUSY
125 __gthread_recursive_mutex_unlock(&_M_mutex);
129 native_handle() noexcept
130 { return &_M_mutex; }
133 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
134 template<typename _Derived>
135 class __timed_mutex_impl
138 typedef chrono::high_resolution_clock __clock_t;
140 template<typename _Rep, typename _Period>
142 _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
144 using chrono::steady_clock;
145 auto __rt = chrono::duration_cast<steady_clock::duration>(__rtime);
146 if (ratio_greater<steady_clock::period, _Period>())
148 return _M_try_lock_until(steady_clock::now() + __rt);
151 template<typename _Duration>
153 _M_try_lock_until(const chrono::time_point<__clock_t,
156 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
157 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
159 __gthread_time_t __ts = {
160 static_cast<std::time_t>(__s.time_since_epoch().count()),
161 static_cast<long>(__ns.count())
164 return static_cast<_Derived*>(this)->_M_timedlock(__ts);
167 template<typename _Clock, typename _Duration>
169 _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
171 auto __rtime = __atime - _Clock::now();
172 return _M_try_lock_until(__clock_t::now() + __rtime);
176 /// The standard timed mutex type.
178 : private __mutex_base, public __timed_mutex_impl<timed_mutex>
181 typedef __native_type* native_handle_type;
183 timed_mutex() = default;
184 ~timed_mutex() = default;
186 timed_mutex(const timed_mutex&) = delete;
187 timed_mutex& operator=(const timed_mutex&) = delete;
192 int __e = __gthread_mutex_lock(&_M_mutex);
194 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
196 __throw_system_error(__e);
202 // XXX EINVAL, EAGAIN, EBUSY
203 return !__gthread_mutex_trylock(&_M_mutex);
206 template <class _Rep, class _Period>
208 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
209 { return _M_try_lock_for(__rtime); }
211 template <class _Clock, class _Duration>
213 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
214 { return _M_try_lock_until(__atime); }
219 // XXX EINVAL, EAGAIN, EBUSY
220 __gthread_mutex_unlock(&_M_mutex);
224 native_handle() noexcept
225 { return &_M_mutex; }
228 friend class __timed_mutex_impl<timed_mutex>;
231 _M_timedlock(const __gthread_time_t& __ts)
232 { return !__gthread_mutex_timedlock(&_M_mutex, &__ts); }
235 /// recursive_timed_mutex
236 class recursive_timed_mutex
237 : private __recursive_mutex_base,
238 public __timed_mutex_impl<recursive_timed_mutex>
241 typedef __native_type* native_handle_type;
243 recursive_timed_mutex() = default;
244 ~recursive_timed_mutex() = default;
246 recursive_timed_mutex(const recursive_timed_mutex&) = delete;
247 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
252 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
254 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
256 __throw_system_error(__e);
262 // XXX EINVAL, EAGAIN, EBUSY
263 return !__gthread_recursive_mutex_trylock(&_M_mutex);
266 template <class _Rep, class _Period>
268 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
269 { return _M_try_lock_for(__rtime); }
271 template <class _Clock, class _Duration>
273 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
274 { return _M_try_lock_until(__atime); }
279 // XXX EINVAL, EAGAIN, EBUSY
280 __gthread_recursive_mutex_unlock(&_M_mutex);
284 native_handle() noexcept
285 { return &_M_mutex; }
288 friend class __timed_mutex_impl<recursive_timed_mutex>;
291 _M_timedlock(const __gthread_time_t& __ts)
292 { return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); }
295 #else // !_GTHREAD_USE_MUTEX_TIMEDLOCK
301 condition_variable _M_cv;
302 bool _M_locked = false;
306 timed_mutex() = default;
307 ~timed_mutex() { __glibcxx_assert( !_M_locked ); }
309 timed_mutex(const timed_mutex&) = delete;
310 timed_mutex& operator=(const timed_mutex&) = delete;
315 unique_lock<mutex> __lk(_M_mut);
316 _M_cv.wait(__lk, [&]{ return !_M_locked; });
323 lock_guard<mutex> __lk(_M_mut);
330 template<typename _Rep, typename _Period>
332 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
334 unique_lock<mutex> __lk(_M_mut);
335 if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; }))
341 template<typename _Clock, typename _Duration>
343 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
345 unique_lock<mutex> __lk(_M_mut);
346 if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; }))
355 lock_guard<mutex> __lk(_M_mut);
356 __glibcxx_assert( _M_locked );
362 /// recursive_timed_mutex
363 class recursive_timed_mutex
366 condition_variable _M_cv;
368 unsigned _M_count = 0;
370 // Predicate type that tests whether the current thread can lock a mutex.
373 // Returns true if the mutex is unlocked or is locked by _M_caller.
375 operator()() const noexcept
376 { return _M_mx->_M_count == 0 || _M_mx->_M_owner == _M_caller; }
378 const recursive_timed_mutex* _M_mx;
379 thread::id _M_caller;
384 recursive_timed_mutex() = default;
385 ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); }
387 recursive_timed_mutex(const recursive_timed_mutex&) = delete;
388 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
393 auto __id = this_thread::get_id();
394 _Can_lock __can_lock{this, __id};
395 unique_lock<mutex> __lk(_M_mut);
396 _M_cv.wait(__lk, __can_lock);
398 __throw_system_error(EAGAIN); // [thread.timedmutex.recursive]/3
406 auto __id = this_thread::get_id();
407 _Can_lock __can_lock{this, __id};
408 lock_guard<mutex> __lk(_M_mut);
418 template<typename _Rep, typename _Period>
420 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
422 auto __id = this_thread::get_id();
423 _Can_lock __can_lock{this, __id};
424 unique_lock<mutex> __lk(_M_mut);
425 if (!_M_cv.wait_for(__lk, __rtime, __can_lock))
434 template<typename _Clock, typename _Duration>
436 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
438 auto __id = this_thread::get_id();
439 _Can_lock __can_lock{this, __id};
440 unique_lock<mutex> __lk(_M_mut);
441 if (!_M_cv.wait_until(__lk, __atime, __can_lock))
453 lock_guard<mutex> __lk(_M_mut);
454 __glibcxx_assert( _M_owner == this_thread::get_id() );
455 __glibcxx_assert( _M_count > 0 );
465 #endif // _GLIBCXX_HAS_GTHREADS
467 template<typename _Lock>
468 inline unique_lock<_Lock>
469 __try_to_lock(_Lock& __l)
470 { return unique_lock<_Lock>{__l, try_to_lock}; }
472 template<int _Idx, bool _Continue = true>
473 struct __try_lock_impl
475 template<typename... _Lock>
477 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
480 auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
481 if (__lock.owns_lock())
483 constexpr bool __cont = _Idx + 2 < sizeof...(_Lock);
484 using __try_locker = __try_lock_impl<_Idx + 1, __cont>;
485 __try_locker::__do_try_lock(__locks, __idx);
493 struct __try_lock_impl<_Idx, false>
495 template<typename... _Lock>
497 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
500 auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
501 if (__lock.owns_lock())
509 /** @brief Generic try_lock.
510 * @param __l1 Meets Mutex requirements (try_lock() may throw).
511 * @param __l2 Meets Mutex requirements (try_lock() may throw).
512 * @param __l3 Meets Mutex requirements (try_lock() may throw).
513 * @return Returns -1 if all try_lock() calls return true. Otherwise returns
514 * a 0-based index corresponding to the argument that returned false.
515 * @post Either all arguments are locked, or none will be.
517 * Sequentially calls try_lock() on each argument.
519 template<typename _Lock1, typename _Lock2, typename... _Lock3>
521 try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
524 auto __locks = std::tie(__l1, __l2, __l3...);
525 __try_lock_impl<0>::__do_try_lock(__locks, __idx);
529 /** @brief Generic lock.
530 * @param __l1 Meets Mutex requirements (try_lock() may throw).
531 * @param __l2 Meets Mutex requirements (try_lock() may throw).
532 * @param __l3 Meets Mutex requirements (try_lock() may throw).
533 * @throw An exception thrown by an argument's lock() or try_lock() member.
534 * @post All arguments are locked.
536 * All arguments are locked via a sequence of calls to lock(), try_lock()
537 * and unlock(). If the call exits via an exception any locks that were
538 * obtained will be released.
540 template<typename _L1, typename _L2, typename... _L3>
542 lock(_L1& __l1, _L2& __l2, _L3&... __l3)
546 using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>;
547 unique_lock<_L1> __first(__l1);
549 auto __locks = std::tie(__l2, __l3...);
550 __try_locker::__do_try_lock(__locks, __idx);
559 #if __cplusplus > 201402L
560 #define __cpp_lib_scoped_lock 201703
561 /** @brief A scoped lock type for multiple lockable objects.
563 * A scoped_lock controls mutex ownership within a scope, releasing
564 * ownership in the destructor.
566 template<typename... _MutexTypes>
570 explicit scoped_lock(_MutexTypes&... __m) : _M_devices(std::tie(__m...))
571 { std::lock(__m...); }
573 explicit scoped_lock(_MutexTypes&... __m, adopt_lock_t) noexcept
574 : _M_devices(std::tie(__m...))
575 { } // calling thread owns mutex
579 std::apply([](_MutexTypes&... __m) {
580 char __i[] __attribute__((__unused__)) = { (__m.unlock(), 0)... };
584 scoped_lock(const scoped_lock&) = delete;
585 scoped_lock& operator=(const scoped_lock&) = delete;
588 tuple<_MutexTypes&...> _M_devices;
595 explicit scoped_lock() = default;
596 explicit scoped_lock(adopt_lock_t) noexcept { }
597 ~scoped_lock() = default;
599 scoped_lock(const scoped_lock&) = delete;
600 scoped_lock& operator=(const scoped_lock&) = delete;
603 template<typename _Mutex>
604 class scoped_lock<_Mutex>
607 using mutex_type = _Mutex;
609 explicit scoped_lock(mutex_type& __m) : _M_device(__m)
610 { _M_device.lock(); }
612 explicit scoped_lock(mutex_type& __m, adopt_lock_t) noexcept
614 { } // calling thread owns mutex
617 { _M_device.unlock(); }
619 scoped_lock(const scoped_lock&) = delete;
620 scoped_lock& operator=(const scoped_lock&) = delete;
623 mutex_type& _M_device;
627 #ifdef _GLIBCXX_HAS_GTHREADS
632 typedef __gthread_once_t __native_type;
633 __native_type _M_once = __GTHREAD_ONCE_INIT;
637 constexpr once_flag() noexcept = default;
639 /// Deleted copy constructor
640 once_flag(const once_flag&) = delete;
641 /// Deleted assignment operator
642 once_flag& operator=(const once_flag&) = delete;
644 template<typename _Callable, typename... _Args>
646 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
649 #ifdef _GLIBCXX_HAVE_TLS
650 extern __thread void* __once_callable;
651 extern __thread void (*__once_call)();
653 extern function<void()> __once_functor;
656 __set_once_functor_lock_ptr(unique_lock<mutex>*);
662 extern "C" void __once_proxy(void);
665 template<typename _Callable, typename... _Args>
667 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
669 // _GLIBCXX_RESOLVE_LIB_DEFECTS
670 // 2442. call_once() shouldn't DECAY_COPY()
671 auto __callable = [&] {
672 std::__invoke(std::forward<_Callable>(__f),
673 std::forward<_Args>(__args)...);
675 #ifdef _GLIBCXX_HAVE_TLS
676 __once_callable = std::__addressof(__callable);
677 __once_call = []{ (*(decltype(__callable)*)__once_callable)(); };
679 unique_lock<mutex> __functor_lock(__get_once_mutex());
680 __once_functor = __callable;
681 __set_once_functor_lock_ptr(&__functor_lock);
684 int __e = __gthread_once(&__once._M_once, &__once_proxy);
686 #ifndef _GLIBCXX_HAVE_TLS
688 __set_once_functor_lock_ptr(0);
692 __throw_system_error(__e);
694 #endif // _GLIBCXX_HAS_GTHREADS
697 _GLIBCXX_END_NAMESPACE_VERSION
699 #endif // _GLIBCXX_USE_C99_STDINT_TR1
703 #endif // _GLIBCXX_MUTEX