3 // Copyright (C) 2003-2016 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>
43 #include <system_error>
44 #include <bits/std_mutex.h>
45 #if ! _GTHREAD_USE_MUTEX_TIMEDLOCK
46 # include <condition_variable>
50 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
52 namespace std _GLIBCXX_VISIBILITY(default)
54 _GLIBCXX_BEGIN_NAMESPACE_VERSION
61 #ifdef _GLIBCXX_HAS_GTHREADS
63 // Common base class for std::recursive_mutex and std::recursive_timed_mutex
64 class __recursive_mutex_base
67 typedef __gthread_recursive_mutex_t __native_type;
69 __recursive_mutex_base(const __recursive_mutex_base&) = delete;
70 __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
72 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
73 __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
75 __recursive_mutex_base() = default;
77 __native_type _M_mutex;
79 __recursive_mutex_base()
81 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
82 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
85 ~__recursive_mutex_base()
86 { __gthread_recursive_mutex_destroy(&_M_mutex); }
90 /// The standard recursive mutex type.
91 class recursive_mutex : private __recursive_mutex_base
94 typedef __native_type* native_handle_type;
96 recursive_mutex() = default;
97 ~recursive_mutex() = default;
99 recursive_mutex(const recursive_mutex&) = delete;
100 recursive_mutex& operator=(const recursive_mutex&) = delete;
105 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
107 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
109 __throw_system_error(__e);
115 // XXX EINVAL, EAGAIN, EBUSY
116 return !__gthread_recursive_mutex_trylock(&_M_mutex);
122 // XXX EINVAL, EAGAIN, EBUSY
123 __gthread_recursive_mutex_unlock(&_M_mutex);
128 { return &_M_mutex; }
131 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
132 template<typename _Derived>
133 class __timed_mutex_impl
136 typedef chrono::high_resolution_clock __clock_t;
138 template<typename _Rep, typename _Period>
140 _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
142 using chrono::steady_clock;
143 auto __rt = chrono::duration_cast<steady_clock::duration>(__rtime);
144 if (ratio_greater<steady_clock::period, _Period>())
146 return _M_try_lock_until(steady_clock::now() + __rt);
149 template<typename _Duration>
151 _M_try_lock_until(const chrono::time_point<__clock_t,
154 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
155 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
157 __gthread_time_t __ts = {
158 static_cast<std::time_t>(__s.time_since_epoch().count()),
159 static_cast<long>(__ns.count())
162 return static_cast<_Derived*>(this)->_M_timedlock(__ts);
165 template<typename _Clock, typename _Duration>
167 _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
169 auto __rtime = __atime - _Clock::now();
170 return _M_try_lock_until(__clock_t::now() + __rtime);
174 /// The standard timed mutex type.
176 : private __mutex_base, public __timed_mutex_impl<timed_mutex>
179 typedef __native_type* native_handle_type;
181 timed_mutex() = default;
182 ~timed_mutex() = default;
184 timed_mutex(const timed_mutex&) = delete;
185 timed_mutex& operator=(const timed_mutex&) = delete;
190 int __e = __gthread_mutex_lock(&_M_mutex);
192 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
194 __throw_system_error(__e);
200 // XXX EINVAL, EAGAIN, EBUSY
201 return !__gthread_mutex_trylock(&_M_mutex);
204 template <class _Rep, class _Period>
206 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
207 { return _M_try_lock_for(__rtime); }
209 template <class _Clock, class _Duration>
211 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
212 { return _M_try_lock_until(__atime); }
217 // XXX EINVAL, EAGAIN, EBUSY
218 __gthread_mutex_unlock(&_M_mutex);
223 { return &_M_mutex; }
226 friend class __timed_mutex_impl<timed_mutex>;
229 _M_timedlock(const __gthread_time_t& __ts)
230 { return !__gthread_mutex_timedlock(&_M_mutex, &__ts); }
233 /// recursive_timed_mutex
234 class recursive_timed_mutex
235 : private __recursive_mutex_base,
236 public __timed_mutex_impl<recursive_timed_mutex>
239 typedef __native_type* native_handle_type;
241 recursive_timed_mutex() = default;
242 ~recursive_timed_mutex() = default;
244 recursive_timed_mutex(const recursive_timed_mutex&) = delete;
245 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
250 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
252 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
254 __throw_system_error(__e);
260 // XXX EINVAL, EAGAIN, EBUSY
261 return !__gthread_recursive_mutex_trylock(&_M_mutex);
264 template <class _Rep, class _Period>
266 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
267 { return _M_try_lock_for(__rtime); }
269 template <class _Clock, class _Duration>
271 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
272 { return _M_try_lock_until(__atime); }
277 // XXX EINVAL, EAGAIN, EBUSY
278 __gthread_recursive_mutex_unlock(&_M_mutex);
283 { return &_M_mutex; }
286 friend class __timed_mutex_impl<recursive_timed_mutex>;
289 _M_timedlock(const __gthread_time_t& __ts)
290 { return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); }
293 #else // !_GTHREAD_USE_MUTEX_TIMEDLOCK
299 condition_variable _M_cv;
300 bool _M_locked = false;
304 timed_mutex() = default;
305 ~timed_mutex() { __glibcxx_assert( !_M_locked ); }
307 timed_mutex(const timed_mutex&) = delete;
308 timed_mutex& operator=(const timed_mutex&) = delete;
313 unique_lock<mutex> __lk(_M_mut);
314 _M_cv.wait(__lk, [&]{ return !_M_locked; });
321 lock_guard<mutex> __lk(_M_mut);
328 template<typename _Rep, typename _Period>
330 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
332 unique_lock<mutex> __lk(_M_mut);
333 if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; }))
339 template<typename _Clock, typename _Duration>
341 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
343 unique_lock<mutex> __lk(_M_mut);
344 if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; }))
353 lock_guard<mutex> __lk(_M_mut);
354 __glibcxx_assert( _M_locked );
360 /// recursive_timed_mutex
361 class recursive_timed_mutex
364 condition_variable _M_cv;
366 unsigned _M_count = 0;
368 // Predicate type that tests whether the current thread can lock a mutex.
371 // Returns true if the mutex is unlocked or is locked by _M_caller.
373 operator()() const noexcept
374 { return _M_mx->_M_count == 0 || _M_mx->_M_owner == _M_caller; }
376 const recursive_timed_mutex* _M_mx;
377 thread::id _M_caller;
382 recursive_timed_mutex() = default;
383 ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); }
385 recursive_timed_mutex(const recursive_timed_mutex&) = delete;
386 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
391 auto __id = this_thread::get_id();
392 _Can_lock __can_lock{this, __id};
393 unique_lock<mutex> __lk(_M_mut);
394 _M_cv.wait(__lk, __can_lock);
396 __throw_system_error(EAGAIN); // [thread.timedmutex.recursive]/3
404 auto __id = this_thread::get_id();
405 _Can_lock __can_lock{this, __id};
406 lock_guard<mutex> __lk(_M_mut);
416 template<typename _Rep, typename _Period>
418 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
420 auto __id = this_thread::get_id();
421 _Can_lock __can_lock{this, __id};
422 unique_lock<mutex> __lk(_M_mut);
423 if (!_M_cv.wait_for(__lk, __rtime, __can_lock))
432 template<typename _Clock, typename _Duration>
434 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
436 auto __id = this_thread::get_id();
437 _Can_lock __can_lock{this, __id};
438 unique_lock<mutex> __lk(_M_mut);
439 if (!_M_cv.wait_until(__lk, __atime, __can_lock))
451 lock_guard<mutex> __lk(_M_mut);
452 __glibcxx_assert( _M_owner == this_thread::get_id() );
453 __glibcxx_assert( _M_count > 0 );
463 #endif // _GLIBCXX_HAS_GTHREADS
465 template<typename _Lock>
466 inline unique_lock<_Lock>
467 __try_to_lock(_Lock& __l)
468 { return unique_lock<_Lock>{__l, try_to_lock}; }
470 template<int _Idx, bool _Continue = true>
471 struct __try_lock_impl
473 template<typename... _Lock>
475 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
478 auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
479 if (__lock.owns_lock())
481 constexpr bool __cont = _Idx + 2 < sizeof...(_Lock);
482 using __try_locker = __try_lock_impl<_Idx + 1, __cont>;
483 __try_locker::__do_try_lock(__locks, __idx);
491 struct __try_lock_impl<_Idx, false>
493 template<typename... _Lock>
495 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
498 auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
499 if (__lock.owns_lock())
507 /** @brief Generic try_lock.
508 * @param __l1 Meets Mutex requirements (try_lock() may throw).
509 * @param __l2 Meets Mutex requirements (try_lock() may throw).
510 * @param __l3 Meets Mutex requirements (try_lock() may throw).
511 * @return Returns -1 if all try_lock() calls return true. Otherwise returns
512 * a 0-based index corresponding to the argument that returned false.
513 * @post Either all arguments are locked, or none will be.
515 * Sequentially calls try_lock() on each argument.
517 template<typename _Lock1, typename _Lock2, typename... _Lock3>
519 try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
522 auto __locks = std::tie(__l1, __l2, __l3...);
523 __try_lock_impl<0>::__do_try_lock(__locks, __idx);
527 /** @brief Generic lock.
528 * @param __l1 Meets Mutex requirements (try_lock() may throw).
529 * @param __l2 Meets Mutex requirements (try_lock() may throw).
530 * @param __l3 Meets Mutex requirements (try_lock() may throw).
531 * @throw An exception thrown by an argument's lock() or try_lock() member.
532 * @post All arguments are locked.
534 * All arguments are locked via a sequence of calls to lock(), try_lock()
535 * and unlock(). If the call exits via an exception any locks that were
536 * obtained will be released.
538 template<typename _L1, typename _L2, typename... _L3>
540 lock(_L1& __l1, _L2& __l2, _L3&... __l3)
544 using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>;
545 unique_lock<_L1> __first(__l1);
547 auto __locks = std::tie(__l2, __l3...);
548 __try_locker::__do_try_lock(__locks, __idx);
557 #ifdef _GLIBCXX_HAS_GTHREADS
562 typedef __gthread_once_t __native_type;
563 __native_type _M_once = __GTHREAD_ONCE_INIT;
567 constexpr once_flag() noexcept = default;
569 /// Deleted copy constructor
570 once_flag(const once_flag&) = delete;
571 /// Deleted assignment operator
572 once_flag& operator=(const once_flag&) = delete;
574 template<typename _Callable, typename... _Args>
576 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
579 #ifdef _GLIBCXX_HAVE_TLS
580 extern __thread void* __once_callable;
581 extern __thread void (*__once_call)();
583 extern function<void()> __once_functor;
586 __set_once_functor_lock_ptr(unique_lock<mutex>*);
592 extern "C" void __once_proxy(void);
595 template<typename _Callable, typename... _Args>
597 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
599 // _GLIBCXX_RESOLVE_LIB_DEFECTS
600 // 2442. call_once() shouldn't DECAY_COPY()
601 auto __callable = [&] {
602 std::__invoke(std::forward<_Callable>(__f),
603 std::forward<_Args>(__args)...);
605 #ifdef _GLIBCXX_HAVE_TLS
606 __once_callable = std::__addressof(__callable);
607 __once_call = []{ (*(decltype(__callable)*)__once_callable)(); };
609 unique_lock<mutex> __functor_lock(__get_once_mutex());
610 __once_functor = __callable;
611 __set_once_functor_lock_ptr(&__functor_lock);
614 int __e = __gthread_once(&__once._M_once, &__once_proxy);
616 #ifndef _GLIBCXX_HAVE_TLS
618 __set_once_functor_lock_ptr(0);
622 __throw_system_error(__e);
624 #endif // _GLIBCXX_HAS_GTHREADS
627 _GLIBCXX_END_NAMESPACE_VERSION
629 #endif // _GLIBCXX_USE_C99_STDINT_TR1
633 #endif // _GLIBCXX_MUTEX