Home | History | Annotate | Line # | Download | only in std
      1 // <mutex> -*- C++ -*-
      2 
      3 // Copyright (C) 2003-2022 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 <exception>
     40 #include <type_traits>
     41 #include <system_error>
     42 #include <bits/chrono.h>
     43 #include <bits/std_mutex.h>
     44 #include <bits/unique_lock.h>
     45 #if ! _GTHREAD_USE_MUTEX_TIMEDLOCK
     46 # include <condition_variable>
     47 # include <thread>
     48 #endif
     49 #include <ext/atomicity.h>     // __gnu_cxx::__is_single_threaded
     50 
     51 #if defined _GLIBCXX_HAS_GTHREADS && ! defined _GLIBCXX_HAVE_TLS
     52 # include <bits/std_function.h>  // std::function
     53 #endif
     54 
     55 namespace std _GLIBCXX_VISIBILITY(default)
     56 {
     57 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     58 
     59   /**
     60    * @addtogroup mutexes
     61    * @{
     62    */
     63 
     64 #ifdef _GLIBCXX_HAS_GTHREADS
     65   /// @cond undocumented
     66 
     67   // Common base class for std::recursive_mutex and std::recursive_timed_mutex
     68   class __recursive_mutex_base
     69   {
     70   protected:
     71     typedef __gthread_recursive_mutex_t		__native_type;
     72 
     73     __recursive_mutex_base(const __recursive_mutex_base&) = delete;
     74     __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
     75 
     76 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
     77     __native_type  _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
     78 
     79     __recursive_mutex_base() = default;
     80 #else
     81     __native_type  _M_mutex;
     82 
     83     __recursive_mutex_base()
     84     {
     85       // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
     86       __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
     87     }
     88 
     89     ~__recursive_mutex_base()
     90     { __gthread_recursive_mutex_destroy(&_M_mutex); }
     91 #endif
     92   };
     93   /// @endcond
     94 
     95   /** The standard recursive mutex type.
     96    *
     97    * A recursive mutex can be locked more than once by the same thread.
     98    * Other threads cannot lock the mutex until the owning thread unlocks it
     99    * as many times as it was locked.
    100    *
    101    * @headerfile mutex
    102    * @since C++11
    103    */
    104   class recursive_mutex : private __recursive_mutex_base
    105   {
    106   public:
    107     typedef __native_type* 			native_handle_type;
    108 
    109     recursive_mutex() = default;
    110     ~recursive_mutex() = default;
    111 
    112     recursive_mutex(const recursive_mutex&) = delete;
    113     recursive_mutex& operator=(const recursive_mutex&) = delete;
    114 
    115     void
    116     lock()
    117     {
    118       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
    119 
    120       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
    121       if (__e)
    122 	__throw_system_error(__e);
    123     }
    124 
    125     bool
    126     try_lock() noexcept
    127     {
    128       // XXX EINVAL, EAGAIN, EBUSY
    129       return !__gthread_recursive_mutex_trylock(&_M_mutex);
    130     }
    131 
    132     void
    133     unlock()
    134     {
    135       // XXX EINVAL, EAGAIN, EBUSY
    136       __gthread_recursive_mutex_unlock(&_M_mutex);
    137     }
    138 
    139     native_handle_type
    140     native_handle() noexcept
    141     { return &_M_mutex; }
    142   };
    143 
    144 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
    145   /// @cond undocumented
    146 
    147   template<typename _Derived>
    148     class __timed_mutex_impl
    149     {
    150     protected:
    151       template<typename _Rep, typename _Period>
    152 	bool
    153 	_M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
    154 	{
    155 #if _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
    156 	  using __clock = chrono::steady_clock;
    157 #else
    158 	  using __clock = chrono::system_clock;
    159 #endif
    160 
    161 	  auto __rt = chrono::duration_cast<__clock::duration>(__rtime);
    162 	  if (ratio_greater<__clock::period, _Period>())
    163 	    ++__rt;
    164 	  return _M_try_lock_until(__clock::now() + __rt);
    165 	}
    166 
    167       template<typename _Duration>
    168 	bool
    169 	_M_try_lock_until(const chrono::time_point<chrono::system_clock,
    170 						   _Duration>& __atime)
    171 	{
    172 	  auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
    173 	  auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
    174 
    175 	  __gthread_time_t __ts = {
    176 	    static_cast<std::time_t>(__s.time_since_epoch().count()),
    177 	    static_cast<long>(__ns.count())
    178 	  };
    179 
    180 	  return static_cast<_Derived*>(this)->_M_timedlock(__ts);
    181 	}
    182 
    183 #ifdef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
    184       template<typename _Duration>
    185 	bool
    186 	_M_try_lock_until(const chrono::time_point<chrono::steady_clock,
    187 						   _Duration>& __atime)
    188 	{
    189 	  auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
    190 	  auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
    191 
    192 	  __gthread_time_t __ts = {
    193 	    static_cast<std::time_t>(__s.time_since_epoch().count()),
    194 	    static_cast<long>(__ns.count())
    195 	  };
    196 
    197 	  return static_cast<_Derived*>(this)->_M_clocklock(CLOCK_MONOTONIC,
    198 							    __ts);
    199 	}
    200 #endif
    201 
    202       template<typename _Clock, typename _Duration>
    203 	bool
    204 	_M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
    205 	{
    206 #if __cplusplus > 201703L
    207 	  static_assert(chrono::is_clock_v<_Clock>);
    208 #endif
    209 	  // The user-supplied clock may not tick at the same rate as
    210 	  // steady_clock, so we must loop in order to guarantee that
    211 	  // the timeout has expired before returning false.
    212 	  auto __now = _Clock::now();
    213 	  do {
    214 	    auto __rtime = __atime - __now;
    215 	    if (_M_try_lock_for(__rtime))
    216 	      return true;
    217 	    __now = _Clock::now();
    218 	  } while (__atime > __now);
    219 	  return false;
    220 	}
    221     };
    222   /// @endcond
    223 
    224   /** The standard timed mutex type.
    225    *
    226    * A non-recursive mutex that supports a timeout when trying to acquire the
    227    * lock.
    228    *
    229    * @headerfile mutex
    230    * @since C++11
    231    */
    232   class timed_mutex
    233   : private __mutex_base, public __timed_mutex_impl<timed_mutex>
    234   {
    235   public:
    236     typedef __native_type* 		  	native_handle_type;
    237 
    238     timed_mutex() = default;
    239     ~timed_mutex() = default;
    240 
    241     timed_mutex(const timed_mutex&) = delete;
    242     timed_mutex& operator=(const timed_mutex&) = delete;
    243 
    244     void
    245     lock()
    246     {
    247       int __e = __gthread_mutex_lock(&_M_mutex);
    248 
    249       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
    250       if (__e)
    251 	__throw_system_error(__e);
    252     }
    253 
    254     bool
    255     try_lock() noexcept
    256     {
    257       // XXX EINVAL, EAGAIN, EBUSY
    258       return !__gthread_mutex_trylock(&_M_mutex);
    259     }
    260 
    261     template <class _Rep, class _Period>
    262       bool
    263       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
    264       { return _M_try_lock_for(__rtime); }
    265 
    266     template <class _Clock, class _Duration>
    267       bool
    268       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
    269       { return _M_try_lock_until(__atime); }
    270 
    271     void
    272     unlock()
    273     {
    274       // XXX EINVAL, EAGAIN, EBUSY
    275       __gthread_mutex_unlock(&_M_mutex);
    276     }
    277 
    278     native_handle_type
    279     native_handle() noexcept
    280     { return &_M_mutex; }
    281 
    282     private:
    283       friend class __timed_mutex_impl<timed_mutex>;
    284 
    285       bool
    286       _M_timedlock(const __gthread_time_t& __ts)
    287       { return !__gthread_mutex_timedlock(&_M_mutex, &__ts); }
    288 
    289 #if _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
    290       bool
    291       _M_clocklock(clockid_t __clockid, const __gthread_time_t& __ts)
    292       { return !pthread_mutex_clocklock(&_M_mutex, __clockid, &__ts); }
    293 #endif
    294   };
    295 
    296   /** The standard recursive timed mutex type.
    297    *
    298    * A recursive mutex that supports a timeout when trying to acquire the
    299    * lock. A recursive mutex can be locked more than once by the same thread.
    300    * Other threads cannot lock the mutex until the owning thread unlocks it
    301    * as many times as it was locked.
    302    *
    303    * @headerfile mutex
    304    * @since C++11
    305    */
    306   class recursive_timed_mutex
    307   : private __recursive_mutex_base,
    308     public __timed_mutex_impl<recursive_timed_mutex>
    309   {
    310   public:
    311     typedef __native_type* 			native_handle_type;
    312 
    313     recursive_timed_mutex() = default;
    314     ~recursive_timed_mutex() = default;
    315 
    316     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
    317     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
    318 
    319     void
    320     lock()
    321     {
    322       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
    323 
    324       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
    325       if (__e)
    326 	__throw_system_error(__e);
    327     }
    328 
    329     bool
    330     try_lock() noexcept
    331     {
    332       // XXX EINVAL, EAGAIN, EBUSY
    333       return !__gthread_recursive_mutex_trylock(&_M_mutex);
    334     }
    335 
    336     template <class _Rep, class _Period>
    337       bool
    338       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
    339       { return _M_try_lock_for(__rtime); }
    340 
    341     template <class _Clock, class _Duration>
    342       bool
    343       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
    344       { return _M_try_lock_until(__atime); }
    345 
    346     void
    347     unlock()
    348     {
    349       // XXX EINVAL, EAGAIN, EBUSY
    350       __gthread_recursive_mutex_unlock(&_M_mutex);
    351     }
    352 
    353     native_handle_type
    354     native_handle() noexcept
    355     { return &_M_mutex; }
    356 
    357     private:
    358       friend class __timed_mutex_impl<recursive_timed_mutex>;
    359 
    360       bool
    361       _M_timedlock(const __gthread_time_t& __ts)
    362       { return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); }
    363 
    364 #ifdef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
    365       bool
    366       _M_clocklock(clockid_t __clockid, const __gthread_time_t& __ts)
    367       { return !pthread_mutex_clocklock(&_M_mutex, __clockid, &__ts); }
    368 #endif
    369   };
    370 
    371 #else // !_GTHREAD_USE_MUTEX_TIMEDLOCK
    372 
    373   /// timed_mutex
    374   class timed_mutex
    375   {
    376     mutex		_M_mut;
    377     condition_variable	_M_cv;
    378     bool		_M_locked = false;
    379 
    380   public:
    381 
    382     timed_mutex() = default;
    383     ~timed_mutex() { __glibcxx_assert( !_M_locked ); }
    384 
    385     timed_mutex(const timed_mutex&) = delete;
    386     timed_mutex& operator=(const timed_mutex&) = delete;
    387 
    388     void
    389     lock()
    390     {
    391       unique_lock<mutex> __lk(_M_mut);
    392       _M_cv.wait(__lk, [&]{ return !_M_locked; });
    393       _M_locked = true;
    394     }
    395 
    396     bool
    397     try_lock()
    398     {
    399       lock_guard<mutex> __lk(_M_mut);
    400       if (_M_locked)
    401 	return false;
    402       _M_locked = true;
    403       return true;
    404     }
    405 
    406     template<typename _Rep, typename _Period>
    407       bool
    408       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
    409       {
    410 	unique_lock<mutex> __lk(_M_mut);
    411 	if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; }))
    412 	  return false;
    413 	_M_locked = true;
    414 	return true;
    415       }
    416 
    417     template<typename _Clock, typename _Duration>
    418       bool
    419       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
    420       {
    421 	unique_lock<mutex> __lk(_M_mut);
    422 	if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; }))
    423 	  return false;
    424 	_M_locked = true;
    425 	return true;
    426       }
    427 
    428     void
    429     unlock()
    430     {
    431       lock_guard<mutex> __lk(_M_mut);
    432       __glibcxx_assert( _M_locked );
    433       _M_locked = false;
    434       _M_cv.notify_one();
    435     }
    436   };
    437 
    438   /// recursive_timed_mutex
    439   class recursive_timed_mutex
    440   {
    441     mutex		_M_mut;
    442     condition_variable	_M_cv;
    443     thread::id		_M_owner;
    444     unsigned		_M_count = 0;
    445 
    446     // Predicate type that tests whether the current thread can lock a mutex.
    447     struct _Can_lock
    448     {
    449       // Returns true if the mutex is unlocked or is locked by _M_caller.
    450       bool
    451       operator()() const noexcept
    452       { return _M_mx->_M_count == 0 || _M_mx->_M_owner == _M_caller; }
    453 
    454       const recursive_timed_mutex* _M_mx;
    455       thread::id _M_caller;
    456     };
    457 
    458   public:
    459 
    460     recursive_timed_mutex() = default;
    461     ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); }
    462 
    463     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
    464     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
    465 
    466     void
    467     lock()
    468     {
    469       auto __id = this_thread::get_id();
    470       _Can_lock __can_lock{this, __id};
    471       unique_lock<mutex> __lk(_M_mut);
    472       _M_cv.wait(__lk, __can_lock);
    473       if (_M_count == -1u)
    474 	__throw_system_error(EAGAIN); // [thread.timedmutex.recursive]/3
    475       _M_owner = __id;
    476       ++_M_count;
    477     }
    478 
    479     bool
    480     try_lock()
    481     {
    482       auto __id = this_thread::get_id();
    483       _Can_lock __can_lock{this, __id};
    484       lock_guard<mutex> __lk(_M_mut);
    485       if (!__can_lock())
    486 	return false;
    487       if (_M_count == -1u)
    488 	return false;
    489       _M_owner = __id;
    490       ++_M_count;
    491       return true;
    492     }
    493 
    494     template<typename _Rep, typename _Period>
    495       bool
    496       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
    497       {
    498 	auto __id = this_thread::get_id();
    499 	_Can_lock __can_lock{this, __id};
    500 	unique_lock<mutex> __lk(_M_mut);
    501 	if (!_M_cv.wait_for(__lk, __rtime, __can_lock))
    502 	  return false;
    503 	if (_M_count == -1u)
    504 	  return false;
    505 	_M_owner = __id;
    506 	++_M_count;
    507 	return true;
    508       }
    509 
    510     template<typename _Clock, typename _Duration>
    511       bool
    512       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
    513       {
    514 	auto __id = this_thread::get_id();
    515 	_Can_lock __can_lock{this, __id};
    516 	unique_lock<mutex> __lk(_M_mut);
    517 	if (!_M_cv.wait_until(__lk, __atime, __can_lock))
    518 	  return false;
    519 	if (_M_count == -1u)
    520 	  return false;
    521 	_M_owner = __id;
    522 	++_M_count;
    523 	return true;
    524       }
    525 
    526     void
    527     unlock()
    528     {
    529       lock_guard<mutex> __lk(_M_mut);
    530       __glibcxx_assert( _M_owner == this_thread::get_id() );
    531       __glibcxx_assert( _M_count > 0 );
    532       if (--_M_count == 0)
    533 	{
    534 	  _M_owner = {};
    535 	  _M_cv.notify_one();
    536 	}
    537     }
    538   };
    539 
    540 #endif
    541 #endif // _GLIBCXX_HAS_GTHREADS
    542 
    543   /// @cond undocumented
    544   namespace __detail
    545   {
    546     // Lock the last lockable, after all previous ones are locked.
    547     template<typename _Lockable>
    548       inline int
    549       __try_lock_impl(_Lockable& __l)
    550       {
    551 	if (unique_lock<_Lockable> __lock{__l, try_to_lock})
    552 	  {
    553 	    __lock.release();
    554 	    return -1;
    555 	  }
    556 	else
    557 	  return 0;
    558       }
    559 
    560     // Lock each lockable in turn.
    561     // Use iteration if all lockables are the same type, recursion otherwise.
    562     template<typename _L0, typename... _Lockables>
    563       inline int
    564       __try_lock_impl(_L0& __l0, _Lockables&... __lockables)
    565       {
    566 #if __cplusplus >= 201703L
    567 	if constexpr ((is_same_v<_L0, _Lockables> && ...))
    568 	  {
    569 	    constexpr int _Np = 1 + sizeof...(_Lockables);
    570 	    unique_lock<_L0> __locks[_Np] = {
    571 		{__l0, defer_lock}, {__lockables, defer_lock}...
    572 	    };
    573 	    for (int __i = 0; __i < _Np; ++__i)
    574 	      {
    575 		if (!__locks[__i].try_lock())
    576 		  {
    577 		    const int __failed = __i;
    578 		    while (__i--)
    579 		      __locks[__i].unlock();
    580 		    return __failed;
    581 		  }
    582 	      }
    583 	    for (auto& __l : __locks)
    584 	      __l.release();
    585 	    return -1;
    586 	  }
    587 	else
    588 #endif
    589 	if (unique_lock<_L0> __lock{__l0, try_to_lock})
    590 	  {
    591 	    int __idx = __detail::__try_lock_impl(__lockables...);
    592 	    if (__idx == -1)
    593 	      {
    594 		__lock.release();
    595 		return -1;
    596 	      }
    597 	    return __idx + 1;
    598 	  }
    599 	else
    600 	  return 0;
    601       }
    602 
    603   } // namespace __detail
    604   /// @endcond
    605 
    606   /** @brief Generic try_lock.
    607    *  @param __l1 Meets Lockable requirements (try_lock() may throw).
    608    *  @param __l2 Meets Lockable requirements (try_lock() may throw).
    609    *  @param __l3 Meets Lockable requirements (try_lock() may throw).
    610    *  @return Returns -1 if all try_lock() calls return true. Otherwise returns
    611    *          a 0-based index corresponding to the argument that returned false.
    612    *  @post Either all arguments are locked, or none will be.
    613    *
    614    *  Sequentially calls try_lock() on each argument.
    615    */
    616   template<typename _L1, typename _L2, typename... _L3>
    617     inline int
    618     try_lock(_L1& __l1, _L2& __l2, _L3&... __l3)
    619     {
    620       return __detail::__try_lock_impl(__l1, __l2, __l3...);
    621     }
    622 
    623   /// @cond undocumented
    624   namespace __detail
    625   {
    626     // This function can recurse up to N levels deep, for N = 1+sizeof...(L1).
    627     // On each recursion the lockables are rotated left one position,
    628     // e.g. depth 0: l0, l1, l2; depth 1: l1, l2, l0; depth 2: l2, l0, l1.
    629     // When a call to l_i.try_lock() fails it recurses/returns to depth=i
    630     // so that l_i is the first argument, and then blocks until l_i is locked.
    631     template<typename _L0, typename... _L1>
    632       void
    633       __lock_impl(int& __i, int __depth, _L0& __l0, _L1&... __l1)
    634       {
    635 	while (__i >= __depth)
    636 	  {
    637 	    if (__i == __depth)
    638 	      {
    639 		int __failed = 1; // index that couldn't be locked
    640 		{
    641 		  unique_lock<_L0> __first(__l0);
    642 		  __failed += __detail::__try_lock_impl(__l1...);
    643 		  if (!__failed)
    644 		    {
    645 		      __i = -1; // finished
    646 		      __first.release();
    647 		      return;
    648 		    }
    649 		}
    650 #if defined _GLIBCXX_HAS_GTHREADS && defined _GLIBCXX_USE_SCHED_YIELD
    651 		__gthread_yield();
    652 #endif
    653 		constexpr auto __n = 1 + sizeof...(_L1);
    654 		__i = (__depth + __failed) % __n;
    655 	      }
    656 	    else // rotate left until l_i is first.
    657 	      __detail::__lock_impl(__i, __depth + 1, __l1..., __l0);
    658 	  }
    659       }
    660 
    661   } // namespace __detail
    662   /// @endcond
    663 
    664   /** @brief Generic lock.
    665    *  @param __l1 Meets Lockable requirements (try_lock() may throw).
    666    *  @param __l2 Meets Lockable requirements (try_lock() may throw).
    667    *  @param __l3 Meets Lockable requirements (try_lock() may throw).
    668    *  @throw An exception thrown by an argument's lock() or try_lock() member.
    669    *  @post All arguments are locked.
    670    *
    671    *  All arguments are locked via a sequence of calls to lock(), try_lock()
    672    *  and unlock().  If this function exits via an exception any locks that
    673    *  were obtained will be released.
    674    */
    675   template<typename _L1, typename _L2, typename... _L3>
    676     void
    677     lock(_L1& __l1, _L2& __l2, _L3&... __l3)
    678     {
    679 #if __cplusplus >= 201703L
    680       if constexpr (is_same_v<_L1, _L2> && (is_same_v<_L1, _L3> && ...))
    681 	{
    682 	  constexpr int _Np = 2 + sizeof...(_L3);
    683 	  unique_lock<_L1> __locks[] = {
    684 	      {__l1, defer_lock}, {__l2, defer_lock}, {__l3, defer_lock}...
    685 	  };
    686 	  int __first = 0;
    687 	  do {
    688 	    __locks[__first].lock();
    689 	    for (int __j = 1; __j < _Np; ++__j)
    690 	      {
    691 		const int __idx = (__first + __j) % _Np;
    692 		if (!__locks[__idx].try_lock())
    693 		  {
    694 		    for (int __k = __j; __k != 0; --__k)
    695 		      __locks[(__first + __k - 1) % _Np].unlock();
    696 		    __first = __idx;
    697 		    break;
    698 		  }
    699 	      }
    700 	  } while (!__locks[__first].owns_lock());
    701 
    702 	  for (auto& __l : __locks)
    703 	    __l.release();
    704 	}
    705       else
    706 #endif
    707 	{
    708 	  int __i = 0;
    709 	  __detail::__lock_impl(__i, 0, __l1, __l2, __l3...);
    710 	}
    711     }
    712 
    713 #if __cplusplus >= 201703L
    714 #define __cpp_lib_scoped_lock 201703L
    715   /** @brief A scoped lock type for multiple lockable objects.
    716    *
    717    * A scoped_lock controls mutex ownership within a scope, releasing
    718    * ownership in the destructor.
    719    *
    720    * @headerfile mutex
    721    * @since C++17
    722    */
    723   template<typename... _MutexTypes>
    724     class scoped_lock
    725     {
    726     public:
    727       explicit scoped_lock(_MutexTypes&... __m) : _M_devices(std::tie(__m...))
    728       { std::lock(__m...); }
    729 
    730       explicit scoped_lock(adopt_lock_t, _MutexTypes&... __m) noexcept
    731       : _M_devices(std::tie(__m...))
    732       { } // calling thread owns mutex
    733 
    734       ~scoped_lock()
    735       { std::apply([](auto&... __m) { (__m.unlock(), ...); }, _M_devices); }
    736 
    737       scoped_lock(const scoped_lock&) = delete;
    738       scoped_lock& operator=(const scoped_lock&) = delete;
    739 
    740     private:
    741       tuple<_MutexTypes&...> _M_devices;
    742     };
    743 
    744   template<>
    745     class scoped_lock<>
    746     {
    747     public:
    748       explicit scoped_lock() = default;
    749       explicit scoped_lock(adopt_lock_t) noexcept { }
    750       ~scoped_lock() = default;
    751 
    752       scoped_lock(const scoped_lock&) = delete;
    753       scoped_lock& operator=(const scoped_lock&) = delete;
    754     };
    755 
    756   template<typename _Mutex>
    757     class scoped_lock<_Mutex>
    758     {
    759     public:
    760       using mutex_type = _Mutex;
    761 
    762       explicit scoped_lock(mutex_type& __m) : _M_device(__m)
    763       { _M_device.lock(); }
    764 
    765       explicit scoped_lock(adopt_lock_t, mutex_type& __m) noexcept
    766       : _M_device(__m)
    767       { } // calling thread owns mutex
    768 
    769       ~scoped_lock()
    770       { _M_device.unlock(); }
    771 
    772       scoped_lock(const scoped_lock&) = delete;
    773       scoped_lock& operator=(const scoped_lock&) = delete;
    774 
    775     private:
    776       mutex_type&  _M_device;
    777     };
    778 #endif // C++17
    779 
    780 #ifdef _GLIBCXX_HAS_GTHREADS
    781   /// Flag type used by std::call_once
    782   struct once_flag
    783   {
    784     constexpr once_flag() noexcept = default;
    785 
    786     /// Deleted copy constructor
    787     once_flag(const once_flag&) = delete;
    788     /// Deleted assignment operator
    789     once_flag& operator=(const once_flag&) = delete;
    790 
    791   private:
    792     // For gthreads targets a pthread_once_t is used with pthread_once, but
    793     // for most targets this doesn't work correctly for exceptional executions.
    794     __gthread_once_t _M_once = __GTHREAD_ONCE_INIT;
    795 
    796     struct _Prepare_execution;
    797 
    798     template<typename _Callable, typename... _Args>
    799       friend void
    800       call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
    801   };
    802 
    803   /// @cond undocumented
    804 # ifdef _GLIBCXX_HAVE_TLS
    805   // If TLS is available use thread-local state for the type-erased callable
    806   // that is being run by std::call_once in the current thread.
    807   extern __thread void* __once_callable;
    808   extern __thread void (*__once_call)();
    809 
    810   // RAII type to set up state for pthread_once call.
    811   struct once_flag::_Prepare_execution
    812   {
    813     template<typename _Callable>
    814       explicit
    815       _Prepare_execution(_Callable& __c)
    816       {
    817 	// Store address in thread-local pointer:
    818 	__once_callable = std::__addressof(__c);
    819 	// Trampoline function to invoke the closure via thread-local pointer:
    820 	__once_call = [] { (*static_cast<_Callable*>(__once_callable))(); };
    821       }
    822 
    823     ~_Prepare_execution()
    824     {
    825       // PR libstdc++/82481
    826       __once_callable = nullptr;
    827       __once_call = nullptr;
    828     }
    829 
    830     _Prepare_execution(const _Prepare_execution&) = delete;
    831     _Prepare_execution& operator=(const _Prepare_execution&) = delete;
    832   };
    833 
    834 # else
    835   // Without TLS use a global std::mutex and store the callable in a
    836   // global std::function.
    837   extern function<void()> __once_functor;
    838 
    839   extern void
    840   __set_once_functor_lock_ptr(unique_lock<mutex>*);
    841 
    842   extern mutex&
    843   __get_once_mutex();
    844 
    845   // RAII type to set up state for pthread_once call.
    846   struct once_flag::_Prepare_execution
    847   {
    848     template<typename _Callable>
    849       explicit
    850       _Prepare_execution(_Callable& __c)
    851       {
    852 	// Store the callable in the global std::function
    853 	__once_functor = __c;
    854 	__set_once_functor_lock_ptr(&_M_functor_lock);
    855       }
    856 
    857     ~_Prepare_execution()
    858     {
    859       if (_M_functor_lock)
    860 	__set_once_functor_lock_ptr(nullptr);
    861     }
    862 
    863   private:
    864     // XXX This deadlocks if used recursively (PR 97949)
    865     unique_lock<mutex> _M_functor_lock{__get_once_mutex()};
    866 
    867     _Prepare_execution(const _Prepare_execution&) = delete;
    868     _Prepare_execution& operator=(const _Prepare_execution&) = delete;
    869   };
    870 # endif
    871   /// @endcond
    872 
    873   // This function is passed to pthread_once by std::call_once.
    874   // It runs __once_call() or __once_functor().
    875   extern "C" void __once_proxy(void);
    876 
    877   /// Invoke a callable and synchronize with other calls using the same flag
    878   template<typename _Callable, typename... _Args>
    879     void
    880     call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
    881     {
    882       // Closure type that runs the function
    883       auto __callable = [&] {
    884 	  std::__invoke(std::forward<_Callable>(__f),
    885 			std::forward<_Args>(__args)...);
    886       };
    887 
    888       once_flag::_Prepare_execution __exec(__callable);
    889 
    890       // XXX pthread_once does not reset the flag if an exception is thrown.
    891       if (int __e = __gthread_once(&__once._M_once, &__once_proxy))
    892 	__throw_system_error(__e);
    893     }
    894 
    895 #else // _GLIBCXX_HAS_GTHREADS
    896 
    897   /// Flag type used by std::call_once
    898   struct once_flag
    899   {
    900     constexpr once_flag() noexcept = default;
    901 
    902     /// Deleted copy constructor
    903     once_flag(const once_flag&) = delete;
    904     /// Deleted assignment operator
    905     once_flag& operator=(const once_flag&) = delete;
    906 
    907   private:
    908     // There are two different std::once_flag interfaces, abstracting four
    909     // different implementations.
    910     // The single-threaded interface uses the _M_activate() and _M_finish(bool)
    911     // functions, which start and finish an active execution respectively.
    912     // See [thread.once.callonce] in C++11 for the definition of
    913     // active/passive/returning/exceptional executions.
    914     enum _Bits : int { _Init = 0, _Active = 1, _Done = 2 };
    915 
    916     int _M_once = _Bits::_Init;
    917 
    918     // Check to see if all executions will be passive now.
    919     bool
    920     _M_passive() const noexcept;
    921 
    922     // Attempts to begin an active execution.
    923     bool _M_activate();
    924 
    925     // Must be called to complete an active execution.
    926     // The argument is true if the active execution was a returning execution,
    927     // false if it was an exceptional execution.
    928     void _M_finish(bool __returning) noexcept;
    929 
    930     // RAII helper to call _M_finish.
    931     struct _Active_execution
    932     {
    933       explicit _Active_execution(once_flag& __flag) : _M_flag(__flag) { }
    934 
    935       ~_Active_execution() { _M_flag._M_finish(_M_returning); }
    936 
    937       _Active_execution(const _Active_execution&) = delete;
    938       _Active_execution& operator=(const _Active_execution&) = delete;
    939 
    940       once_flag& _M_flag;
    941       bool _M_returning = false;
    942     };
    943 
    944     template<typename _Callable, typename... _Args>
    945       friend void
    946       call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
    947   };
    948 
    949   // Inline definitions of std::once_flag members for single-threaded targets.
    950 
    951   inline bool
    952   once_flag::_M_passive() const noexcept
    953   { return _M_once == _Bits::_Done; }
    954 
    955   inline bool
    956   once_flag::_M_activate()
    957   {
    958     if (_M_once == _Bits::_Init) [[__likely__]]
    959       {
    960 	_M_once = _Bits::_Active;
    961 	return true;
    962       }
    963     else if (_M_passive()) // Caller should have checked this already.
    964       return false;
    965     else
    966       __throw_system_error(EDEADLK);
    967   }
    968 
    969   inline void
    970   once_flag::_M_finish(bool __returning) noexcept
    971   { _M_once = __returning ? _Bits::_Done : _Bits::_Init; }
    972 
    973   /// Invoke a callable and synchronize with other calls using the same flag
    974   template<typename _Callable, typename... _Args>
    975     inline void
    976     call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
    977     {
    978       if (__once._M_passive())
    979 	return;
    980       else if (__once._M_activate())
    981 	{
    982 	  once_flag::_Active_execution __exec(__once);
    983 
    984 	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
    985 	  // 2442. call_once() shouldn't DECAY_COPY()
    986 	  std::__invoke(std::forward<_Callable>(__f),
    987 			std::forward<_Args>(__args)...);
    988 
    989 	  // __f(__args...) did not throw
    990 	  __exec._M_returning = true;
    991 	}
    992     }
    993 #endif // _GLIBCXX_HAS_GTHREADS
    994 
    995   /// @} group mutexes
    996 _GLIBCXX_END_NAMESPACE_VERSION
    997 } // namespace
    998 
    999 #endif // C++11
   1000 
   1001 #endif // _GLIBCXX_MUTEX
   1002