1// <mutex> -*- C++ -*-
2
3// Copyright (C) 2003-2015 Free Software Foundation, Inc.
4//
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)
9// any later version.
10
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.
15
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.
19
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/>.
24
25/** @file include/mutex
26 * This is a Standard C++ Library header.
27 */
28
29#ifndef _GLIBCXX_MUTEX
30#define _GLIBCXX_MUTEX 1
31
32#pragma GCC system_header
33
34#if __cplusplus < 201103L
35# include <bits/c++0x_warning.h>
36#else
37
38#include <tuple>
39#include <chrono>
40#include <exception>
41#include <type_traits>
42#include <functional>
43#include <system_error>
44#include <bits/functexcept.h>
45#include <bits/gthr.h>
46#include <bits/move.h> // for std::swap
47#include <bits/cxxabi_forced.h>
48
49#ifdef _GLIBCXX_USE_C99_STDINT_TR1
50
51namespace std _GLIBCXX_VISIBILITY(default)
52{
53_GLIBCXX_BEGIN_NAMESPACE_VERSION
54
55#ifdef _GLIBCXX_HAS_GTHREADS
56 // Common base class for std::mutex and std::timed_mutex
57 class __mutex_base
58 {
59 protected:
60 typedef __gthread_mutex_t __native_type;
61
62#ifdef __GTHREAD_MUTEX_INIT
63 __native_type _M_mutex = __GTHREAD_MUTEX_INIT;
64
65 constexpr __mutex_base() noexcept = default;
66#else
67 __native_type _M_mutex;
68
69 __mutex_base() noexcept
70 {
71 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
72 __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
73 }
74
75 ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); }
76#endif
77
78 __mutex_base(const __mutex_base&) = delete;
79 __mutex_base& operator=(const __mutex_base&) = delete;
80 };
81
82 // Common base class for std::recursive_mutex and std::recursive_timed_mutex
83 class __recursive_mutex_base
84 {
85 protected:
86 typedef __gthread_recursive_mutex_t __native_type;
87
88 __recursive_mutex_base(const __recursive_mutex_base&) = delete;
89 __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
90
91#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
92 __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
93
94 __recursive_mutex_base() = default;
95#else
96 __native_type _M_mutex;
97
98 __recursive_mutex_base()
99 {
100 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
101 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
102 }
103
104 ~__recursive_mutex_base()
105 { __gthread_recursive_mutex_destroy(&_M_mutex); }
106#endif
107 };
108
109 /**
110 * @defgroup mutexes Mutexes
111 * @ingroup concurrency
112 *
113 * Classes for mutex support.
114 * @{
115 */
116
117 /// The standard mutex type.
118 class mutex : private __mutex_base
119 {
120 public:
121 typedef __native_type* native_handle_type;
122
123#ifdef __GTHREAD_MUTEX_INIT
124 constexpr
125#endif
126 mutex() noexcept = default;
127 ~mutex() = default;
128
129 mutex(const mutex&) = delete;
130 mutex& operator=(const mutex&) = delete;
131
132 void
133 lock()
134 {
135 int __e = __gthread_mutex_lock(&_M_mutex);
136
137 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
138 if (__e)
139 __throw_system_error(__e);
140 }
141
142 bool
143 try_lock() noexcept
144 {
145 // XXX EINVAL, EAGAIN, EBUSY
146 return !__gthread_mutex_trylock(&_M_mutex);
147 }
148
149 void
150 unlock()
151 {
152 // XXX EINVAL, EAGAIN, EPERM
153 __gthread_mutex_unlock(&_M_mutex);
154 }
155
156 native_handle_type
157 native_handle()
158 { return &_M_mutex; }
159 };
160
161 /// The standard recursive mutex type.
162 class recursive_mutex : private __recursive_mutex_base
163 {
164 public:
165 typedef __native_type* native_handle_type;
166
167 recursive_mutex() = default;
168 ~recursive_mutex() = default;
169
170 recursive_mutex(const recursive_mutex&) = delete;
171 recursive_mutex& operator=(const recursive_mutex&) = delete;
172
173 void
174 lock()
175 {
176 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
177
178 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
179 if (__e)
180 __throw_system_error(__e);
181 }
182
183 bool
184 try_lock() noexcept
185 {
186 // XXX EINVAL, EAGAIN, EBUSY
187 return !__gthread_recursive_mutex_trylock(&_M_mutex);
188 }
189
190 void
191 unlock()
192 {
193 // XXX EINVAL, EAGAIN, EBUSY
194 __gthread_recursive_mutex_unlock(&_M_mutex);
195 }
196
197 native_handle_type
198 native_handle()
199 { return &_M_mutex; }
200 };
201
202#if _GTHREAD_USE_MUTEX_TIMEDLOCK
203 template<typename _Derived>
204 class __timed_mutex_impl
205 {
206 protected:
207 typedef chrono::high_resolution_clock __clock_t;
208
209 template<typename _Rep, typename _Period>
210 bool
211 _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
212 {
213 using chrono::steady_clock;
214 auto __rt = chrono::duration_cast<steady_clock::duration>(__rtime);
215 if (ratio_greater<steady_clock::period, _Period>())
216 ++__rt;
217 return _M_try_lock_until(steady_clock::now() + __rt);
218 }
219
220 template<typename _Duration>
221 bool
222 _M_try_lock_until(const chrono::time_point<__clock_t,
223 _Duration>& __atime)
224 {
225 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
226 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
227
228 __gthread_time_t __ts = {
229 static_cast<std::time_t>(__s.time_since_epoch().count()),
230 static_cast<long>(__ns.count())
231 };
232
233 auto __mutex = static_cast<_Derived*>(this)->native_handle();
234 return !__gthread_mutex_timedlock(__mutex, &__ts);
235 }
236
237 template<typename _Clock, typename _Duration>
238 bool
239 _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
240 {
241 auto __rtime = __atime - _Clock::now();
242 return _M_try_lock_until(__clock_t::now() + __rtime);
243 }
244 };
245
246 /// The standard timed mutex type.
247 class timed_mutex
248 : private __mutex_base, public __timed_mutex_impl<timed_mutex>
249 {
250 public:
251 typedef __native_type* native_handle_type;
252
253 timed_mutex() = default;
254 ~timed_mutex() = default;
255
256 timed_mutex(const timed_mutex&) = delete;
257 timed_mutex& operator=(const timed_mutex&) = delete;
258
259 void
260 lock()
261 {
262 int __e = __gthread_mutex_lock(&_M_mutex);
263
264 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
265 if (__e)
266 __throw_system_error(__e);
267 }
268
269 bool
270 try_lock() noexcept
271 {
272 // XXX EINVAL, EAGAIN, EBUSY
273 return !__gthread_mutex_trylock(&_M_mutex);
274 }
275
276 template <class _Rep, class _Period>
277 bool
278 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
279 { return _M_try_lock_for(__rtime); }
280
281 template <class _Clock, class _Duration>
282 bool
283 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
284 { return _M_try_lock_until(__atime); }
285
286 void
287 unlock()
288 {
289 // XXX EINVAL, EAGAIN, EBUSY
290 __gthread_mutex_unlock(&_M_mutex);
291 }
292
293 native_handle_type
294 native_handle()
295 { return &_M_mutex; }
296 };
297
298 /// The standard recursive timed mutex type.
299 class recursive_timed_mutex
300 : private __recursive_mutex_base,
301 public __timed_mutex_impl<recursive_timed_mutex>
302 {
303 public:
304 typedef __native_type* native_handle_type;
305
306 recursive_timed_mutex() = default;
307 ~recursive_timed_mutex() = default;
308
309 recursive_timed_mutex(const recursive_timed_mutex&) = delete;
310 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
311
312 void
313 lock()
314 {
315 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
316
317 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
318 if (__e)
319 __throw_system_error(__e);
320 }
321
322 bool
323 try_lock() noexcept
324 {
325 // XXX EINVAL, EAGAIN, EBUSY
326 return !__gthread_recursive_mutex_trylock(&_M_mutex);
327 }
328
329 template <class _Rep, class _Period>
330 bool
331 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
332 { return _M_try_lock_for(__rtime); }
333
334 template <class _Clock, class _Duration>
335 bool
336 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
337 { return _M_try_lock_until(__atime); }
338
339 void
340 unlock()
341 {
342 // XXX EINVAL, EAGAIN, EBUSY
343 __gthread_recursive_mutex_unlock(&_M_mutex);
344 }
345
346 native_handle_type
347 native_handle()
348 { return &_M_mutex; }
349 };
350#endif
351#endif // _GLIBCXX_HAS_GTHREADS
352
353 /// Do not acquire ownership of the mutex.
354 struct defer_lock_t { };
355
356 /// Try to acquire ownership of the mutex without blocking.
357 struct try_to_lock_t { };
358
359 /// Assume the calling thread has already obtained mutex ownership
360 /// and manage it.
361 struct adopt_lock_t { };
362
363 /// Tag used to prevent a scoped lock from acquiring ownership of a mutex.
364 constexpr defer_lock_t defer_lock { };
365
366 /// Tag used to prevent a scoped lock from blocking if a mutex is locked.
367 constexpr try_to_lock_t try_to_lock { };
368
369 /// Tag used to make a scoped lock take ownership of a locked mutex.
370 constexpr adopt_lock_t adopt_lock { };
371
372 /** @brief A movable scoped lock type.
373 *
374 * A unique_lock controls mutex ownership within a scope. Ownership of the
375 * mutex can be delayed until after construction and can be transferred
376 * to another unique_lock by move construction or move assignment. If a
377 * mutex lock is owned when the destructor runs ownership will be released.
378 */
379 template<typename _Mutex>
380 class lock_guard
381 {
382 public:
383 typedef _Mutex mutex_type;
384
385 explicit lock_guard(mutex_type& __m) : _M_device(__m)
386 { _M_device.lock(); }
387
388 lock_guard(mutex_type& __m, adopt_lock_t) : _M_device(__m)
389 { } // calling thread owns mutex
390
391 ~lock_guard()
392 { _M_device.unlock(); }
393
394 lock_guard(const lock_guard&) = delete;
395 lock_guard& operator=(const lock_guard&) = delete;
396
397 private:
398 mutex_type& _M_device;
399 };
400
401 /// unique_lock
402 template<typename _Mutex>
403 class unique_lock
404 {
405 public:
406 typedef _Mutex mutex_type;
407
408 unique_lock() noexcept
409 : _M_device(0), _M_owns(false)
410 { }
411
412 explicit unique_lock(mutex_type& __m)
413 : _M_device(std::__addressof(__m)), _M_owns(false)
414 {
415 lock();
416 _M_owns = true;
417 }
418
419 unique_lock(mutex_type& __m, defer_lock_t) noexcept
420 : _M_device(std::__addressof(__m)), _M_owns(false)
421 { }
422
423 unique_lock(mutex_type& __m, try_to_lock_t)
424 : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock())
425 { }
426
427 unique_lock(mutex_type& __m, adopt_lock_t)
428 : _M_device(std::__addressof(__m)), _M_owns(true)
429 {
430 // XXX calling thread owns mutex
431 }
432
433 template<typename _Clock, typename _Duration>
434 unique_lock(mutex_type& __m,
435 const chrono::time_point<_Clock, _Duration>& __atime)
436 : _M_device(std::__addressof(__m)),
437 _M_owns(_M_device->try_lock_until(__atime))
438 { }
439
440 template<typename _Rep, typename _Period>
441 unique_lock(mutex_type& __m,
442 const chrono::duration<_Rep, _Period>& __rtime)
443 : _M_device(std::__addressof(__m)),
444 _M_owns(_M_device->try_lock_for(__rtime))
445 { }
446
447 ~unique_lock()
448 {
449 if (_M_owns)
450 unlock();
451 }
452
453 unique_lock(const unique_lock&) = delete;
454 unique_lock& operator=(const unique_lock&) = delete;
455
456 unique_lock(unique_lock&& __u) noexcept
457 : _M_device(__u._M_device), _M_owns(__u._M_owns)
458 {
459 __u._M_device = 0;
460 __u._M_owns = false;
461 }
462
463 unique_lock& operator=(unique_lock&& __u) noexcept
464 {
465 if(_M_owns)
466 unlock();
467
468 unique_lock(std::move(__u)).swap(*this);
469
470 __u._M_device = 0;
471 __u._M_owns = false;
472
473 return *this;
474 }
475
476 void
477 lock()
478 {
479 if (!_M_device)
480 __throw_system_error(int(errc::operation_not_permitted));
481 else if (_M_owns)
482 __throw_system_error(int(errc::resource_deadlock_would_occur));
483 else
484 {
485 _M_device->lock();
486 _M_owns = true;
487 }
488 }
489
490 bool
491 try_lock()
492 {
493 if (!_M_device)
494 __throw_system_error(int(errc::operation_not_permitted));
495 else if (_M_owns)
496 __throw_system_error(int(errc::resource_deadlock_would_occur));
497 else
498 {
499 _M_owns = _M_device->try_lock();
500 return _M_owns;
501 }
502 }
503
504 template<typename _Clock, typename _Duration>
505 bool
506 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
507 {
508 if (!_M_device)
509 __throw_system_error(int(errc::operation_not_permitted));
510 else if (_M_owns)
511 __throw_system_error(int(errc::resource_deadlock_would_occur));
512 else
513 {
514 _M_owns = _M_device->try_lock_until(__atime);
515 return _M_owns;
516 }
517 }
518
519 template<typename _Rep, typename _Period>
520 bool
521 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
522 {
523 if (!_M_device)
524 __throw_system_error(int(errc::operation_not_permitted));
525 else if (_M_owns)
526 __throw_system_error(int(errc::resource_deadlock_would_occur));
527 else
528 {
529 _M_owns = _M_device->try_lock_for(__rtime);
530 return _M_owns;
531 }
532 }
533
534 void
535 unlock()
536 {
537 if (!_M_owns)
538 __throw_system_error(int(errc::operation_not_permitted));
539 else if (_M_device)
540 {
541 _M_device->unlock();
542 _M_owns = false;
543 }
544 }
545
546 void
547 swap(unique_lock& __u) noexcept
548 {
549 std::swap(_M_device, __u._M_device);
550 std::swap(_M_owns, __u._M_owns);
551 }
552
553 mutex_type*
554 release() noexcept
555 {
556 mutex_type* __ret = _M_device;
557 _M_device = 0;
558 _M_owns = false;
559 return __ret;
560 }
561
562 bool
563 owns_lock() const noexcept
564 { return _M_owns; }
565
566 explicit operator bool() const noexcept
567 { return owns_lock(); }
568
569 mutex_type*
570 mutex() const noexcept
571 { return _M_device; }
572
573 private:
574 mutex_type* _M_device;
575 bool _M_owns; // XXX use atomic_bool
576 };
577
578 /// Swap overload for unique_lock objects.
579 template<typename _Mutex>
580 inline void
581 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
582 { __x.swap(__y); }
583
584 template<typename _Lock>
585 inline unique_lock<_Lock>
586 __try_to_lock(_Lock& __l)
587 { return unique_lock<_Lock>{__l, try_to_lock}; }
588
589 template<int _Idx, bool _Continue = true>
590 struct __try_lock_impl
591 {
592 template<typename... _Lock>
593 static void
594 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
595 {
596 __idx = _Idx;
597 auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
598 if (__lock.owns_lock())
599 {
600 constexpr bool __cont = _Idx + 2 < sizeof...(_Lock);
601 using __try_locker = __try_lock_impl<_Idx + 1, __cont>;
602 __try_locker::__do_try_lock(__locks, __idx);
603 if (__idx == -1)
604 __lock.release();
605 }
606 }
607 };
608
609 template<int _Idx>
610 struct __try_lock_impl<_Idx, false>
611 {
612 template<typename... _Lock>
613 static void
614 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
615 {
616 __idx = _Idx;
617 auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
618 if (__lock.owns_lock())
619 {
620 __idx = -1;
621 __lock.release();
622 }
623 }
624 };
625
626 /** @brief Generic try_lock.
627 * @param __l1 Meets Mutex requirements (try_lock() may throw).
628 * @param __l2 Meets Mutex requirements (try_lock() may throw).
629 * @param __l3 Meets Mutex requirements (try_lock() may throw).
630 * @return Returns -1 if all try_lock() calls return true. Otherwise returns
631 * a 0-based index corresponding to the argument that returned false.
632 * @post Either all arguments are locked, or none will be.
633 *
634 * Sequentially calls try_lock() on each argument.
635 */
636 template<typename _Lock1, typename _Lock2, typename... _Lock3>
637 int
638 try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
639 {
640 int __idx;
641 auto __locks = std::tie(__l1, __l2, __l3...);
642 __try_lock_impl<0>::__do_try_lock(__locks, __idx);
643 return __idx;
644 }
645
646 /** @brief Generic lock.
647 * @param __l1 Meets Mutex requirements (try_lock() may throw).
648 * @param __l2 Meets Mutex requirements (try_lock() may throw).
649 * @param __l3 Meets Mutex requirements (try_lock() may throw).
650 * @throw An exception thrown by an argument's lock() or try_lock() member.
651 * @post All arguments are locked.
652 *
653 * All arguments are locked via a sequence of calls to lock(), try_lock()
654 * and unlock(). If the call exits via an exception any locks that were
655 * obtained will be released.
656 */
657 template<typename _L1, typename _L2, typename... _L3>
658 void
659 lock(_L1& __l1, _L2& __l2, _L3&... __l3)
660 {
661 while (true)
662 {
663 using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>;
664 unique_lock<_L1> __first(__l1);
665 int __idx;
666 auto __locks = std::tie(__l2, __l3...);
667 __try_locker::__do_try_lock(__locks, __idx);
668 if (__idx == -1)
669 {
670 __first.release();
671 return;
672 }
673 }
674 }
675
676#ifdef _GLIBCXX_HAS_GTHREADS
677 /// once_flag
678 struct once_flag
679 {
680 private:
681 typedef __gthread_once_t __native_type;
682 __native_type _M_once = __GTHREAD_ONCE_INIT;
683
684 public:
685 /// Constructor
686 constexpr once_flag() noexcept = default;
687
688 /// Deleted copy constructor
689 once_flag(const once_flag&) = delete;
690 /// Deleted assignment operator
691 once_flag& operator=(const once_flag&) = delete;
692
693 template<typename _Callable, typename... _Args>
694 friend void
695 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
696 };
697
698#ifdef _GLIBCXX_HAVE_TLS
699 extern __thread void* __once_callable;
700 extern __thread void (*__once_call)();
701
702 template<typename _Callable>
703 inline void
704 __once_call_impl()
705 {
706 (*(_Callable*)__once_callable)();
707 }
708#else
709 extern function<void()> __once_functor;
710
711 extern void
712 __set_once_functor_lock_ptr(unique_lock<mutex>*);
713
714 extern mutex&
715 __get_once_mutex();
716#endif
717
718 extern "C" void __once_proxy(void);
719
720 /// call_once
721 template<typename _Callable, typename... _Args>
722 void
723 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
724 {
725#ifdef _GLIBCXX_HAVE_TLS
726 auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f),
727 std::forward<_Args>(__args)...);
728 __once_callable = std::__addressof(__bound_functor);
729 __once_call = &__once_call_impl<decltype(__bound_functor)>;
730#else
731 unique_lock<mutex> __functor_lock(__get_once_mutex());
732 auto __callable = std::__bind_simple(std::forward<_Callable>(__f),
733 std::forward<_Args>(__args)...);
734 __once_functor = [&]() { __callable(); };
735 __set_once_functor_lock_ptr(&__functor_lock);
736#endif
737
738 int __e = __gthread_once(&__once._M_once, &__once_proxy);
739
740#ifndef _GLIBCXX_HAVE_TLS
741 if (__functor_lock)
742 __set_once_functor_lock_ptr(0);
743#endif
744
745 if (__e)
746 __throw_system_error(__e);
747 }
748#endif // _GLIBCXX_HAS_GTHREADS
749
750 // @} group mutexes
751_GLIBCXX_END_NAMESPACE_VERSION
752} // namespace
753#endif // _GLIBCXX_USE_C99_STDINT_TR1
754
755#endif // C++11
756
757#endif // _GLIBCXX_MUTEX
758