libstdc++
mutex
Go to the documentation of this file.
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
00652       { __try_lock_impl<0>::__do_try_lock(__locks, __idx); }
00653       __catch(const __cxxabiv1::__forced_unwind&)
00654       { __throw_exception_again; }
00655       __catch(...)
00656       { }
00657       return __idx;
00658     }
00659 
00660   /** @brief Generic lock.
00661    *  @param __l1 Meets Mutex requirements (try_lock() may throw).
00662    *  @param __l2 Meets Mutex requirements (try_lock() may throw).
00663    *  @param __l3 Meets Mutex requirements (try_lock() may throw).
00664    *  @throw An exception thrown by an argument's lock() or try_lock() member.
00665    *  @post All arguments are locked.
00666    *
00667    *  All arguments are locked via a sequence of calls to lock(), try_lock()
00668    *  and unlock().  If the call exits via an exception any locks that were
00669    *  obtained will be released.
00670    */
00671   template<typename _L1, typename _L2, typename ..._L3>
00672     void
00673     lock(_L1& __l1, _L2& __l2, _L3&... __l3)
00674     {
00675       while (true)
00676         {
00677           unique_lock<_L1> __first(__l1);
00678           int __idx;
00679           auto __locks = std::tie(__l2, __l3...);
00680           __try_lock_impl<0, sizeof...(_L3)>::__do_try_lock(__locks, __idx);
00681           if (__idx == -1)
00682             {
00683               __first.release();
00684               return;
00685             }
00686         }
00687     }
00688 
00689 #ifdef _GLIBCXX_HAS_GTHREADS
00690   /// once_flag
00691   struct once_flag
00692   {
00693   private:
00694     typedef __gthread_once_t __native_type;
00695     __native_type  _M_once = __GTHREAD_ONCE_INIT;
00696 
00697   public:
00698     /// Constructor
00699     constexpr once_flag() noexcept = default;
00700 
00701     /// Deleted copy constructor
00702     once_flag(const once_flag&) = delete;
00703     /// Deleted assignment operator
00704     once_flag& operator=(const once_flag&) = delete;
00705 
00706     template<typename _Callable, typename... _Args>
00707       friend void
00708       call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
00709   };
00710 
00711 #ifdef _GLIBCXX_HAVE_TLS
00712   extern __thread void* __once_callable;
00713   extern __thread void (*__once_call)();
00714 
00715   template<typename _Callable>
00716     inline void
00717     __once_call_impl()
00718     {
00719       (*(_Callable*)__once_callable)();
00720     }
00721 #else
00722   extern function<void()> __once_functor;
00723 
00724   extern void
00725   __set_once_functor_lock_ptr(unique_lock<mutex>*);
00726 
00727   extern mutex&
00728   __get_once_mutex();
00729 #endif
00730 
00731   extern "C" void __once_proxy(void);
00732 
00733   /// call_once
00734   template<typename _Callable, typename... _Args>
00735     void
00736     call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
00737     {
00738 #ifdef _GLIBCXX_HAVE_TLS
00739       auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f),
00740           std::forward<_Args>(__args)...);
00741       __once_callable = &__bound_functor;
00742       __once_call = &__once_call_impl<decltype(__bound_functor)>;
00743 #else
00744       unique_lock<mutex> __functor_lock(__get_once_mutex());
00745       auto __callable = std::__bind_simple(std::forward<_Callable>(__f),
00746           std::forward<_Args>(__args)...);
00747       __once_functor = [&]() { __callable(); };
00748       __set_once_functor_lock_ptr(&__functor_lock);
00749 #endif
00750 
00751       int __e = __gthread_once(&__once._M_once, &__once_proxy);
00752 
00753 #ifndef _GLIBCXX_HAVE_TLS
00754       if (__functor_lock)
00755         __set_once_functor_lock_ptr(0);
00756 #endif
00757 
00758       if (__e)
00759     __throw_system_error(__e);
00760     }
00761 #endif // _GLIBCXX_HAS_GTHREADS
00762 
00763   // @} group mutexes
00764 _GLIBCXX_END_NAMESPACE_VERSION
00765 } // namespace
00766 #endif // _GLIBCXX_USE_C99_STDINT_TR1
00767 
00768 #endif // C++11
00769 
00770 #endif // _GLIBCXX_MUTEX