mutex

Go to the documentation of this file.
00001 // <mutex> -*- C++ -*-
00002 
00003 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
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 <bits/c++0x_warning.h>
00037 #else
00038 
00039 #include <tuple>
00040 #include <chrono>
00041 #include <exception>
00042 #include <type_traits>
00043 #include <functional>
00044 #include <system_error>
00045 #include <bits/functexcept.h>
00046 #include <bits/gthr.h>
00047 #include <bits/move.h> // for std::swap
00048 
00049 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
00050 
00051 namespace std
00052 {
00053   /**
00054    * @defgroup mutexes Mutexes
00055    * @ingroup concurrency
00056    *
00057    * Classes for mutex support.
00058    * @{
00059    */
00060 
00061   /// mutex
00062   class mutex
00063   {
00064     typedef __gthread_mutex_t           __native_type;
00065     __native_type  _M_mutex;
00066 
00067   public:
00068     typedef __native_type*          native_handle_type;
00069 
00070     mutex()
00071     {
00072       // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
00073 #ifdef __GTHREAD_MUTEX_INIT
00074       __native_type __tmp = __GTHREAD_MUTEX_INIT;
00075       _M_mutex = __tmp;
00076 #else
00077       __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
00078 #endif
00079     }
00080 
00081     mutex(const mutex&) = delete;
00082     mutex& operator=(const mutex&) = delete;
00083 
00084     void
00085     lock()
00086     {
00087       int __e = __gthread_mutex_lock(&_M_mutex);
00088 
00089       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
00090       if (__e)
00091     __throw_system_error(__e);
00092     }
00093 
00094     bool
00095     try_lock()
00096     {
00097       // XXX EINVAL, EAGAIN, EBUSY
00098       return !__gthread_mutex_trylock(&_M_mutex);
00099     }
00100 
00101     void
00102     unlock()
00103     {
00104       // XXX EINVAL, EAGAIN, EPERM
00105       __gthread_mutex_unlock(&_M_mutex);
00106     }
00107 
00108     native_handle_type
00109     native_handle()
00110     { return &_M_mutex; }
00111   };
00112 
00113   /// recursive_mutex
00114   class recursive_mutex
00115   {
00116     typedef __gthread_recursive_mutex_t     __native_type;
00117     __native_type  _M_mutex;
00118 
00119   public:
00120     typedef __native_type*          native_handle_type;
00121 
00122     recursive_mutex()
00123     {
00124       // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
00125 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
00126       __native_type __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT;
00127       _M_mutex = __tmp;
00128 #else
00129       __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
00130 #endif
00131     }
00132 
00133     recursive_mutex(const recursive_mutex&) = delete;
00134     recursive_mutex& operator=(const recursive_mutex&) = delete;
00135 
00136     void
00137     lock()
00138     {
00139       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
00140 
00141       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
00142       if (__e)
00143     __throw_system_error(__e);
00144     }
00145 
00146     bool
00147     try_lock()
00148     {
00149       // XXX EINVAL, EAGAIN, EBUSY
00150       return !__gthread_recursive_mutex_trylock(&_M_mutex);
00151     }
00152 
00153     void
00154     unlock()
00155     {
00156       // XXX EINVAL, EAGAIN, EBUSY
00157       __gthread_recursive_mutex_unlock(&_M_mutex);
00158     }
00159 
00160     native_handle_type
00161     native_handle()
00162     { return &_M_mutex; }
00163   };
00164 
00165   /// timed_mutex
00166   class timed_mutex
00167   {
00168     typedef __gthread_mutex_t           __native_type;
00169 
00170 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
00171     typedef chrono::monotonic_clock         __clock_t;
00172 #else
00173     typedef chrono::high_resolution_clock   __clock_t;
00174 #endif
00175 
00176     __native_type  _M_mutex;
00177 
00178   public:
00179     typedef __native_type*          native_handle_type;
00180 
00181     timed_mutex()
00182     {
00183 #ifdef __GTHREAD_MUTEX_INIT
00184       __native_type __tmp = __GTHREAD_MUTEX_INIT;
00185       _M_mutex = __tmp;
00186 #else
00187       __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
00188 #endif
00189     }
00190 
00191     timed_mutex(const timed_mutex&) = delete;
00192     timed_mutex& operator=(const timed_mutex&) = delete;
00193 
00194     void
00195     lock()
00196     {
00197       int __e = __gthread_mutex_lock(&_M_mutex);
00198 
00199       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
00200       if (__e)
00201     __throw_system_error(__e);
00202     }
00203 
00204     bool
00205     try_lock()
00206     {
00207       // XXX EINVAL, EAGAIN, EBUSY
00208       return !__gthread_mutex_trylock(&_M_mutex);
00209     }
00210 
00211     template <class _Rep, class _Period>
00212       bool
00213       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
00214       { return __try_lock_for_impl(__rtime); }
00215 
00216     template <class _Clock, class _Duration>
00217       bool
00218       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
00219       {
00220     chrono::time_point<_Clock, chrono::seconds> __s =
00221       chrono::time_point_cast<chrono::seconds>(__atime);
00222 
00223     chrono::nanoseconds __ns =
00224       chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
00225 
00226     __gthread_time_t __ts = {
00227       static_cast<std::time_t>(__s.time_since_epoch().count()),
00228       static_cast<long>(__ns.count())
00229     };
00230 
00231     return !__gthread_mutex_timedlock(&_M_mutex, &__ts);
00232       }
00233 
00234     void
00235     unlock()
00236     {
00237       // XXX EINVAL, EAGAIN, EBUSY
00238       __gthread_mutex_unlock(&_M_mutex);
00239     }
00240 
00241     native_handle_type
00242     native_handle()
00243     { return &_M_mutex; }
00244 
00245   private:
00246     template<typename _Rep, typename _Period>
00247       typename enable_if<
00248     ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
00249       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
00250       {
00251     __clock_t::time_point __atime = __clock_t::now()
00252       + chrono::duration_cast<__clock_t::duration>(__rtime);
00253 
00254     return try_lock_until(__atime);
00255       }
00256 
00257     template <typename _Rep, typename _Period>
00258       typename enable_if<
00259     !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
00260       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
00261       {
00262     __clock_t::time_point __atime = __clock_t::now()
00263       + ++chrono::duration_cast<__clock_t::duration>(__rtime);
00264 
00265     return try_lock_until(__atime);
00266       }
00267   };
00268 
00269   /// recursive_timed_mutex
00270   class recursive_timed_mutex
00271   {
00272     typedef __gthread_recursive_mutex_t     __native_type;
00273 
00274 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
00275     typedef chrono::monotonic_clock         __clock_t;
00276 #else
00277     typedef chrono::high_resolution_clock   __clock_t;
00278 #endif
00279 
00280     __native_type  _M_mutex;
00281 
00282   public:
00283     typedef __native_type*          native_handle_type;
00284 
00285     recursive_timed_mutex()
00286     {
00287       // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
00288 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
00289       __native_type __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT;
00290       _M_mutex = __tmp;
00291 #else
00292       __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
00293 #endif
00294     }
00295 
00296     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
00297     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
00298 
00299     void
00300     lock()
00301     {
00302       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
00303 
00304       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
00305       if (__e)
00306     __throw_system_error(__e);
00307     }
00308 
00309     bool
00310     try_lock()
00311     {
00312       // XXX EINVAL, EAGAIN, EBUSY
00313       return !__gthread_recursive_mutex_trylock(&_M_mutex);
00314     }
00315 
00316     template <class _Rep, class _Period>
00317       bool
00318       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
00319       { return __try_lock_for_impl(__rtime); }
00320 
00321     template <class _Clock, class _Duration>
00322       bool
00323       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
00324       {
00325     chrono::time_point<_Clock, chrono::seconds>  __s =
00326       chrono::time_point_cast<chrono::seconds>(__atime);
00327 
00328     chrono::nanoseconds __ns =
00329       chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
00330 
00331     __gthread_time_t __ts = {
00332       static_cast<std::time_t>(__s.time_since_epoch().count()),
00333       static_cast<long>(__ns.count())
00334     };
00335 
00336     return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts);
00337       }
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   private:
00351     template<typename _Rep, typename _Period>
00352       typename enable_if<
00353     ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
00354       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
00355       {
00356     __clock_t::time_point __atime = __clock_t::now()
00357       + chrono::duration_cast<__clock_t::duration>(__rtime);
00358 
00359     return try_lock_until(__atime);
00360       }
00361 
00362     template <typename _Rep, typename _Period>
00363       typename enable_if<
00364     !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
00365       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
00366       {
00367     __clock_t::time_point __atime = __clock_t::now()
00368       + ++chrono::duration_cast<__clock_t::duration>(__rtime);
00369 
00370     return try_lock_until(__atime);
00371       }
00372   };
00373 
00374   /// Do not acquire ownership of the mutex.
00375   struct defer_lock_t { };
00376 
00377   /// Try to acquire ownership of the mutex without blocking.
00378   struct try_to_lock_t { };
00379 
00380   /// Assume the calling thread has already obtained mutex ownership
00381   /// and manage it.
00382   struct adopt_lock_t { };
00383 
00384   extern const defer_lock_t defer_lock;
00385   extern const try_to_lock_t    try_to_lock;
00386   extern const adopt_lock_t adopt_lock;
00387 
00388   /// @brief  Scoped lock idiom.
00389   // Acquire the mutex here with a constructor call, then release with
00390   // the destructor call in accordance with RAII style.
00391   template<typename _Mutex>
00392     class lock_guard
00393     {
00394     public:
00395       typedef _Mutex mutex_type;
00396 
00397       explicit lock_guard(mutex_type& __m) : _M_device(__m)
00398       { _M_device.lock(); }
00399 
00400       lock_guard(mutex_type& __m, adopt_lock_t) : _M_device(__m)
00401       { } // calling thread owns mutex
00402 
00403       ~lock_guard()
00404       { _M_device.unlock(); }
00405 
00406       lock_guard(const lock_guard&) = delete;
00407       lock_guard& operator=(const lock_guard&) = delete;
00408 
00409     private:
00410       mutex_type&  _M_device;
00411     };
00412 
00413   /// unique_lock
00414   template<typename _Mutex>
00415     class unique_lock
00416     {
00417     public:
00418       typedef _Mutex mutex_type;
00419 
00420       unique_lock()
00421       : _M_device(0), _M_owns(false)
00422       { }
00423 
00424       explicit unique_lock(mutex_type& __m)
00425       : _M_device(&__m), _M_owns(false)
00426       {
00427     lock();
00428     _M_owns = true;
00429       }
00430 
00431       unique_lock(mutex_type& __m, defer_lock_t)
00432       : _M_device(&__m), _M_owns(false)
00433       { }
00434 
00435       unique_lock(mutex_type& __m, try_to_lock_t)
00436       : _M_device(&__m), _M_owns(_M_device->try_lock())
00437       { }
00438 
00439       unique_lock(mutex_type& __m, adopt_lock_t)
00440       : _M_device(&__m), _M_owns(true)
00441       {
00442     // XXX calling thread owns mutex
00443       }
00444 
00445       template<typename _Clock, typename _Duration>
00446     unique_lock(mutex_type& __m,
00447             const chrono::time_point<_Clock, _Duration>& __atime)
00448     : _M_device(&__m), _M_owns(_M_device->try_lock_until(__atime))
00449     { }
00450 
00451       template<typename _Rep, typename _Period>
00452     unique_lock(mutex_type& __m,
00453             const chrono::duration<_Rep, _Period>& __rtime)
00454     : _M_device(&__m), _M_owns(_M_device->try_lock_for(__rtime))
00455     { }
00456 
00457       ~unique_lock()
00458       {
00459     if (_M_owns)
00460       unlock();
00461       }
00462 
00463       unique_lock(const unique_lock&) = delete;
00464       unique_lock& operator=(const unique_lock&) = delete;
00465 
00466       unique_lock(unique_lock&& __u)
00467       : _M_device(__u._M_device), _M_owns(__u._M_owns)
00468       {
00469     __u._M_device = 0;
00470     __u._M_owns = false;
00471       }
00472 
00473       unique_lock& operator=(unique_lock&& __u)
00474       {
00475     if(_M_owns)
00476       unlock();
00477 
00478     unique_lock(std::move(__u)).swap(*this);
00479 
00480     __u._M_device = 0;
00481     __u._M_owns = false;
00482 
00483     return *this;
00484       }
00485 
00486       void
00487       lock()
00488       {
00489     if (!_M_device)
00490       __throw_system_error(int(errc::operation_not_permitted));
00491     else if (_M_owns)
00492       __throw_system_error(int(errc::resource_deadlock_would_occur));
00493     else
00494       {
00495         _M_device->lock();
00496         _M_owns = true;
00497       }
00498       }
00499 
00500       bool
00501       try_lock()
00502       {
00503     if (!_M_device)
00504       __throw_system_error(int(errc::operation_not_permitted));
00505     else if (_M_owns)
00506       __throw_system_error(int(errc::resource_deadlock_would_occur));
00507     else
00508       {
00509         _M_owns = _M_device->try_lock();
00510         return _M_owns;
00511       }
00512       }
00513 
00514       template<typename _Clock, typename _Duration>
00515     bool
00516     try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
00517     {
00518       if (!_M_device)
00519         __throw_system_error(int(errc::operation_not_permitted));
00520       else if (_M_owns)
00521         __throw_system_error(int(errc::resource_deadlock_would_occur));
00522       else
00523         {
00524           _M_owns = _M_device->try_lock_until(__atime);
00525           return _M_owns;
00526         }
00527     }
00528 
00529       template<typename _Rep, typename _Period>
00530     bool
00531     try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
00532     {
00533       if (!_M_device)
00534         __throw_system_error(int(errc::operation_not_permitted));
00535       else if (_M_owns)
00536         __throw_system_error(int(errc::resource_deadlock_would_occur));
00537       else
00538         {
00539           _M_owns = _M_device->try_lock_for(__rtime);
00540           return _M_owns;
00541         }
00542      }
00543 
00544       void
00545       unlock()
00546       {
00547     if (!_M_owns)
00548       __throw_system_error(int(errc::operation_not_permitted));
00549     else if (_M_device)
00550       {
00551         _M_device->unlock();
00552         _M_owns = false;
00553       }
00554       }
00555 
00556       void
00557       swap(unique_lock& __u)
00558       {
00559     std::swap(_M_device, __u._M_device);
00560     std::swap(_M_owns, __u._M_owns);
00561       }
00562 
00563       mutex_type*
00564       release()
00565       {
00566     mutex_type* __ret = _M_device;
00567     _M_device = 0;
00568     _M_owns = false;
00569     return __ret;
00570       }
00571 
00572       bool
00573       owns_lock() const
00574       { return _M_owns; }
00575 
00576       explicit operator bool() const
00577       { return owns_lock(); }
00578 
00579       mutex_type*
00580       mutex() const
00581       { return _M_device; }
00582 
00583     private:
00584       mutex_type*   _M_device;
00585       bool      _M_owns; // XXX use atomic_bool
00586     };
00587 
00588   template<typename _Mutex>
00589     inline void
00590     swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y)
00591     { __x.swap(__y); }
00592 
00593   template<int _Idx>
00594     struct __unlock_impl
00595     {
00596       template<typename... _Lock>
00597     static void
00598     __do_unlock(tuple<_Lock&...>& __locks)
00599     {
00600       std::get<_Idx>(__locks).unlock();
00601       __unlock_impl<_Idx - 1>::__do_unlock(__locks);
00602     }
00603     };
00604 
00605   template<>
00606     struct __unlock_impl<-1>
00607     {
00608       template<typename... _Lock>
00609     static void
00610     __do_unlock(tuple<_Lock&...>&)
00611     { }
00612     };
00613 
00614   template<int _Idx, bool _Continue = true>
00615     struct __try_lock_impl
00616     {
00617       template<typename... _Lock>
00618     static int
00619     __do_try_lock(tuple<_Lock&...>& __locks)
00620     {
00621       if(std::get<_Idx>(__locks).try_lock())
00622         {
00623           return __try_lock_impl<_Idx + 1,
00624         _Idx + 2 < sizeof...(_Lock)>::__do_try_lock(__locks);
00625         }
00626       else
00627         {
00628           __unlock_impl<_Idx>::__do_unlock(__locks);
00629           return _Idx;
00630         }
00631     }
00632     };
00633 
00634   template<int _Idx>
00635     struct __try_lock_impl<_Idx, false>
00636     {
00637       template<typename... _Lock>
00638     static int
00639     __do_try_lock(tuple<_Lock&...>& __locks)
00640     {
00641       if(std::get<_Idx>(__locks).try_lock())
00642         return -1;
00643       else
00644         {
00645           __unlock_impl<_Idx>::__do_unlock(__locks);
00646           return _Idx;
00647         }
00648     }
00649     };
00650 
00651   /** @brief Generic try_lock.
00652    *  @param __l1 Meets Mutex requirements (try_lock() may throw).
00653    *  @param __l2 Meets Mutex requirements (try_lock() may throw).
00654    *  @param __l3 Meets Mutex requirements (try_lock() may throw).
00655    *  @return Returns -1 if all try_lock() calls return true. Otherwise returns
00656    *          a 0-based index corresponding to the argument that returned false.
00657    *  @post Either all arguments are locked, or none will be.
00658    *
00659    *  Sequentially calls try_lock() on each argument.
00660    */
00661   template<typename _Lock1, typename _Lock2, typename... _Lock3>
00662     int
00663     try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
00664     {
00665       tuple<_Lock1&, _Lock2&, _Lock3&...> __locks(__l1, __l2, __l3...);
00666       return __try_lock_impl<0>::__do_try_lock(__locks);
00667     }
00668 
00669   /// lock
00670   template<typename _L1, typename _L2, typename ..._L3>
00671     void
00672     lock(_L1&, _L2&, _L3&...);
00673 
00674   /// once_flag
00675   struct once_flag
00676   {
00677   private:
00678     typedef __gthread_once_t __native_type;
00679     __native_type  _M_once;
00680 
00681   public:
00682     once_flag()
00683     {
00684       __native_type __tmp = __GTHREAD_ONCE_INIT;
00685       _M_once = __tmp;
00686     }
00687 
00688     once_flag(const once_flag&) = delete;
00689     once_flag& operator=(const once_flag&) = delete;
00690 
00691     template<typename _Callable, typename... _Args>
00692       friend void
00693       call_once(once_flag& __once, _Callable __f, _Args&&... __args);
00694   };
00695 
00696 #ifdef _GLIBCXX_HAVE_TLS
00697   extern __thread void* __once_callable;
00698   extern __thread void (*__once_call)();
00699 
00700   template<typename _Callable>
00701     inline void
00702     __once_call_impl()
00703     {
00704       (*(_Callable*)__once_callable)();
00705     }
00706 #else
00707   extern function<void()> __once_functor;
00708 
00709   extern void
00710   __set_once_functor_lock_ptr(unique_lock<mutex>*);
00711 
00712   extern mutex&
00713   __get_once_mutex();
00714 #endif
00715 
00716   extern "C" void __once_proxy();
00717 
00718   /// call_once
00719   template<typename _Callable, typename... _Args>
00720     void
00721     call_once(once_flag& __once, _Callable __f, _Args&&... __args)
00722     {
00723 #ifdef _GLIBCXX_HAVE_TLS
00724       auto __bound_functor = std::bind<void>(__f, __args...);
00725       __once_callable = &__bound_functor;
00726       __once_call = &__once_call_impl<decltype(__bound_functor)>;
00727 #else
00728       unique_lock<mutex> __functor_lock(__get_once_mutex());
00729       __once_functor = std::bind<void>(__f, __args...);
00730       __set_once_functor_lock_ptr(&__functor_lock);
00731 #endif
00732 
00733       int __e = __gthread_once(&(__once._M_once), &__once_proxy);
00734 
00735 #ifndef _GLIBCXX_HAVE_TLS
00736       if (__functor_lock)
00737         __set_once_functor_lock_ptr(0);
00738 #endif
00739 
00740       if (__e)
00741     __throw_system_error(__e);
00742     }
00743 
00744   // @} group mutexes
00745 }
00746 
00747 #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
00748 
00749 #endif // __GXX_EXPERIMENTAL_CXX0X__
00750 
00751 #endif // _GLIBCXX_MUTEX