mutex

Go to the documentation of this file.
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

Generated on Thu Jul 23 21:16:12 2009 for libstdc++ by  doxygen 1.5.8