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