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