00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef _GLIBCXX_MUTEX
00031 #define _GLIBCXX_MUTEX 1
00032
00033 #pragma GCC system_header
00034
00035 #ifndef __GXX_EXPERIMENTAL_CXX0X__
00036 # include <bits/c++0x_warning.h>
00037 #else
00038
00039 #include <tuple>
00040 #include <chrono>
00041 #include <exception>
00042 #include <type_traits>
00043 #include <functional>
00044 #include <system_error>
00045 #include <bits/functexcept.h>
00046 #include <bits/gthr.h>
00047 #include <bits/move.h>
00048
00049 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
00050
00051 namespace std _GLIBCXX_VISIBILITY(default)
00052 {
00053 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 class mutex
00065 {
00066 typedef __gthread_mutex_t __native_type;
00067 __native_type _M_mutex;
00068
00069 public:
00070 typedef __native_type* native_handle_type;
00071
00072 #ifdef __GTHREAD_MUTEX_INIT
00073 constexpr mutex() : _M_mutex(__GTHREAD_MUTEX_INIT) { }
00074 #else
00075 mutex()
00076 {
00077
00078 __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
00079 }
00080
00081 ~mutex() { __gthread_mutex_destroy(&_M_mutex); }
00082 #endif
00083
00084 mutex(const mutex&) = delete;
00085 mutex& operator=(const mutex&) = delete;
00086
00087 void
00088 lock()
00089 {
00090 int __e = __gthread_mutex_lock(&_M_mutex);
00091
00092
00093 if (__e)
00094 __throw_system_error(__e);
00095 }
00096
00097 bool
00098 try_lock()
00099 {
00100
00101 return !__gthread_mutex_trylock(&_M_mutex);
00102 }
00103
00104 void
00105 unlock()
00106 {
00107
00108 __gthread_mutex_unlock(&_M_mutex);
00109 }
00110
00111 native_handle_type
00112 native_handle()
00113 { return &_M_mutex; }
00114 };
00115
00116 #ifndef __GTHREAD_RECURSIVE_MUTEX_INIT
00117
00118
00119 class __destroy_recursive_mutex
00120 {
00121 template<typename _Mx, typename _Rm>
00122 static void
00123 _S_destroy_win32(_Mx* __mx, _Rm const* __rmx)
00124 {
00125 __mx->counter = __rmx->counter;
00126 __mx->sema = __rmx->sema;
00127 __gthread_mutex_destroy(__mx);
00128 }
00129
00130 public:
00131
00132 template<typename _Rm>
00133 static typename enable_if<sizeof(&_Rm::sema), void>::type
00134 _S_destroy(_Rm* __mx)
00135 {
00136 __gthread_mutex_t __tmp;
00137 _S_destroy_win32(&__tmp, __mx);
00138 }
00139
00140
00141 template<typename _Rm>
00142 static typename enable_if<sizeof(&_Rm::actual), void>::type
00143 _S_destroy(_Rm* __mx)
00144 { __gthread_mutex_destroy(&__mx->actual); }
00145
00146
00147 template<typename _Rm>
00148 static
00149 typename enable_if<is_same<_Rm, __gthread_mutex_t>::value, void>::type
00150 _S_destroy(_Rm* __mx)
00151 { __gthread_mutex_destroy(__mx); }
00152 };
00153 #endif
00154
00155
00156 class recursive_mutex
00157 {
00158 typedef __gthread_recursive_mutex_t __native_type;
00159 __native_type _M_mutex;
00160
00161 public:
00162 typedef __native_type* native_handle_type;
00163
00164 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
00165 recursive_mutex() : _M_mutex(__GTHREAD_RECURSIVE_MUTEX_INIT) { }
00166 #else
00167 recursive_mutex()
00168 {
00169
00170 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
00171 }
00172
00173 ~recursive_mutex()
00174 { __destroy_recursive_mutex::_S_destroy(&_M_mutex); }
00175 #endif
00176
00177 recursive_mutex(const recursive_mutex&) = delete;
00178 recursive_mutex& operator=(const recursive_mutex&) = delete;
00179
00180 void
00181 lock()
00182 {
00183 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
00184
00185
00186 if (__e)
00187 __throw_system_error(__e);
00188 }
00189
00190 bool
00191 try_lock()
00192 {
00193
00194 return !__gthread_recursive_mutex_trylock(&_M_mutex);
00195 }
00196
00197 void
00198 unlock()
00199 {
00200
00201 __gthread_recursive_mutex_unlock(&_M_mutex);
00202 }
00203
00204 native_handle_type
00205 native_handle()
00206 { return &_M_mutex; }
00207 };
00208
00209
00210 class timed_mutex
00211 {
00212 typedef __gthread_mutex_t __native_type;
00213
00214 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
00215 typedef chrono::monotonic_clock __clock_t;
00216 #else
00217 typedef chrono::high_resolution_clock __clock_t;
00218 #endif
00219
00220 __native_type _M_mutex;
00221
00222 public:
00223 typedef __native_type* native_handle_type;
00224
00225 #ifdef __GTHREAD_MUTEX_INIT
00226 timed_mutex() : _M_mutex(__GTHREAD_MUTEX_INIT) { }
00227 #else
00228 timed_mutex()
00229 {
00230 __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
00231 }
00232
00233 ~timed_mutex() { __gthread_mutex_destroy(&_M_mutex); }
00234 #endif
00235
00236 timed_mutex(const timed_mutex&) = delete;
00237 timed_mutex& operator=(const timed_mutex&) = delete;
00238
00239 void
00240 lock()
00241 {
00242 int __e = __gthread_mutex_lock(&_M_mutex);
00243
00244
00245 if (__e)
00246 __throw_system_error(__e);
00247 }
00248
00249 bool
00250 try_lock()
00251 {
00252
00253 return !__gthread_mutex_trylock(&_M_mutex);
00254 }
00255
00256 template <class _Rep, class _Period>
00257 bool
00258 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
00259 { return __try_lock_for_impl(__rtime); }
00260
00261 template <class _Clock, class _Duration>
00262 bool
00263 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
00264 {
00265 chrono::time_point<_Clock, chrono::seconds> __s =
00266 chrono::time_point_cast<chrono::seconds>(__atime);
00267
00268 chrono::nanoseconds __ns =
00269 chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
00270
00271 __gthread_time_t __ts = {
00272 static_cast<std::time_t>(__s.time_since_epoch().count()),
00273 static_cast<long>(__ns.count())
00274 };
00275
00276 return !__gthread_mutex_timedlock(&_M_mutex, &__ts);
00277 }
00278
00279 void
00280 unlock()
00281 {
00282
00283 __gthread_mutex_unlock(&_M_mutex);
00284 }
00285
00286 native_handle_type
00287 native_handle()
00288 { return &_M_mutex; }
00289
00290 private:
00291 template<typename _Rep, typename _Period>
00292 typename enable_if<
00293 ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
00294 __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
00295 {
00296 __clock_t::time_point __atime = __clock_t::now()
00297 + chrono::duration_cast<__clock_t::duration>(__rtime);
00298
00299 return try_lock_until(__atime);
00300 }
00301
00302 template <typename _Rep, typename _Period>
00303 typename enable_if<
00304 !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
00305 __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
00306 {
00307 __clock_t::time_point __atime = __clock_t::now()
00308 + ++chrono::duration_cast<__clock_t::duration>(__rtime);
00309
00310 return try_lock_until(__atime);
00311 }
00312 };
00313
00314
00315 class recursive_timed_mutex
00316 {
00317 typedef __gthread_recursive_mutex_t __native_type;
00318
00319 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
00320 typedef chrono::monotonic_clock __clock_t;
00321 #else
00322 typedef chrono::high_resolution_clock __clock_t;
00323 #endif
00324
00325 __native_type _M_mutex;
00326
00327 public:
00328 typedef __native_type* native_handle_type;
00329
00330 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
00331 recursive_timed_mutex() : _M_mutex(__GTHREAD_RECURSIVE_MUTEX_INIT) { }
00332 #else
00333 recursive_timed_mutex()
00334 {
00335
00336 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
00337 }
00338
00339 ~recursive_timed_mutex()
00340 { __destroy_recursive_mutex::_S_destroy(&_M_mutex); }
00341 #endif
00342
00343 recursive_timed_mutex(const recursive_timed_mutex&) = delete;
00344 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
00345
00346 void
00347 lock()
00348 {
00349 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
00350
00351
00352 if (__e)
00353 __throw_system_error(__e);
00354 }
00355
00356 bool
00357 try_lock()
00358 {
00359
00360 return !__gthread_recursive_mutex_trylock(&_M_mutex);
00361 }
00362
00363 template <class _Rep, class _Period>
00364 bool
00365 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
00366 { return __try_lock_for_impl(__rtime); }
00367
00368 template <class _Clock, class _Duration>
00369 bool
00370 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
00371 {
00372 chrono::time_point<_Clock, chrono::seconds> __s =
00373 chrono::time_point_cast<chrono::seconds>(__atime);
00374
00375 chrono::nanoseconds __ns =
00376 chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
00377
00378 __gthread_time_t __ts = {
00379 static_cast<std::time_t>(__s.time_since_epoch().count()),
00380 static_cast<long>(__ns.count())
00381 };
00382
00383 return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts);
00384 }
00385
00386 void
00387 unlock()
00388 {
00389
00390 __gthread_recursive_mutex_unlock(&_M_mutex);
00391 }
00392
00393 native_handle_type
00394 native_handle()
00395 { return &_M_mutex; }
00396
00397 private:
00398 template<typename _Rep, typename _Period>
00399 typename enable_if<
00400 ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
00401 __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
00402 {
00403 __clock_t::time_point __atime = __clock_t::now()
00404 + chrono::duration_cast<__clock_t::duration>(__rtime);
00405
00406 return try_lock_until(__atime);
00407 }
00408
00409 template <typename _Rep, typename _Period>
00410 typename enable_if<
00411 !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
00412 __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
00413 {
00414 __clock_t::time_point __atime = __clock_t::now()
00415 + ++chrono::duration_cast<__clock_t::duration>(__rtime);
00416
00417 return try_lock_until(__atime);
00418 }
00419 };
00420
00421
00422 struct defer_lock_t { };
00423
00424
00425 struct try_to_lock_t { };
00426
00427
00428
00429 struct adopt_lock_t { };
00430
00431 constexpr defer_lock_t defer_lock { };
00432 constexpr try_to_lock_t try_to_lock { };
00433 constexpr adopt_lock_t adopt_lock { };
00434
00435
00436
00437
00438 template<typename _Mutex>
00439 class lock_guard
00440 {
00441 public:
00442 typedef _Mutex mutex_type;
00443
00444 explicit lock_guard(mutex_type& __m) : _M_device(__m)
00445 { _M_device.lock(); }
00446
00447 lock_guard(mutex_type& __m, adopt_lock_t) : _M_device(__m)
00448 { }
00449
00450 ~lock_guard()
00451 { _M_device.unlock(); }
00452
00453 lock_guard(const lock_guard&) = delete;
00454 lock_guard& operator=(const lock_guard&) = delete;
00455
00456 private:
00457 mutex_type& _M_device;
00458 };
00459
00460
00461 template<typename _Mutex>
00462 class unique_lock
00463 {
00464 public:
00465 typedef _Mutex mutex_type;
00466
00467 unique_lock()
00468 : _M_device(0), _M_owns(false)
00469 { }
00470
00471 explicit unique_lock(mutex_type& __m)
00472 : _M_device(&__m), _M_owns(false)
00473 {
00474 lock();
00475 _M_owns = true;
00476 }
00477
00478 unique_lock(mutex_type& __m, defer_lock_t)
00479 : _M_device(&__m), _M_owns(false)
00480 { }
00481
00482 unique_lock(mutex_type& __m, try_to_lock_t)
00483 : _M_device(&__m), _M_owns(_M_device->try_lock())
00484 { }
00485
00486 unique_lock(mutex_type& __m, adopt_lock_t)
00487 : _M_device(&__m), _M_owns(true)
00488 {
00489
00490 }
00491
00492 template<typename _Clock, typename _Duration>
00493 unique_lock(mutex_type& __m,
00494 const chrono::time_point<_Clock, _Duration>& __atime)
00495 : _M_device(&__m), _M_owns(_M_device->try_lock_until(__atime))
00496 { }
00497
00498 template<typename _Rep, typename _Period>
00499 unique_lock(mutex_type& __m,
00500 const chrono::duration<_Rep, _Period>& __rtime)
00501 : _M_device(&__m), _M_owns(_M_device->try_lock_for(__rtime))
00502 { }
00503
00504 ~unique_lock()
00505 {
00506 if (_M_owns)
00507 unlock();
00508 }
00509
00510 unique_lock(const unique_lock&) = delete;
00511 unique_lock& operator=(const unique_lock&) = delete;
00512
00513 unique_lock(unique_lock&& __u)
00514 : _M_device(__u._M_device), _M_owns(__u._M_owns)
00515 {
00516 __u._M_device = 0;
00517 __u._M_owns = false;
00518 }
00519
00520 unique_lock& operator=(unique_lock&& __u)
00521 {
00522 if(_M_owns)
00523 unlock();
00524
00525 unique_lock(std::move(__u)).swap(*this);
00526
00527 __u._M_device = 0;
00528 __u._M_owns = false;
00529
00530 return *this;
00531 }
00532
00533 void
00534 lock()
00535 {
00536 if (!_M_device)
00537 __throw_system_error(int(errc::operation_not_permitted));
00538 else if (_M_owns)
00539 __throw_system_error(int(errc::resource_deadlock_would_occur));
00540 else
00541 {
00542 _M_device->lock();
00543 _M_owns = true;
00544 }
00545 }
00546
00547 bool
00548 try_lock()
00549 {
00550 if (!_M_device)
00551 __throw_system_error(int(errc::operation_not_permitted));
00552 else if (_M_owns)
00553 __throw_system_error(int(errc::resource_deadlock_would_occur));
00554 else
00555 {
00556 _M_owns = _M_device->try_lock();
00557 return _M_owns;
00558 }
00559 }
00560
00561 template<typename _Clock, typename _Duration>
00562 bool
00563 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
00564 {
00565 if (!_M_device)
00566 __throw_system_error(int(errc::operation_not_permitted));
00567 else if (_M_owns)
00568 __throw_system_error(int(errc::resource_deadlock_would_occur));
00569 else
00570 {
00571 _M_owns = _M_device->try_lock_until(__atime);
00572 return _M_owns;
00573 }
00574 }
00575
00576 template<typename _Rep, typename _Period>
00577 bool
00578 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
00579 {
00580 if (!_M_device)
00581 __throw_system_error(int(errc::operation_not_permitted));
00582 else if (_M_owns)
00583 __throw_system_error(int(errc::resource_deadlock_would_occur));
00584 else
00585 {
00586 _M_owns = _M_device->try_lock_for(__rtime);
00587 return _M_owns;
00588 }
00589 }
00590
00591 void
00592 unlock()
00593 {
00594 if (!_M_owns)
00595 __throw_system_error(int(errc::operation_not_permitted));
00596 else if (_M_device)
00597 {
00598 _M_device->unlock();
00599 _M_owns = false;
00600 }
00601 }
00602
00603 void
00604 swap(unique_lock& __u)
00605 {
00606 std::swap(_M_device, __u._M_device);
00607 std::swap(_M_owns, __u._M_owns);
00608 }
00609
00610 mutex_type*
00611 release()
00612 {
00613 mutex_type* __ret = _M_device;
00614 _M_device = 0;
00615 _M_owns = false;
00616 return __ret;
00617 }
00618
00619 bool
00620 owns_lock() const
00621 { return _M_owns; }
00622
00623 explicit operator bool() const
00624 { return owns_lock(); }
00625
00626 mutex_type*
00627 mutex() const
00628 { return _M_device; }
00629
00630 private:
00631 mutex_type* _M_device;
00632 bool _M_owns;
00633 };
00634
00635 template<typename _Mutex>
00636 inline void
00637 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y)
00638 { __x.swap(__y); }
00639
00640 template<int _Idx>
00641 struct __unlock_impl
00642 {
00643 template<typename... _Lock>
00644 static void
00645 __do_unlock(tuple<_Lock&...>& __locks)
00646 {
00647 std::get<_Idx>(__locks).unlock();
00648 __unlock_impl<_Idx - 1>::__do_unlock(__locks);
00649 }
00650 };
00651
00652 template<>
00653 struct __unlock_impl<-1>
00654 {
00655 template<typename... _Lock>
00656 static void
00657 __do_unlock(tuple<_Lock&...>&)
00658 { }
00659 };
00660
00661 template<typename _Lock>
00662 unique_lock<_Lock>
00663 __try_to_lock(_Lock& __l)
00664 { return unique_lock<_Lock>(__l, try_to_lock); }
00665
00666 template<int _Idx, bool _Continue = true>
00667 struct __try_lock_impl
00668 {
00669 template<typename... _Lock>
00670 static void
00671 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
00672 {
00673 __idx = _Idx;
00674 auto __lock = __try_to_lock(std::get<_Idx>(__locks));
00675 if (__lock.owns_lock())
00676 {
00677 __try_lock_impl<_Idx + 1, _Idx + 2 < sizeof...(_Lock)>::
00678 __do_try_lock(__locks, __idx);
00679 if (__idx == -1)
00680 __lock.release();
00681 }
00682 }
00683 };
00684
00685 template<int _Idx>
00686 struct __try_lock_impl<_Idx, false>
00687 {
00688 template<typename... _Lock>
00689 static void
00690 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
00691 {
00692 __idx = _Idx;
00693 auto __lock = __try_to_lock(std::get<_Idx>(__locks));
00694 if (__lock.owns_lock())
00695 {
00696 __idx = -1;
00697 __lock.release();
00698 }
00699 }
00700 };
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712 template<typename _Lock1, typename _Lock2, typename... _Lock3>
00713 int
00714 try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
00715 {
00716 int __idx;
00717 auto __locks = std::tie(__l1, __l2, __l3...);
00718 __try
00719 { __try_lock_impl<0>::__do_try_lock(__locks, __idx); }
00720 __catch(...)
00721 { }
00722 return __idx;
00723 }
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 template<typename _L1, typename _L2, typename ..._L3>
00737 void
00738 lock(_L1& __l1, _L2& __l2, _L3&... __l3)
00739 {
00740 while (true)
00741 {
00742 unique_lock<_L1> __first(__l1);
00743 int __idx;
00744 auto __locks = std::tie(__l2, __l3...);
00745 __try_lock_impl<0, sizeof...(_L3)>::__do_try_lock(__locks, __idx);
00746 if (__idx == -1)
00747 {
00748 __first.release();
00749 return;
00750 }
00751 }
00752 }
00753
00754
00755 struct once_flag
00756 {
00757 private:
00758 typedef __gthread_once_t __native_type;
00759 __native_type _M_once;
00760
00761 public:
00762 constexpr once_flag() : _M_once(__GTHREAD_ONCE_INIT) { }
00763
00764 once_flag(const once_flag&) = delete;
00765 once_flag& operator=(const once_flag&) = delete;
00766
00767 template<typename _Callable, typename... _Args>
00768 friend void
00769 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
00770 };
00771
00772 #ifdef _GLIBCXX_HAVE_TLS
00773 extern __thread void* __once_callable;
00774 extern __thread void (*__once_call)();
00775
00776 template<typename _Callable>
00777 inline void
00778 __once_call_impl()
00779 {
00780 (*(_Callable*)__once_callable)();
00781 }
00782 #else
00783 extern function<void()> __once_functor;
00784
00785 extern void
00786 __set_once_functor_lock_ptr(unique_lock<mutex>*);
00787
00788 extern mutex&
00789 __get_once_mutex();
00790 #endif
00791
00792 extern "C" void __once_proxy();
00793
00794
00795 template<typename _Callable, typename... _Args>
00796 void
00797 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
00798 {
00799 #ifdef _GLIBCXX_HAVE_TLS
00800 auto __bound_functor = std::bind<void>(std::forward<_Callable>(__f),
00801 std::forward<_Args>(__args)...);
00802 __once_callable = &__bound_functor;
00803 __once_call = &__once_call_impl<decltype(__bound_functor)>;
00804 #else
00805 unique_lock<mutex> __functor_lock(__get_once_mutex());
00806 __once_functor = std::bind<void>(std::forward<_Callable>(__f),
00807 std::forward<_Args>(__args)...);
00808 __set_once_functor_lock_ptr(&__functor_lock);
00809 #endif
00810
00811 int __e = __gthread_once(&(__once._M_once), &__once_proxy);
00812
00813 #ifndef _GLIBCXX_HAVE_TLS
00814 if (__functor_lock)
00815 __set_once_functor_lock_ptr(0);
00816 #endif
00817
00818 if (__e)
00819 __throw_system_error(__e);
00820 }
00821
00822
00823 _GLIBCXX_END_NAMESPACE_VERSION
00824 }
00825
00826 #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
00827
00828 #endif // __GXX_EXPERIMENTAL_CXX0X__
00829
00830 #endif // _GLIBCXX_MUTEX