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