libstdc++
|
00001 // <mutex> -*- C++ -*- 00002 00003 // Copyright (C) 2003-2014 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(&__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(&__m), _M_owns(false) 00412 { } 00413 00414 unique_lock(mutex_type& __m, try_to_lock_t) 00415 : _M_device(&__m), _M_owns(_M_device->try_lock()) 00416 { } 00417 00418 unique_lock(mutex_type& __m, adopt_lock_t) 00419 : _M_device(&__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(&__m), _M_owns(_M_device->try_lock_until(__atime)) 00428 { } 00429 00430 template<typename _Rep, typename _Period> 00431 unique_lock(mutex_type& __m, 00432 const chrono::duration<_Rep, _Period>& __rtime) 00433 : _M_device(&__m), _M_owns(_M_device->try_lock_for(__rtime)) 00434 { } 00435 00436 ~unique_lock() 00437 { 00438 if (_M_owns) 00439 unlock(); 00440 } 00441 00442 unique_lock(const unique_lock&) = delete; 00443 unique_lock& operator=(const unique_lock&) = delete; 00444 00445 unique_lock(unique_lock&& __u) noexcept 00446 : _M_device(__u._M_device), _M_owns(__u._M_owns) 00447 { 00448 __u._M_device = 0; 00449 __u._M_owns = false; 00450 } 00451 00452 unique_lock& operator=(unique_lock&& __u) noexcept 00453 { 00454 if(_M_owns) 00455 unlock(); 00456 00457 unique_lock(std::move(__u)).swap(*this); 00458 00459 __u._M_device = 0; 00460 __u._M_owns = false; 00461 00462 return *this; 00463 } 00464 00465 void 00466 lock() 00467 { 00468 if (!_M_device) 00469 __throw_system_error(int(errc::operation_not_permitted)); 00470 else if (_M_owns) 00471 __throw_system_error(int(errc::resource_deadlock_would_occur)); 00472 else 00473 { 00474 _M_device->lock(); 00475 _M_owns = true; 00476 } 00477 } 00478 00479 bool 00480 try_lock() 00481 { 00482 if (!_M_device) 00483 __throw_system_error(int(errc::operation_not_permitted)); 00484 else if (_M_owns) 00485 __throw_system_error(int(errc::resource_deadlock_would_occur)); 00486 else 00487 { 00488 _M_owns = _M_device->try_lock(); 00489 return _M_owns; 00490 } 00491 } 00492 00493 template<typename _Clock, typename _Duration> 00494 bool 00495 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 00496 { 00497 if (!_M_device) 00498 __throw_system_error(int(errc::operation_not_permitted)); 00499 else if (_M_owns) 00500 __throw_system_error(int(errc::resource_deadlock_would_occur)); 00501 else 00502 { 00503 _M_owns = _M_device->try_lock_until(__atime); 00504 return _M_owns; 00505 } 00506 } 00507 00508 template<typename _Rep, typename _Period> 00509 bool 00510 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 00511 { 00512 if (!_M_device) 00513 __throw_system_error(int(errc::operation_not_permitted)); 00514 else if (_M_owns) 00515 __throw_system_error(int(errc::resource_deadlock_would_occur)); 00516 else 00517 { 00518 _M_owns = _M_device->try_lock_for(__rtime); 00519 return _M_owns; 00520 } 00521 } 00522 00523 void 00524 unlock() 00525 { 00526 if (!_M_owns) 00527 __throw_system_error(int(errc::operation_not_permitted)); 00528 else if (_M_device) 00529 { 00530 _M_device->unlock(); 00531 _M_owns = false; 00532 } 00533 } 00534 00535 void 00536 swap(unique_lock& __u) noexcept 00537 { 00538 std::swap(_M_device, __u._M_device); 00539 std::swap(_M_owns, __u._M_owns); 00540 } 00541 00542 mutex_type* 00543 release() noexcept 00544 { 00545 mutex_type* __ret = _M_device; 00546 _M_device = 0; 00547 _M_owns = false; 00548 return __ret; 00549 } 00550 00551 bool 00552 owns_lock() const noexcept 00553 { return _M_owns; } 00554 00555 explicit operator bool() const noexcept 00556 { return owns_lock(); } 00557 00558 mutex_type* 00559 mutex() const noexcept 00560 { return _M_device; } 00561 00562 private: 00563 mutex_type* _M_device; 00564 bool _M_owns; // XXX use atomic_bool 00565 }; 00566 00567 /// Partial specialization for unique_lock objects. 00568 template<typename _Mutex> 00569 inline void 00570 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept 00571 { __x.swap(__y); } 00572 00573 template<int _Idx> 00574 struct __unlock_impl 00575 { 00576 template<typename... _Lock> 00577 static void 00578 __do_unlock(tuple<_Lock&...>& __locks) 00579 { 00580 std::get<_Idx>(__locks).unlock(); 00581 __unlock_impl<_Idx - 1>::__do_unlock(__locks); 00582 } 00583 }; 00584 00585 template<> 00586 struct __unlock_impl<-1> 00587 { 00588 template<typename... _Lock> 00589 static void 00590 __do_unlock(tuple<_Lock&...>&) 00591 { } 00592 }; 00593 00594 template<typename _Lock> 00595 unique_lock<_Lock> 00596 __try_to_lock(_Lock& __l) 00597 { return unique_lock<_Lock>(__l, try_to_lock); } 00598 00599 template<int _Idx, bool _Continue = true> 00600 struct __try_lock_impl 00601 { 00602 template<typename... _Lock> 00603 static void 00604 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) 00605 { 00606 __idx = _Idx; 00607 auto __lock = __try_to_lock(std::get<_Idx>(__locks)); 00608 if (__lock.owns_lock()) 00609 { 00610 __try_lock_impl<_Idx + 1, _Idx + 2 < sizeof...(_Lock)>:: 00611 __do_try_lock(__locks, __idx); 00612 if (__idx == -1) 00613 __lock.release(); 00614 } 00615 } 00616 }; 00617 00618 template<int _Idx> 00619 struct __try_lock_impl<_Idx, false> 00620 { 00621 template<typename... _Lock> 00622 static void 00623 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) 00624 { 00625 __idx = _Idx; 00626 auto __lock = __try_to_lock(std::get<_Idx>(__locks)); 00627 if (__lock.owns_lock()) 00628 { 00629 __idx = -1; 00630 __lock.release(); 00631 } 00632 } 00633 }; 00634 00635 /** @brief Generic try_lock. 00636 * @param __l1 Meets Mutex requirements (try_lock() may throw). 00637 * @param __l2 Meets Mutex requirements (try_lock() may throw). 00638 * @param __l3 Meets Mutex requirements (try_lock() may throw). 00639 * @return Returns -1 if all try_lock() calls return true. Otherwise returns 00640 * a 0-based index corresponding to the argument that returned false. 00641 * @post Either all arguments are locked, or none will be. 00642 * 00643 * Sequentially calls try_lock() on each argument. 00644 */ 00645 template<typename _Lock1, typename _Lock2, typename... _Lock3> 00646 int 00647 try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3) 00648 { 00649 int __idx; 00650 auto __locks = std::tie(__l1, __l2, __l3...); 00651 __try_lock_impl<0>::__do_try_lock(__locks, __idx); 00652 return __idx; 00653 } 00654 00655 /** @brief Generic lock. 00656 * @param __l1 Meets Mutex requirements (try_lock() may throw). 00657 * @param __l2 Meets Mutex requirements (try_lock() may throw). 00658 * @param __l3 Meets Mutex requirements (try_lock() may throw). 00659 * @throw An exception thrown by an argument's lock() or try_lock() member. 00660 * @post All arguments are locked. 00661 * 00662 * All arguments are locked via a sequence of calls to lock(), try_lock() 00663 * and unlock(). If the call exits via an exception any locks that were 00664 * obtained will be released. 00665 */ 00666 template<typename _L1, typename _L2, typename ..._L3> 00667 void 00668 lock(_L1& __l1, _L2& __l2, _L3&... __l3) 00669 { 00670 while (true) 00671 { 00672 unique_lock<_L1> __first(__l1); 00673 int __idx; 00674 auto __locks = std::tie(__l2, __l3...); 00675 __try_lock_impl<0, sizeof...(_L3)>::__do_try_lock(__locks, __idx); 00676 if (__idx == -1) 00677 { 00678 __first.release(); 00679 return; 00680 } 00681 } 00682 } 00683 00684 #ifdef _GLIBCXX_HAS_GTHREADS 00685 /// once_flag 00686 struct once_flag 00687 { 00688 private: 00689 typedef __gthread_once_t __native_type; 00690 __native_type _M_once = __GTHREAD_ONCE_INIT; 00691 00692 public: 00693 /// Constructor 00694 constexpr once_flag() noexcept = default; 00695 00696 /// Deleted copy constructor 00697 once_flag(const once_flag&) = delete; 00698 /// Deleted assignment operator 00699 once_flag& operator=(const once_flag&) = delete; 00700 00701 template<typename _Callable, typename... _Args> 00702 friend void 00703 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args); 00704 }; 00705 00706 #ifdef _GLIBCXX_HAVE_TLS 00707 extern __thread void* __once_callable; 00708 extern __thread void (*__once_call)(); 00709 00710 template<typename _Callable> 00711 inline void 00712 __once_call_impl() 00713 { 00714 (*(_Callable*)__once_callable)(); 00715 } 00716 #else 00717 extern function<void()> __once_functor; 00718 00719 extern void 00720 __set_once_functor_lock_ptr(unique_lock<mutex>*); 00721 00722 extern mutex& 00723 __get_once_mutex(); 00724 #endif 00725 00726 extern "C" void __once_proxy(void); 00727 00728 /// call_once 00729 template<typename _Callable, typename... _Args> 00730 void 00731 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args) 00732 { 00733 #ifdef _GLIBCXX_HAVE_TLS 00734 auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f), 00735 std::forward<_Args>(__args)...); 00736 __once_callable = &__bound_functor; 00737 __once_call = &__once_call_impl<decltype(__bound_functor)>; 00738 #else 00739 unique_lock<mutex> __functor_lock(__get_once_mutex()); 00740 auto __callable = std::__bind_simple(std::forward<_Callable>(__f), 00741 std::forward<_Args>(__args)...); 00742 __once_functor = [&]() { __callable(); }; 00743 __set_once_functor_lock_ptr(&__functor_lock); 00744 #endif 00745 00746 int __e = __gthread_once(&__once._M_once, &__once_proxy); 00747 00748 #ifndef _GLIBCXX_HAVE_TLS 00749 if (__functor_lock) 00750 __set_once_functor_lock_ptr(0); 00751 #endif 00752 00753 if (__e) 00754 __throw_system_error(__e); 00755 } 00756 #endif // _GLIBCXX_HAS_GTHREADS 00757 00758 // @} group mutexes 00759 _GLIBCXX_END_NAMESPACE_VERSION 00760 } // namespace 00761 #endif // _GLIBCXX_USE_C99_STDINT_TR1 00762 00763 #endif // C++11 00764 00765 #endif // _GLIBCXX_MUTEX