libstdc++
|
00001 // <mutex> -*- C++ -*- 00002 00003 // Copyright (C) 2003-2015 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file include/mutex 00026 * This is a Standard C++ Library header. 00027 */ 00028 00029 #ifndef _GLIBCXX_MUTEX 00030 #define _GLIBCXX_MUTEX 1 00031 00032 #pragma GCC system_header 00033 00034 #if __cplusplus < 201103L 00035 # include <bits/c++0x_warning.h> 00036 #else 00037 00038 #include <tuple> 00039 #include <chrono> 00040 #include <exception> 00041 #include <type_traits> 00042 #include <functional> 00043 #include <system_error> 00044 #include <bits/functexcept.h> 00045 #include <bits/gthr.h> 00046 #include <bits/move.h> // for std::swap 00047 #include <bits/cxxabi_forced.h> 00048 00049 #ifdef _GLIBCXX_USE_C99_STDINT_TR1 00050 00051 namespace std _GLIBCXX_VISIBILITY(default) 00052 { 00053 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00054 00055 #ifdef _GLIBCXX_HAS_GTHREADS 00056 // Common base class for std::mutex and std::timed_mutex 00057 class __mutex_base 00058 { 00059 protected: 00060 typedef __gthread_mutex_t __native_type; 00061 00062 #ifdef __GTHREAD_MUTEX_INIT 00063 __native_type _M_mutex = __GTHREAD_MUTEX_INIT; 00064 00065 constexpr __mutex_base() noexcept = default; 00066 #else 00067 __native_type _M_mutex; 00068 00069 __mutex_base() noexcept 00070 { 00071 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) 00072 __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); 00073 } 00074 00075 ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); } 00076 #endif 00077 00078 __mutex_base(const __mutex_base&) = delete; 00079 __mutex_base& operator=(const __mutex_base&) = delete; 00080 }; 00081 00082 // Common base class for std::recursive_mutex and std::recursive_timed_mutex 00083 class __recursive_mutex_base 00084 { 00085 protected: 00086 typedef __gthread_recursive_mutex_t __native_type; 00087 00088 __recursive_mutex_base(const __recursive_mutex_base&) = delete; 00089 __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete; 00090 00091 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT 00092 __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT; 00093 00094 __recursive_mutex_base() = default; 00095 #else 00096 __native_type _M_mutex; 00097 00098 __recursive_mutex_base() 00099 { 00100 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) 00101 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex); 00102 } 00103 00104 ~__recursive_mutex_base() 00105 { __gthread_recursive_mutex_destroy(&_M_mutex); } 00106 #endif 00107 }; 00108 00109 /** 00110 * @defgroup mutexes Mutexes 00111 * @ingroup concurrency 00112 * 00113 * Classes for mutex support. 00114 * @{ 00115 */ 00116 00117 /// mutex 00118 class mutex : private __mutex_base 00119 { 00120 public: 00121 typedef __native_type* native_handle_type; 00122 00123 #ifdef __GTHREAD_MUTEX_INIT 00124 constexpr 00125 #endif 00126 mutex() noexcept = default; 00127 ~mutex() = default; 00128 00129 mutex(const mutex&) = delete; 00130 mutex& operator=(const mutex&) = delete; 00131 00132 void 00133 lock() 00134 { 00135 int __e = __gthread_mutex_lock(&_M_mutex); 00136 00137 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 00138 if (__e) 00139 __throw_system_error(__e); 00140 } 00141 00142 bool 00143 try_lock() noexcept 00144 { 00145 // XXX EINVAL, EAGAIN, EBUSY 00146 return !__gthread_mutex_trylock(&_M_mutex); 00147 } 00148 00149 void 00150 unlock() 00151 { 00152 // XXX EINVAL, EAGAIN, EPERM 00153 __gthread_mutex_unlock(&_M_mutex); 00154 } 00155 00156 native_handle_type 00157 native_handle() 00158 { return &_M_mutex; } 00159 }; 00160 00161 /// recursive_mutex 00162 class recursive_mutex : private __recursive_mutex_base 00163 { 00164 public: 00165 typedef __native_type* native_handle_type; 00166 00167 recursive_mutex() = default; 00168 ~recursive_mutex() = default; 00169 00170 recursive_mutex(const recursive_mutex&) = delete; 00171 recursive_mutex& operator=(const recursive_mutex&) = delete; 00172 00173 void 00174 lock() 00175 { 00176 int __e = __gthread_recursive_mutex_lock(&_M_mutex); 00177 00178 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 00179 if (__e) 00180 __throw_system_error(__e); 00181 } 00182 00183 bool 00184 try_lock() noexcept 00185 { 00186 // XXX EINVAL, EAGAIN, EBUSY 00187 return !__gthread_recursive_mutex_trylock(&_M_mutex); 00188 } 00189 00190 void 00191 unlock() 00192 { 00193 // XXX EINVAL, EAGAIN, EBUSY 00194 __gthread_recursive_mutex_unlock(&_M_mutex); 00195 } 00196 00197 native_handle_type 00198 native_handle() 00199 { return &_M_mutex; } 00200 }; 00201 00202 #if _GTHREAD_USE_MUTEX_TIMEDLOCK 00203 template<typename _Derived> 00204 class __timed_mutex_impl 00205 { 00206 protected: 00207 typedef chrono::high_resolution_clock __clock_t; 00208 00209 template<typename _Rep, typename _Period> 00210 bool 00211 _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 00212 { 00213 using chrono::steady_clock; 00214 auto __rt = chrono::duration_cast<steady_clock::duration>(__rtime); 00215 if (ratio_greater<steady_clock::period, _Period>()) 00216 ++__rt; 00217 return _M_try_lock_until(steady_clock::now() + __rt); 00218 } 00219 00220 template<typename _Duration> 00221 bool 00222 _M_try_lock_until(const chrono::time_point<__clock_t, 00223 _Duration>& __atime) 00224 { 00225 auto __s = chrono::time_point_cast<chrono::seconds>(__atime); 00226 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s); 00227 00228 __gthread_time_t __ts = { 00229 static_cast<std::time_t>(__s.time_since_epoch().count()), 00230 static_cast<long>(__ns.count()) 00231 }; 00232 00233 auto __mutex = static_cast<_Derived*>(this)->native_handle(); 00234 return !__gthread_mutex_timedlock(__mutex, &__ts); 00235 } 00236 00237 template<typename _Clock, typename _Duration> 00238 bool 00239 _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 00240 { 00241 auto __rtime = __atime - _Clock::now(); 00242 return _M_try_lock_until(__clock_t::now() + __rtime); 00243 } 00244 }; 00245 00246 /// timed_mutex 00247 class timed_mutex 00248 : private __mutex_base, public __timed_mutex_impl<timed_mutex> 00249 { 00250 public: 00251 typedef __native_type* native_handle_type; 00252 00253 timed_mutex() = default; 00254 ~timed_mutex() = default; 00255 00256 timed_mutex(const timed_mutex&) = delete; 00257 timed_mutex& operator=(const timed_mutex&) = delete; 00258 00259 void 00260 lock() 00261 { 00262 int __e = __gthread_mutex_lock(&_M_mutex); 00263 00264 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 00265 if (__e) 00266 __throw_system_error(__e); 00267 } 00268 00269 bool 00270 try_lock() noexcept 00271 { 00272 // XXX EINVAL, EAGAIN, EBUSY 00273 return !__gthread_mutex_trylock(&_M_mutex); 00274 } 00275 00276 template <class _Rep, class _Period> 00277 bool 00278 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 00279 { return _M_try_lock_for(__rtime); } 00280 00281 template <class _Clock, class _Duration> 00282 bool 00283 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 00284 { return _M_try_lock_until(__atime); } 00285 00286 void 00287 unlock() 00288 { 00289 // XXX EINVAL, EAGAIN, EBUSY 00290 __gthread_mutex_unlock(&_M_mutex); 00291 } 00292 00293 native_handle_type 00294 native_handle() 00295 { return &_M_mutex; } 00296 }; 00297 00298 /// recursive_timed_mutex 00299 class recursive_timed_mutex 00300 : private __recursive_mutex_base, 00301 public __timed_mutex_impl<recursive_timed_mutex> 00302 { 00303 public: 00304 typedef __native_type* native_handle_type; 00305 00306 recursive_timed_mutex() = default; 00307 ~recursive_timed_mutex() = default; 00308 00309 recursive_timed_mutex(const recursive_timed_mutex&) = delete; 00310 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; 00311 00312 void 00313 lock() 00314 { 00315 int __e = __gthread_recursive_mutex_lock(&_M_mutex); 00316 00317 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 00318 if (__e) 00319 __throw_system_error(__e); 00320 } 00321 00322 bool 00323 try_lock() noexcept 00324 { 00325 // XXX EINVAL, EAGAIN, EBUSY 00326 return !__gthread_recursive_mutex_trylock(&_M_mutex); 00327 } 00328 00329 template <class _Rep, class _Period> 00330 bool 00331 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 00332 { return _M_try_lock_for(__rtime); } 00333 00334 template <class _Clock, class _Duration> 00335 bool 00336 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 00337 { return _M_try_lock_until(__atime); } 00338 00339 void 00340 unlock() 00341 { 00342 // XXX EINVAL, EAGAIN, EBUSY 00343 __gthread_recursive_mutex_unlock(&_M_mutex); 00344 } 00345 00346 native_handle_type 00347 native_handle() 00348 { return &_M_mutex; } 00349 }; 00350 #endif 00351 #endif // _GLIBCXX_HAS_GTHREADS 00352 00353 /// Do not acquire ownership of the mutex. 00354 struct defer_lock_t { }; 00355 00356 /// Try to acquire ownership of the mutex without blocking. 00357 struct try_to_lock_t { }; 00358 00359 /// Assume the calling thread has already obtained mutex ownership 00360 /// and manage it. 00361 struct adopt_lock_t { }; 00362 00363 constexpr defer_lock_t defer_lock { }; 00364 constexpr try_to_lock_t try_to_lock { }; 00365 constexpr adopt_lock_t adopt_lock { }; 00366 00367 /// @brief Scoped lock idiom. 00368 // Acquire the mutex here with a constructor call, then release with 00369 // the destructor call in accordance with RAII style. 00370 template<typename _Mutex> 00371 class lock_guard 00372 { 00373 public: 00374 typedef _Mutex mutex_type; 00375 00376 explicit lock_guard(mutex_type& __m) : _M_device(__m) 00377 { _M_device.lock(); } 00378 00379 lock_guard(mutex_type& __m, adopt_lock_t) : _M_device(__m) 00380 { } // calling thread owns mutex 00381 00382 ~lock_guard() 00383 { _M_device.unlock(); } 00384 00385 lock_guard(const lock_guard&) = delete; 00386 lock_guard& operator=(const lock_guard&) = delete; 00387 00388 private: 00389 mutex_type& _M_device; 00390 }; 00391 00392 /// unique_lock 00393 template<typename _Mutex> 00394 class unique_lock 00395 { 00396 public: 00397 typedef _Mutex mutex_type; 00398 00399 unique_lock() noexcept 00400 : _M_device(0), _M_owns(false) 00401 { } 00402 00403 explicit unique_lock(mutex_type& __m) 00404 : _M_device(std::__addressof(__m)), _M_owns(false) 00405 { 00406 lock(); 00407 _M_owns = true; 00408 } 00409 00410 unique_lock(mutex_type& __m, defer_lock_t) noexcept 00411 : _M_device(std::__addressof(__m)), _M_owns(false) 00412 { } 00413 00414 unique_lock(mutex_type& __m, try_to_lock_t) 00415 : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock()) 00416 { } 00417 00418 unique_lock(mutex_type& __m, adopt_lock_t) 00419 : _M_device(std::__addressof(__m)), _M_owns(true) 00420 { 00421 // XXX calling thread owns mutex 00422 } 00423 00424 template<typename _Clock, typename _Duration> 00425 unique_lock(mutex_type& __m, 00426 const chrono::time_point<_Clock, _Duration>& __atime) 00427 : _M_device(std::__addressof(__m)), 00428 _M_owns(_M_device->try_lock_until(__atime)) 00429 { } 00430 00431 template<typename _Rep, typename _Period> 00432 unique_lock(mutex_type& __m, 00433 const chrono::duration<_Rep, _Period>& __rtime) 00434 : _M_device(std::__addressof(__m)), 00435 _M_owns(_M_device->try_lock_for(__rtime)) 00436 { } 00437 00438 ~unique_lock() 00439 { 00440 if (_M_owns) 00441 unlock(); 00442 } 00443 00444 unique_lock(const unique_lock&) = delete; 00445 unique_lock& operator=(const unique_lock&) = delete; 00446 00447 unique_lock(unique_lock&& __u) noexcept 00448 : _M_device(__u._M_device), _M_owns(__u._M_owns) 00449 { 00450 __u._M_device = 0; 00451 __u._M_owns = false; 00452 } 00453 00454 unique_lock& operator=(unique_lock&& __u) noexcept 00455 { 00456 if(_M_owns) 00457 unlock(); 00458 00459 unique_lock(std::move(__u)).swap(*this); 00460 00461 __u._M_device = 0; 00462 __u._M_owns = false; 00463 00464 return *this; 00465 } 00466 00467 void 00468 lock() 00469 { 00470 if (!_M_device) 00471 __throw_system_error(int(errc::operation_not_permitted)); 00472 else if (_M_owns) 00473 __throw_system_error(int(errc::resource_deadlock_would_occur)); 00474 else 00475 { 00476 _M_device->lock(); 00477 _M_owns = true; 00478 } 00479 } 00480 00481 bool 00482 try_lock() 00483 { 00484 if (!_M_device) 00485 __throw_system_error(int(errc::operation_not_permitted)); 00486 else if (_M_owns) 00487 __throw_system_error(int(errc::resource_deadlock_would_occur)); 00488 else 00489 { 00490 _M_owns = _M_device->try_lock(); 00491 return _M_owns; 00492 } 00493 } 00494 00495 template<typename _Clock, typename _Duration> 00496 bool 00497 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 00498 { 00499 if (!_M_device) 00500 __throw_system_error(int(errc::operation_not_permitted)); 00501 else if (_M_owns) 00502 __throw_system_error(int(errc::resource_deadlock_would_occur)); 00503 else 00504 { 00505 _M_owns = _M_device->try_lock_until(__atime); 00506 return _M_owns; 00507 } 00508 } 00509 00510 template<typename _Rep, typename _Period> 00511 bool 00512 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 00513 { 00514 if (!_M_device) 00515 __throw_system_error(int(errc::operation_not_permitted)); 00516 else if (_M_owns) 00517 __throw_system_error(int(errc::resource_deadlock_would_occur)); 00518 else 00519 { 00520 _M_owns = _M_device->try_lock_for(__rtime); 00521 return _M_owns; 00522 } 00523 } 00524 00525 void 00526 unlock() 00527 { 00528 if (!_M_owns) 00529 __throw_system_error(int(errc::operation_not_permitted)); 00530 else if (_M_device) 00531 { 00532 _M_device->unlock(); 00533 _M_owns = false; 00534 } 00535 } 00536 00537 void 00538 swap(unique_lock& __u) noexcept 00539 { 00540 std::swap(_M_device, __u._M_device); 00541 std::swap(_M_owns, __u._M_owns); 00542 } 00543 00544 mutex_type* 00545 release() noexcept 00546 { 00547 mutex_type* __ret = _M_device; 00548 _M_device = 0; 00549 _M_owns = false; 00550 return __ret; 00551 } 00552 00553 bool 00554 owns_lock() const noexcept 00555 { return _M_owns; } 00556 00557 explicit operator bool() const noexcept 00558 { return owns_lock(); } 00559 00560 mutex_type* 00561 mutex() const noexcept 00562 { return _M_device; } 00563 00564 private: 00565 mutex_type* _M_device; 00566 bool _M_owns; // XXX use atomic_bool 00567 }; 00568 00569 /// Swap overload for unique_lock objects. 00570 template<typename _Mutex> 00571 inline void 00572 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept 00573 { __x.swap(__y); } 00574 00575 template<typename _Lock> 00576 inline unique_lock<_Lock> 00577 __try_to_lock(_Lock& __l) 00578 { return unique_lock<_Lock>{__l, try_to_lock}; } 00579 00580 template<int _Idx, bool _Continue = true> 00581 struct __try_lock_impl 00582 { 00583 template<typename... _Lock> 00584 static void 00585 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) 00586 { 00587 __idx = _Idx; 00588 auto __lock = std::__try_to_lock(std::get<_Idx>(__locks)); 00589 if (__lock.owns_lock()) 00590 { 00591 constexpr bool __cont = _Idx + 2 < sizeof...(_Lock); 00592 using __try_locker = __try_lock_impl<_Idx + 1, __cont>; 00593 __try_locker::__do_try_lock(__locks, __idx); 00594 if (__idx == -1) 00595 __lock.release(); 00596 } 00597 } 00598 }; 00599 00600 template<int _Idx> 00601 struct __try_lock_impl<_Idx, false> 00602 { 00603 template<typename... _Lock> 00604 static void 00605 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) 00606 { 00607 __idx = _Idx; 00608 auto __lock = std::__try_to_lock(std::get<_Idx>(__locks)); 00609 if (__lock.owns_lock()) 00610 { 00611 __idx = -1; 00612 __lock.release(); 00613 } 00614 } 00615 }; 00616 00617 /** @brief Generic try_lock. 00618 * @param __l1 Meets Mutex requirements (try_lock() may throw). 00619 * @param __l2 Meets Mutex requirements (try_lock() may throw). 00620 * @param __l3 Meets Mutex requirements (try_lock() may throw). 00621 * @return Returns -1 if all try_lock() calls return true. Otherwise returns 00622 * a 0-based index corresponding to the argument that returned false. 00623 * @post Either all arguments are locked, or none will be. 00624 * 00625 * Sequentially calls try_lock() on each argument. 00626 */ 00627 template<typename _Lock1, typename _Lock2, typename... _Lock3> 00628 int 00629 try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3) 00630 { 00631 int __idx; 00632 auto __locks = std::tie(__l1, __l2, __l3...); 00633 __try_lock_impl<0>::__do_try_lock(__locks, __idx); 00634 return __idx; 00635 } 00636 00637 /** @brief Generic lock. 00638 * @param __l1 Meets Mutex requirements (try_lock() may throw). 00639 * @param __l2 Meets Mutex requirements (try_lock() may throw). 00640 * @param __l3 Meets Mutex requirements (try_lock() may throw). 00641 * @throw An exception thrown by an argument's lock() or try_lock() member. 00642 * @post All arguments are locked. 00643 * 00644 * All arguments are locked via a sequence of calls to lock(), try_lock() 00645 * and unlock(). If the call exits via an exception any locks that were 00646 * obtained will be released. 00647 */ 00648 template<typename _L1, typename _L2, typename... _L3> 00649 void 00650 lock(_L1& __l1, _L2& __l2, _L3&... __l3) 00651 { 00652 while (true) 00653 { 00654 using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>; 00655 unique_lock<_L1> __first(__l1); 00656 int __idx; 00657 auto __locks = std::tie(__l2, __l3...); 00658 __try_locker::__do_try_lock(__locks, __idx); 00659 if (__idx == -1) 00660 { 00661 __first.release(); 00662 return; 00663 } 00664 } 00665 } 00666 00667 #ifdef _GLIBCXX_HAS_GTHREADS 00668 /// once_flag 00669 struct once_flag 00670 { 00671 private: 00672 typedef __gthread_once_t __native_type; 00673 __native_type _M_once = __GTHREAD_ONCE_INIT; 00674 00675 public: 00676 /// Constructor 00677 constexpr once_flag() noexcept = default; 00678 00679 /// Deleted copy constructor 00680 once_flag(const once_flag&) = delete; 00681 /// Deleted assignment operator 00682 once_flag& operator=(const once_flag&) = delete; 00683 00684 template<typename _Callable, typename... _Args> 00685 friend void 00686 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args); 00687 }; 00688 00689 #ifdef _GLIBCXX_HAVE_TLS 00690 extern __thread void* __once_callable; 00691 extern __thread void (*__once_call)(); 00692 00693 template<typename _Callable> 00694 inline void 00695 __once_call_impl() 00696 { 00697 (*(_Callable*)__once_callable)(); 00698 } 00699 #else 00700 extern function<void()> __once_functor; 00701 00702 extern void 00703 __set_once_functor_lock_ptr(unique_lock<mutex>*); 00704 00705 extern mutex& 00706 __get_once_mutex(); 00707 #endif 00708 00709 extern "C" void __once_proxy(void); 00710 00711 /// call_once 00712 template<typename _Callable, typename... _Args> 00713 void 00714 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args) 00715 { 00716 #ifdef _GLIBCXX_HAVE_TLS 00717 auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f), 00718 std::forward<_Args>(__args)...); 00719 __once_callable = std::__addressof(__bound_functor); 00720 __once_call = &__once_call_impl<decltype(__bound_functor)>; 00721 #else 00722 unique_lock<mutex> __functor_lock(__get_once_mutex()); 00723 auto __callable = std::__bind_simple(std::forward<_Callable>(__f), 00724 std::forward<_Args>(__args)...); 00725 __once_functor = [&]() { __callable(); }; 00726 __set_once_functor_lock_ptr(&__functor_lock); 00727 #endif 00728 00729 int __e = __gthread_once(&__once._M_once, &__once_proxy); 00730 00731 #ifndef _GLIBCXX_HAVE_TLS 00732 if (__functor_lock) 00733 __set_once_functor_lock_ptr(0); 00734 #endif 00735 00736 if (__e) 00737 __throw_system_error(__e); 00738 } 00739 #endif // _GLIBCXX_HAS_GTHREADS 00740 00741 // @} group mutexes 00742 _GLIBCXX_END_NAMESPACE_VERSION 00743 } // namespace 00744 #endif // _GLIBCXX_USE_C99_STDINT_TR1 00745 00746 #endif // C++11 00747 00748 #endif // _GLIBCXX_MUTEX