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