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