libstdc++
|
00001 // <mutex> -*- C++ -*- 00002 00003 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 00004 // Free Software Foundation, Inc. 00005 // 00006 // This file is part of the GNU ISO C++ Library. This library is free 00007 // software; you can redistribute it and/or modify it under the 00008 // terms of the GNU General Public License as published by the 00009 // Free Software Foundation; either version 3, or (at your option) 00010 // any later version. 00011 00012 // This library is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 00017 // Under Section 7 of GPL version 3, you are granted additional 00018 // permissions described in the GCC Runtime Library Exception, version 00019 // 3.1, as published by the Free Software Foundation. 00020 00021 // You should have received a copy of the GNU General Public License and 00022 // a copy of the GCC Runtime Library Exception along with this program; 00023 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00024 // <http://www.gnu.org/licenses/>. 00025 00026 /** @file mutex 00027 * This is a Standard C++ Library header. 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> // for std::swap 00049 00050 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) 00051 00052 namespace std 00053 { 00054 /** 00055 * @defgroup mutexes Mutexes 00056 * @ingroup concurrency 00057 * 00058 * Classes for mutex support. 00059 * @{ 00060 */ 00061 00062 /// mutex 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 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) 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 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 00091 if (__e) 00092 __throw_system_error(__e); 00093 } 00094 00095 bool 00096 try_lock() 00097 { 00098 // XXX EINVAL, EAGAIN, EBUSY 00099 return !__gthread_mutex_trylock(&_M_mutex); 00100 } 00101 00102 void 00103 unlock() 00104 { 00105 // XXX EINVAL, EAGAIN, EPERM 00106 __gthread_mutex_unlock(&_M_mutex); 00107 } 00108 00109 native_handle_type 00110 native_handle() 00111 { return &_M_mutex; } 00112 }; 00113 00114 /// recursive_mutex 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 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) 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 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 00143 if (__e) 00144 __throw_system_error(__e); 00145 } 00146 00147 bool 00148 try_lock() 00149 { 00150 // XXX EINVAL, EAGAIN, EBUSY 00151 return !__gthread_recursive_mutex_trylock(&_M_mutex); 00152 } 00153 00154 void 00155 unlock() 00156 { 00157 // XXX EINVAL, EAGAIN, EBUSY 00158 __gthread_recursive_mutex_unlock(&_M_mutex); 00159 } 00160 00161 native_handle_type 00162 native_handle() 00163 { return &_M_mutex; } 00164 }; 00165 00166 /// timed_mutex 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 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 00201 if (__e) 00202 __throw_system_error(__e); 00203 } 00204 00205 bool 00206 try_lock() 00207 { 00208 // XXX EINVAL, EAGAIN, EBUSY 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 // XXX EINVAL, EAGAIN, EBUSY 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 /// recursive_timed_mutex 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 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) 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 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 00306 if (__e) 00307 __throw_system_error(__e); 00308 } 00309 00310 bool 00311 try_lock() 00312 { 00313 // XXX EINVAL, EAGAIN, EBUSY 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 // XXX EINVAL, EAGAIN, EBUSY 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 /// Do not acquire ownership of the mutex. 00376 struct defer_lock_t { }; 00377 00378 /// Try to acquire ownership of the mutex without blocking. 00379 struct try_to_lock_t { }; 00380 00381 /// Assume the calling thread has already obtained mutex ownership 00382 /// and manage it. 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 * @brief Thrown to indicate errors with lock operations. 00391 * 00392 * @ingroup exceptions 00393 */ 00394 class lock_error : public exception 00395 { 00396 public: 00397 virtual const char* 00398 what() const throw(); 00399 }; 00400 00401 /// @brief Scoped lock idiom. 00402 // Acquire the mutex here with a constructor call, then release with 00403 // the destructor call in accordance with RAII style. 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 /// unique_lock 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 // XXX calling thread owns mutex 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 /* explicit */ 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; // XXX use atomic_bool 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 /** @brief Generic try_lock. 00675 * @param __l1 Meets Mutex requirements (try_lock() may throw). 00676 * @param __l2 Meets Mutex requirements (try_lock() may throw). 00677 * @param __l3 Meets Mutex requirements (try_lock() may throw). 00678 * @return Returns -1 if all try_lock() calls return true. Otherwise returns 00679 * a 0-based index corresponding to the argument that returned false. 00680 * @post Either all arguments are locked, or none will be. 00681 * 00682 * Sequentially calls try_lock() on each argument. 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 /// lock 00693 template<typename _L1, typename _L2, typename ..._L3> 00694 void 00695 lock(_L1&, _L2&, _L3&...); 00696 00697 /// once_flag 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 /// call_once 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 // @} group mutexes 00768 } 00769 00770 #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 00771 00772 #endif // __GXX_EXPERIMENTAL_CXX0X__ 00773 00774 #endif // _GLIBCXX_MUTEX