Home | History | Annotate | Download | only in include
      1 // <mutex> -*- C++ -*-
      2 
      3 // Copyright (C) 2003-2013 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file include/mutex
     26  *  This is a Standard C++ Library header.
     27  */
     28 
     29 #ifndef _GLIBCXX_MUTEX
     30 #define _GLIBCXX_MUTEX 1
     31 
     32 #pragma GCC system_header
     33 
     34 #if __cplusplus < 201103L
     35 # include <bits/c++0x_warning.h>
     36 #else
     37 
     38 #include <tuple>
     39 #include <chrono>
     40 #include <exception>
     41 #include <type_traits>
     42 #include <functional>
     43 #include <system_error>
     44 #include <bits/functexcept.h>
     45 #include <bits/gthr.h>
     46 #include <bits/move.h> // for std::swap
     47 
     48 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
     49 
     50 namespace std _GLIBCXX_VISIBILITY(default)
     51 {
     52 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     53 
     54 #ifdef _GLIBCXX_HAS_GTHREADS
     55   // Common base class for std::mutex and std::timed_mutex
     56   class __mutex_base
     57   {
     58   protected:
     59     typedef __gthread_mutex_t			__native_type;
     60 
     61 #ifdef __GTHREAD_MUTEX_INIT
     62     __native_type  _M_mutex = __GTHREAD_MUTEX_INIT;
     63 
     64     constexpr __mutex_base() noexcept = default;
     65 #else
     66     __native_type  _M_mutex;
     67 
     68     __mutex_base() noexcept
     69     {
     70       // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
     71       __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
     72     }
     73 
     74     ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); }
     75 #endif
     76 
     77     __mutex_base(const __mutex_base&) = delete;
     78     __mutex_base& operator=(const __mutex_base&) = delete;
     79   };
     80 
     81   // Common base class for std::recursive_mutex and std::timed_recursive_mutex
     82   class __recursive_mutex_base
     83   {
     84   protected:
     85     typedef __gthread_recursive_mutex_t		__native_type;
     86 
     87     __recursive_mutex_base(const __recursive_mutex_base&) = delete;
     88     __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
     89 
     90 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
     91     __native_type  _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
     92 
     93     __recursive_mutex_base() = default;
     94 #else
     95     __native_type  _M_mutex;
     96 
     97     __recursive_mutex_base()
     98     {
     99       // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
    100       __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
    101     }
    102 
    103     ~__recursive_mutex_base()
    104     { __gthread_recursive_mutex_destroy(&_M_mutex); }
    105 #endif
    106   };
    107 
    108   /**
    109    * @defgroup mutexes Mutexes
    110    * @ingroup concurrency
    111    *
    112    * Classes for mutex support.
    113    * @{
    114    */
    115 
    116   /// mutex
    117   class mutex : private __mutex_base
    118   {
    119   public:
    120     typedef __native_type* 			native_handle_type;
    121 
    122 #ifdef __GTHREAD_MUTEX_INIT
    123     constexpr
    124 #endif
    125     mutex() noexcept = default;
    126     ~mutex() = default;
    127 
    128     mutex(const mutex&) = delete;
    129     mutex& operator=(const mutex&) = delete;
    130 
    131     void
    132     lock()
    133     {
    134       int __e = __gthread_mutex_lock(&_M_mutex);
    135 
    136       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
    137       if (__e)
    138 	__throw_system_error(__e);
    139     }
    140 
    141     bool
    142     try_lock() noexcept
    143     {
    144       // XXX EINVAL, EAGAIN, EBUSY
    145       return !__gthread_mutex_trylock(&_M_mutex);
    146     }
    147 
    148     void
    149     unlock()
    150     {
    151       // XXX EINVAL, EAGAIN, EPERM
    152       __gthread_mutex_unlock(&_M_mutex);
    153     }
    154 
    155     native_handle_type
    156     native_handle()
    157     { return &_M_mutex; }
    158   };
    159 
    160   /// recursive_mutex
    161   class recursive_mutex : private __recursive_mutex_base
    162   {
    163   public:
    164     typedef __native_type* 			native_handle_type;
    165 
    166     recursive_mutex() = default;
    167     ~recursive_mutex() = default;
    168 
    169     recursive_mutex(const recursive_mutex&) = delete;
    170     recursive_mutex& operator=(const recursive_mutex&) = delete;
    171 
    172     void
    173     lock()
    174     {
    175       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
    176 
    177       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
    178       if (__e)
    179 	__throw_system_error(__e);
    180     }
    181 
    182     bool
    183     try_lock() noexcept
    184     {
    185       // XXX EINVAL, EAGAIN, EBUSY
    186       return !__gthread_recursive_mutex_trylock(&_M_mutex);
    187     }
    188 
    189     void
    190     unlock()
    191     {
    192       // XXX EINVAL, EAGAIN, EBUSY
    193       __gthread_recursive_mutex_unlock(&_M_mutex);
    194     }
    195 
    196     native_handle_type
    197     native_handle()
    198     { return &_M_mutex; }
    199   };
    200 
    201 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
    202   /// timed_mutex
    203   class timed_mutex : private __mutex_base
    204   {
    205 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
    206     typedef chrono::steady_clock 	  	__clock_t;
    207 #else
    208     typedef chrono::high_resolution_clock 	__clock_t;
    209 #endif
    210 
    211   public:
    212     typedef __native_type* 		  	native_handle_type;
    213 
    214     timed_mutex() = default;
    215     ~timed_mutex() = default;
    216 
    217     timed_mutex(const timed_mutex&) = delete;
    218     timed_mutex& operator=(const timed_mutex&) = delete;
    219 
    220     void
    221     lock()
    222     {
    223       int __e = __gthread_mutex_lock(&_M_mutex);
    224 
    225       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
    226       if (__e)
    227 	__throw_system_error(__e);
    228     }
    229 
    230     bool
    231     try_lock() noexcept
    232     {
    233       // XXX EINVAL, EAGAIN, EBUSY
    234       return !__gthread_mutex_trylock(&_M_mutex);
    235     }
    236 
    237     template <class _Rep, class _Period>
    238       bool
    239       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
    240       { return _M_try_lock_for(__rtime); }
    241 
    242     template <class _Clock, class _Duration>
    243       bool
    244       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
    245       { return _M_try_lock_until(__atime); }
    246 
    247     void
    248     unlock()
    249     {
    250       // XXX EINVAL, EAGAIN, EBUSY
    251       __gthread_mutex_unlock(&_M_mutex);
    252     }
    253 
    254     native_handle_type
    255     native_handle()
    256     { return &_M_mutex; }
    257 
    258   private:
    259     template<typename _Rep, typename _Period>
    260       bool
    261       _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
    262       {
    263 	auto __rt = chrono::duration_cast<__clock_t::duration>(__rtime);
    264 	if (ratio_greater<__clock_t::period, _Period>())
    265 	  ++__rt;
    266 
    267 	return _M_try_lock_until(__clock_t::now() + __rt);
    268       }
    269 
    270     template<typename _Duration>
    271       bool
    272       _M_try_lock_until(const chrono::time_point<__clock_t,
    273 						 _Duration>& __atime)
    274       {
    275 	chrono::time_point<__clock_t, chrono::seconds> __s =
    276 	  chrono::time_point_cast<chrono::seconds>(__atime);
    277 
    278 	chrono::nanoseconds __ns =
    279 	  chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
    280 
    281 	__gthread_time_t __ts = {
    282 	  static_cast<std::time_t>(__s.time_since_epoch().count()),
    283 	  static_cast<long>(__ns.count())
    284 	};
    285 
    286 	return !__gthread_mutex_timedlock(native_handle(), &__ts);
    287       }
    288 
    289     template<typename _Clock, typename _Duration>
    290       bool
    291       _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
    292       { return _M_try_lock_for(__atime - _Clock::now()); }
    293   };
    294 
    295   /// recursive_timed_mutex
    296   class recursive_timed_mutex : private __recursive_mutex_base
    297   {
    298 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
    299     typedef chrono::steady_clock 		__clock_t;
    300 #else
    301     typedef chrono::high_resolution_clock 	__clock_t;
    302 #endif
    303 
    304   public:
    305     typedef __native_type* 			native_handle_type;
    306 
    307     recursive_timed_mutex() = default;
    308     ~recursive_timed_mutex() = default;
    309 
    310     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
    311     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
    312 
    313     void
    314     lock()
    315     {
    316       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
    317 
    318       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
    319       if (__e)
    320 	__throw_system_error(__e);
    321     }
    322 
    323     bool
    324     try_lock() noexcept
    325     {
    326       // XXX EINVAL, EAGAIN, EBUSY
    327       return !__gthread_recursive_mutex_trylock(&_M_mutex);
    328     }
    329 
    330     template <class _Rep, class _Period>
    331       bool
    332       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
    333       { return _M_try_lock_for(__rtime); }
    334 
    335     template <class _Clock, class _Duration>
    336       bool
    337       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
    338       { return _M_try_lock_until(__atime); }
    339 
    340     void
    341     unlock()
    342     {
    343       // XXX EINVAL, EAGAIN, EBUSY
    344       __gthread_recursive_mutex_unlock(&_M_mutex);
    345     }
    346 
    347     native_handle_type
    348     native_handle()
    349     { return &_M_mutex; }
    350 
    351   private:
    352     template<typename _Rep, typename _Period>
    353       bool
    354       _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
    355       {
    356 	auto __rt = chrono::duration_cast<__clock_t::duration>(__rtime);
    357 	if (ratio_greater<__clock_t::period, _Period>())
    358 	  ++__rt;
    359 
    360 	return _M_try_lock_until(__clock_t::now() + __rt);
    361       }
    362 
    363     template<typename _Duration>
    364       bool
    365       _M_try_lock_until(const chrono::time_point<__clock_t,
    366 						 _Duration>& __atime)
    367       {
    368 	chrono::time_point<__clock_t, chrono::seconds> __s =
    369 	  chrono::time_point_cast<chrono::seconds>(__atime);
    370 
    371 	chrono::nanoseconds __ns =
    372 	  chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
    373 
    374 	__gthread_time_t __ts = {
    375 	  static_cast<std::time_t>(__s.time_since_epoch().count()),
    376 	  static_cast<long>(__ns.count())
    377 	};
    378 
    379 	return !__gthread_mutex_timedlock(native_handle(), &__ts);
    380       }
    381 
    382     template<typename _Clock, typename _Duration>
    383       bool
    384       _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
    385       { return _M_try_lock_for(__atime - _Clock::now()); }
    386   };
    387 #endif
    388 #endif // _GLIBCXX_HAS_GTHREADS
    389 
    390   /// Do not acquire ownership of the mutex.
    391   struct defer_lock_t { };
    392 
    393   /// Try to acquire ownership of the mutex without blocking.
    394   struct try_to_lock_t { };
    395 
    396   /// Assume the calling thread has already obtained mutex ownership
    397   /// and manage it.
    398   struct adopt_lock_t { };
    399 
    400   constexpr defer_lock_t	defer_lock { };
    401   constexpr try_to_lock_t	try_to_lock { };
    402   constexpr adopt_lock_t	adopt_lock { };
    403 
    404   /// @brief  Scoped lock idiom.
    405   // Acquire the mutex here with a constructor call, then release with
    406   // the destructor call in accordance with RAII style.
    407   template<typename _Mutex>
    408     class lock_guard
    409     {
    410     public:
    411       typedef _Mutex mutex_type;
    412 
    413       explicit lock_guard(mutex_type& __m) : _M_device(__m)
    414       { _M_device.lock(); }
    415 
    416       lock_guard(mutex_type& __m, adopt_lock_t) : _M_device(__m)
    417       { } // calling thread owns mutex
    418 
    419       ~lock_guard()
    420       { _M_device.unlock(); }
    421 
    422       lock_guard(const lock_guard&) = delete;
    423       lock_guard& operator=(const lock_guard&) = delete;
    424 
    425     private:
    426       mutex_type&  _M_device;
    427     };
    428 
    429   /// unique_lock
    430   template<typename _Mutex>
    431     class unique_lock
    432     {
    433     public:
    434       typedef _Mutex mutex_type;
    435 
    436       unique_lock() noexcept
    437       : _M_device(0), _M_owns(false)
    438       { }
    439 
    440       explicit unique_lock(mutex_type& __m)
    441       : _M_device(&__m), _M_owns(false)
    442       {
    443 	lock();
    444 	_M_owns = true;
    445       }
    446 
    447       unique_lock(mutex_type& __m, defer_lock_t) noexcept
    448       : _M_device(&__m), _M_owns(false)
    449       { }
    450 
    451       unique_lock(mutex_type& __m, try_to_lock_t)
    452       : _M_device(&__m), _M_owns(_M_device->try_lock())
    453       { }
    454 
    455       unique_lock(mutex_type& __m, adopt_lock_t)
    456       : _M_device(&__m), _M_owns(true)
    457       {
    458 	// XXX calling thread owns mutex
    459       }
    460 
    461       template<typename _Clock, typename _Duration>
    462 	unique_lock(mutex_type& __m,
    463 		    const chrono::time_point<_Clock, _Duration>& __atime)
    464 	: _M_device(&__m), _M_owns(_M_device->try_lock_until(__atime))
    465 	{ }
    466 
    467       template<typename _Rep, typename _Period>
    468 	unique_lock(mutex_type& __m,
    469 		    const chrono::duration<_Rep, _Period>& __rtime)
    470 	: _M_device(&__m), _M_owns(_M_device->try_lock_for(__rtime))
    471 	{ }
    472 
    473       ~unique_lock()
    474       {
    475 	if (_M_owns)
    476 	  unlock();
    477       }
    478 
    479       unique_lock(const unique_lock&) = delete;
    480       unique_lock& operator=(const unique_lock&) = delete;
    481 
    482       unique_lock(unique_lock&& __u) noexcept
    483       : _M_device(__u._M_device), _M_owns(__u._M_owns)
    484       {
    485 	__u._M_device = 0;
    486 	__u._M_owns = false;
    487       }
    488 
    489       unique_lock& operator=(unique_lock&& __u) noexcept
    490       {
    491 	if(_M_owns)
    492 	  unlock();
    493 
    494 	unique_lock(std::move(__u)).swap(*this);
    495 
    496 	__u._M_device = 0;
    497 	__u._M_owns = false;
    498 
    499 	return *this;
    500       }
    501 
    502       void
    503       lock()
    504       {
    505 	if (!_M_device)
    506 	  __throw_system_error(int(errc::operation_not_permitted));
    507 	else if (_M_owns)
    508 	  __throw_system_error(int(errc::resource_deadlock_would_occur));
    509 	else
    510 	  {
    511 	    _M_device->lock();
    512 	    _M_owns = true;
    513 	  }
    514       }
    515 
    516       bool
    517       try_lock()
    518       {
    519 	if (!_M_device)
    520 	  __throw_system_error(int(errc::operation_not_permitted));
    521 	else if (_M_owns)
    522 	  __throw_system_error(int(errc::resource_deadlock_would_occur));
    523 	else
    524 	  {
    525 	    _M_owns = _M_device->try_lock();
    526 	    return _M_owns;
    527 	  }
    528       }
    529 
    530       template<typename _Clock, typename _Duration>
    531 	bool
    532 	try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
    533 	{
    534 	  if (!_M_device)
    535 	    __throw_system_error(int(errc::operation_not_permitted));
    536 	  else if (_M_owns)
    537 	    __throw_system_error(int(errc::resource_deadlock_would_occur));
    538 	  else
    539 	    {
    540 	      _M_owns = _M_device->try_lock_until(__atime);
    541 	      return _M_owns;
    542 	    }
    543 	}
    544 
    545       template<typename _Rep, typename _Period>
    546 	bool
    547 	try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
    548 	{
    549 	  if (!_M_device)
    550 	    __throw_system_error(int(errc::operation_not_permitted));
    551 	  else if (_M_owns)
    552 	    __throw_system_error(int(errc::resource_deadlock_would_occur));
    553 	  else
    554 	    {
    555 	      _M_owns = _M_device->try_lock_for(__rtime);
    556 	      return _M_owns;
    557 	    }
    558 	 }
    559 
    560       void
    561       unlock()
    562       {
    563 	if (!_M_owns)
    564 	  __throw_system_error(int(errc::operation_not_permitted));
    565 	else if (_M_device)
    566 	  {
    567 	    _M_device->unlock();
    568 	    _M_owns = false;
    569 	  }
    570       }
    571 
    572       void
    573       swap(unique_lock& __u) noexcept
    574       {
    575 	std::swap(_M_device, __u._M_device);
    576 	std::swap(_M_owns, __u._M_owns);
    577       }
    578 
    579       mutex_type*
    580       release() noexcept
    581       {
    582 	mutex_type* __ret = _M_device;
    583 	_M_device = 0;
    584 	_M_owns = false;
    585 	return __ret;
    586       }
    587 
    588       bool
    589       owns_lock() const noexcept
    590       { return _M_owns; }
    591 
    592       explicit operator bool() const noexcept
    593       { return owns_lock(); }
    594 
    595       mutex_type*
    596       mutex() const noexcept
    597       { return _M_device; }
    598 
    599     private:
    600       mutex_type*	_M_device;
    601       bool		_M_owns; // XXX use atomic_bool
    602     };
    603 
    604   /// Partial specialization for unique_lock objects.
    605   template<typename _Mutex>
    606     inline void
    607     swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
    608     { __x.swap(__y); }
    609 
    610   template<int _Idx>
    611     struct __unlock_impl
    612     {
    613       template<typename... _Lock>
    614 	static void
    615 	__do_unlock(tuple<_Lock&...>& __locks)
    616 	{
    617 	  std::get<_Idx>(__locks).unlock();
    618 	  __unlock_impl<_Idx - 1>::__do_unlock(__locks);
    619 	}
    620     };
    621 
    622   template<>
    623     struct __unlock_impl<-1>
    624     {
    625       template<typename... _Lock>
    626 	static void
    627 	__do_unlock(tuple<_Lock&...>&)
    628 	{ }
    629     };
    630 
    631   template<typename _Lock>
    632     unique_lock<_Lock>
    633     __try_to_lock(_Lock& __l)
    634     { return unique_lock<_Lock>(__l, try_to_lock); }
    635 
    636   template<int _Idx, bool _Continue = true>
    637     struct __try_lock_impl
    638     {
    639       template<typename... _Lock>
    640 	static void
    641 	__do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
    642 	{
    643           __idx = _Idx;
    644           auto __lock = __try_to_lock(std::get<_Idx>(__locks));
    645           if (__lock.owns_lock())
    646             {
    647               __try_lock_impl<_Idx + 1, _Idx + 2 < sizeof...(_Lock)>::
    648                 __do_try_lock(__locks, __idx);
    649               if (__idx == -1)
    650                 __lock.release();
    651             }
    652 	}
    653     };
    654 
    655   template<int _Idx>
    656     struct __try_lock_impl<_Idx, false>
    657     {
    658       template<typename... _Lock>
    659 	static void
    660 	__do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
    661 	{
    662           __idx = _Idx;
    663           auto __lock = __try_to_lock(std::get<_Idx>(__locks));
    664           if (__lock.owns_lock())
    665             {
    666               __idx = -1;
    667               __lock.release();
    668             }
    669 	}
    670     };
    671 
    672   /** @brief Generic try_lock.
    673    *  @param __l1 Meets Mutex requirements (try_lock() may throw).
    674    *  @param __l2 Meets Mutex requirements (try_lock() may throw).
    675    *  @param __l3 Meets Mutex requirements (try_lock() may throw).
    676    *  @return Returns -1 if all try_lock() calls return true. Otherwise returns
    677    *          a 0-based index corresponding to the argument that returned false.
    678    *  @post Either all arguments are locked, or none will be.
    679    *
    680    *  Sequentially calls try_lock() on each argument.
    681    */
    682   template<typename _Lock1, typename _Lock2, typename... _Lock3>
    683     int
    684     try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
    685     {
    686       int __idx;
    687       auto __locks = std::tie(__l1, __l2, __l3...);
    688       __try
    689       { __try_lock_impl<0>::__do_try_lock(__locks, __idx); }
    690       __catch(...)
    691       { }
    692       return __idx;
    693     }
    694 
    695   /** @brief Generic lock.
    696    *  @param __l1 Meets Mutex requirements (try_lock() may throw).
    697    *  @param __l2 Meets Mutex requirements (try_lock() may throw).
    698    *  @param __l3 Meets Mutex requirements (try_lock() may throw).
    699    *  @throw An exception thrown by an argument's lock() or try_lock() member.
    700    *  @post All arguments are locked.
    701    *
    702    *  All arguments are locked via a sequence of calls to lock(), try_lock()
    703    *  and unlock().  If the call exits via an exception any locks that were
    704    *  obtained will be released.
    705    */
    706   template<typename _L1, typename _L2, typename ..._L3>
    707     void
    708     lock(_L1& __l1, _L2& __l2, _L3&... __l3)
    709     {
    710       while (true)
    711         {
    712           unique_lock<_L1> __first(__l1);
    713           int __idx;
    714           auto __locks = std::tie(__l2, __l3...);
    715           __try_lock_impl<0, sizeof...(_L3)>::__do_try_lock(__locks, __idx);
    716           if (__idx == -1)
    717             {
    718               __first.release();
    719               return;
    720             }
    721         }
    722     }
    723 
    724 #ifdef _GLIBCXX_HAS_GTHREADS
    725   /// once_flag
    726   struct once_flag
    727   {
    728   private:
    729     typedef __gthread_once_t __native_type;
    730     __native_type  _M_once = __GTHREAD_ONCE_INIT;
    731 
    732   public:
    733     /// Constructor
    734     constexpr once_flag() noexcept = default;
    735 
    736     /// Deleted copy constructor
    737     once_flag(const once_flag&) = delete;
    738     /// Deleted assignment operator
    739     once_flag& operator=(const once_flag&) = delete;
    740 
    741     template<typename _Callable, typename... _Args>
    742       friend void
    743       call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
    744   };
    745 
    746 #ifdef _GLIBCXX_HAVE_TLS
    747   extern __thread void* __once_callable;
    748   extern __thread void (*__once_call)();
    749 
    750   template<typename _Callable>
    751     inline void
    752     __once_call_impl()
    753     {
    754       (*(_Callable*)__once_callable)();
    755     }
    756 #else
    757   extern function<void()> __once_functor;
    758 
    759   extern void
    760   __set_once_functor_lock_ptr(unique_lock<mutex>*);
    761 
    762   extern mutex&
    763   __get_once_mutex();
    764 #endif
    765 
    766   extern "C" void __once_proxy(void);
    767 
    768   /// call_once
    769   template<typename _Callable, typename... _Args>
    770     void
    771     call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
    772     {
    773 #ifdef _GLIBCXX_HAVE_TLS
    774       auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f),
    775           std::forward<_Args>(__args)...);
    776       __once_callable = &__bound_functor;
    777       __once_call = &__once_call_impl<decltype(__bound_functor)>;
    778 #else
    779       unique_lock<mutex> __functor_lock(__get_once_mutex());
    780       auto __callable = std::__bind_simple(std::forward<_Callable>(__f),
    781           std::forward<_Args>(__args)...);
    782       __once_functor = [&]() { __callable(); };
    783       __set_once_functor_lock_ptr(&__functor_lock);
    784 #endif
    785 
    786       int __e = __gthread_once(&(__once._M_once), &__once_proxy);
    787 
    788 #ifndef _GLIBCXX_HAVE_TLS
    789       if (__functor_lock)
    790         __set_once_functor_lock_ptr(0);
    791 #endif
    792 
    793       if (__e)
    794 	__throw_system_error(__e);
    795     }
    796 #endif // _GLIBCXX_HAS_GTHREADS
    797 
    798   // @} group mutexes
    799 _GLIBCXX_END_NAMESPACE_VERSION
    800 } // namespace
    801 #endif // _GLIBCXX_USE_C99_STDINT_TR1
    802 
    803 #endif // C++11
    804 
    805 #endif // _GLIBCXX_MUTEX
    806