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