libstdc++
mutex
Go to the documentation of this file.
1 // <mutex> -*- C++ -*-
2 
3 // Copyright (C) 2003-2021 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 <system_error>
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 
66  // Common base class for std::recursive_mutex and std::recursive_timed_mutex
67  class __recursive_mutex_base
68  {
69  protected:
70  typedef __gthread_recursive_mutex_t __native_type;
71 
72  __recursive_mutex_base(const __recursive_mutex_base&) = delete;
73  __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
74 
75 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
76  __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
77 
78  __recursive_mutex_base() = default;
79 #else
80  __native_type _M_mutex;
81 
82  __recursive_mutex_base()
83  {
84  // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
85  __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
86  }
87 
88  ~__recursive_mutex_base()
89  { __gthread_recursive_mutex_destroy(&_M_mutex); }
90 #endif
91  };
92 
93  /// The standard recursive mutex type.
94  class recursive_mutex : private __recursive_mutex_base
95  {
96  public:
97  typedef __native_type* native_handle_type;
98 
99  recursive_mutex() = default;
100  ~recursive_mutex() = default;
101 
102  recursive_mutex(const recursive_mutex&) = delete;
103  recursive_mutex& operator=(const recursive_mutex&) = delete;
104 
105  void
106  lock()
107  {
108  int __e = __gthread_recursive_mutex_lock(&_M_mutex);
109 
110  // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
111  if (__e)
112  __throw_system_error(__e);
113  }
114 
115  bool
116  try_lock() noexcept
117  {
118  // XXX EINVAL, EAGAIN, EBUSY
119  return !__gthread_recursive_mutex_trylock(&_M_mutex);
120  }
121 
122  void
123  unlock()
124  {
125  // XXX EINVAL, EAGAIN, EBUSY
126  __gthread_recursive_mutex_unlock(&_M_mutex);
127  }
128 
129  native_handle_type
130  native_handle() noexcept
131  { return &_M_mutex; }
132  };
133 
134 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
135  template<typename _Derived>
136  class __timed_mutex_impl
137  {
138  protected:
139  template<typename _Rep, typename _Period>
140  bool
141  _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
142  {
143 #if _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
144  using __clock = chrono::steady_clock;
145 #else
146  using __clock = chrono::system_clock;
147 #endif
148 
149  auto __rt = chrono::duration_cast<__clock::duration>(__rtime);
151  ++__rt;
152  return _M_try_lock_until(__clock::now() + __rt);
153  }
154 
155  template<typename _Duration>
156  bool
157  _M_try_lock_until(const chrono::time_point<chrono::system_clock,
158  _Duration>& __atime)
159  {
160  auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
161  auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
162 
163  __gthread_time_t __ts = {
164  static_cast<std::time_t>(__s.time_since_epoch().count()),
165  static_cast<long>(__ns.count())
166  };
167 
168  return static_cast<_Derived*>(this)->_M_timedlock(__ts);
169  }
170 
171 #ifdef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
172  template<typename _Duration>
173  bool
174  _M_try_lock_until(const chrono::time_point<chrono::steady_clock,
175  _Duration>& __atime)
176  {
177  auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
178  auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
179 
180  __gthread_time_t __ts = {
181  static_cast<std::time_t>(__s.time_since_epoch().count()),
182  static_cast<long>(__ns.count())
183  };
184 
185  return static_cast<_Derived*>(this)->_M_clocklock(CLOCK_MONOTONIC,
186  __ts);
187  }
188 #endif
189 
190  template<typename _Clock, typename _Duration>
191  bool
192  _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
193  {
194 #if __cplusplus > 201703L
195  static_assert(chrono::is_clock_v<_Clock>);
196 #endif
197  // The user-supplied clock may not tick at the same rate as
198  // steady_clock, so we must loop in order to guarantee that
199  // the timeout has expired before returning false.
200  auto __now = _Clock::now();
201  do {
202  auto __rtime = __atime - __now;
203  if (_M_try_lock_for(__rtime))
204  return true;
205  __now = _Clock::now();
206  } while (__atime > __now);
207  return false;
208  }
209  };
210 
211  /// The standard timed mutex type.
212  class timed_mutex
213  : private __mutex_base, public __timed_mutex_impl<timed_mutex>
214  {
215  public:
216  typedef __native_type* native_handle_type;
217 
218  timed_mutex() = default;
219  ~timed_mutex() = default;
220 
221  timed_mutex(const timed_mutex&) = delete;
222  timed_mutex& operator=(const timed_mutex&) = delete;
223 
224  void
225  lock()
226  {
227  int __e = __gthread_mutex_lock(&_M_mutex);
228 
229  // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
230  if (__e)
231  __throw_system_error(__e);
232  }
233 
234  bool
235  try_lock() noexcept
236  {
237  // XXX EINVAL, EAGAIN, EBUSY
238  return !__gthread_mutex_trylock(&_M_mutex);
239  }
240 
241  template <class _Rep, class _Period>
242  bool
243  try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
244  { return _M_try_lock_for(__rtime); }
245 
246  template <class _Clock, class _Duration>
247  bool
248  try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
249  { return _M_try_lock_until(__atime); }
250 
251  void
252  unlock()
253  {
254  // XXX EINVAL, EAGAIN, EBUSY
255  __gthread_mutex_unlock(&_M_mutex);
256  }
257 
258  native_handle_type
259  native_handle() noexcept
260  { return &_M_mutex; }
261 
262  private:
263  friend class __timed_mutex_impl<timed_mutex>;
264 
265  bool
266  _M_timedlock(const __gthread_time_t& __ts)
267  { return !__gthread_mutex_timedlock(&_M_mutex, &__ts); }
268 
269 #if _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
270  bool
271  _M_clocklock(clockid_t clockid, const __gthread_time_t& __ts)
272  { return !pthread_mutex_clocklock(&_M_mutex, clockid, &__ts); }
273 #endif
274  };
275 
276  /// recursive_timed_mutex
277  class recursive_timed_mutex
278  : private __recursive_mutex_base,
279  public __timed_mutex_impl<recursive_timed_mutex>
280  {
281  public:
282  typedef __native_type* native_handle_type;
283 
284  recursive_timed_mutex() = default;
285  ~recursive_timed_mutex() = default;
286 
287  recursive_timed_mutex(const recursive_timed_mutex&) = delete;
288  recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
289 
290  void
291  lock()
292  {
293  int __e = __gthread_recursive_mutex_lock(&_M_mutex);
294 
295  // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
296  if (__e)
297  __throw_system_error(__e);
298  }
299 
300  bool
301  try_lock() noexcept
302  {
303  // XXX EINVAL, EAGAIN, EBUSY
304  return !__gthread_recursive_mutex_trylock(&_M_mutex);
305  }
306 
307  template <class _Rep, class _Period>
308  bool
309  try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
310  { return _M_try_lock_for(__rtime); }
311 
312  template <class _Clock, class _Duration>
313  bool
314  try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
315  { return _M_try_lock_until(__atime); }
316 
317  void
318  unlock()
319  {
320  // XXX EINVAL, EAGAIN, EBUSY
321  __gthread_recursive_mutex_unlock(&_M_mutex);
322  }
323 
324  native_handle_type
325  native_handle() noexcept
326  { return &_M_mutex; }
327 
328  private:
329  friend class __timed_mutex_impl<recursive_timed_mutex>;
330 
331  bool
332  _M_timedlock(const __gthread_time_t& __ts)
333  { return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); }
334 
335 #ifdef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK
336  bool
337  _M_clocklock(clockid_t clockid, const __gthread_time_t& __ts)
338  { return !pthread_mutex_clocklock(&_M_mutex, clockid, &__ts); }
339 #endif
340  };
341 
342 #else // !_GTHREAD_USE_MUTEX_TIMEDLOCK
343 
344  /// timed_mutex
346  {
347  mutex _M_mut;
348  condition_variable _M_cv;
349  bool _M_locked = false;
350 
351  public:
352 
353  timed_mutex() = default;
354  ~timed_mutex() { __glibcxx_assert( !_M_locked ); }
355 
356  timed_mutex(const timed_mutex&) = delete;
357  timed_mutex& operator=(const timed_mutex&) = delete;
358 
359  void
360  lock()
361  {
362  unique_lock<mutex> __lk(_M_mut);
363  _M_cv.wait(__lk, [&]{ return !_M_locked; });
364  _M_locked = true;
365  }
366 
367  bool
368  try_lock()
369  {
370  lock_guard<mutex> __lk(_M_mut);
371  if (_M_locked)
372  return false;
373  _M_locked = true;
374  return true;
375  }
376 
377  template<typename _Rep, typename _Period>
378  bool
379  try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
380  {
381  unique_lock<mutex> __lk(_M_mut);
382  if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; }))
383  return false;
384  _M_locked = true;
385  return true;
386  }
387 
388  template<typename _Clock, typename _Duration>
389  bool
390  try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
391  {
392  unique_lock<mutex> __lk(_M_mut);
393  if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; }))
394  return false;
395  _M_locked = true;
396  return true;
397  }
398 
399  void
400  unlock()
401  {
402  lock_guard<mutex> __lk(_M_mut);
403  __glibcxx_assert( _M_locked );
404  _M_locked = false;
405  _M_cv.notify_one();
406  }
407  };
408 
409  /// recursive_timed_mutex
411  {
412  mutex _M_mut;
413  condition_variable _M_cv;
414  thread::id _M_owner;
415  unsigned _M_count = 0;
416 
417  // Predicate type that tests whether the current thread can lock a mutex.
418  struct _Can_lock
419  {
420  // Returns true if the mutex is unlocked or is locked by _M_caller.
421  bool
422  operator()() const noexcept
423  { return _M_mx->_M_count == 0 || _M_mx->_M_owner == _M_caller; }
424 
425  const recursive_timed_mutex* _M_mx;
426  thread::id _M_caller;
427  };
428 
429  public:
430 
431  recursive_timed_mutex() = default;
432  ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); }
433 
435  recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
436 
437  void
438  lock()
439  {
440  auto __id = this_thread::get_id();
441  _Can_lock __can_lock{this, __id};
442  unique_lock<mutex> __lk(_M_mut);
443  _M_cv.wait(__lk, __can_lock);
444  if (_M_count == -1u)
445  __throw_system_error(EAGAIN); // [thread.timedmutex.recursive]/3
446  _M_owner = __id;
447  ++_M_count;
448  }
449 
450  bool
451  try_lock()
452  {
453  auto __id = this_thread::get_id();
454  _Can_lock __can_lock{this, __id};
455  lock_guard<mutex> __lk(_M_mut);
456  if (!__can_lock())
457  return false;
458  if (_M_count == -1u)
459  return false;
460  _M_owner = __id;
461  ++_M_count;
462  return true;
463  }
464 
465  template<typename _Rep, typename _Period>
466  bool
467  try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
468  {
469  auto __id = this_thread::get_id();
470  _Can_lock __can_lock{this, __id};
471  unique_lock<mutex> __lk(_M_mut);
472  if (!_M_cv.wait_for(__lk, __rtime, __can_lock))
473  return false;
474  if (_M_count == -1u)
475  return false;
476  _M_owner = __id;
477  ++_M_count;
478  return true;
479  }
480 
481  template<typename _Clock, typename _Duration>
482  bool
483  try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
484  {
485  auto __id = this_thread::get_id();
486  _Can_lock __can_lock{this, __id};
487  unique_lock<mutex> __lk(_M_mut);
488  if (!_M_cv.wait_until(__lk, __atime, __can_lock))
489  return false;
490  if (_M_count == -1u)
491  return false;
492  _M_owner = __id;
493  ++_M_count;
494  return true;
495  }
496 
497  void
498  unlock()
499  {
500  lock_guard<mutex> __lk(_M_mut);
501  __glibcxx_assert( _M_owner == this_thread::get_id() );
502  __glibcxx_assert( _M_count > 0 );
503  if (--_M_count == 0)
504  {
505  _M_owner = {};
506  _M_cv.notify_one();
507  }
508  }
509  };
510 
511 #endif
512 #endif // _GLIBCXX_HAS_GTHREADS
513 
514  /// @cond undocumented
515  template<typename _Lock>
516  inline unique_lock<_Lock>
517  __try_to_lock(_Lock& __l)
518  { return unique_lock<_Lock>{__l, try_to_lock}; }
519 
520  template<int _Idx, bool _Continue = true>
521  struct __try_lock_impl
522  {
523  template<typename... _Lock>
524  static void
525  __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
526  {
527  __idx = _Idx;
528  auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
529  if (__lock.owns_lock())
530  {
531  constexpr bool __cont = _Idx + 2 < sizeof...(_Lock);
532  using __try_locker = __try_lock_impl<_Idx + 1, __cont>;
533  __try_locker::__do_try_lock(__locks, __idx);
534  if (__idx == -1)
535  __lock.release();
536  }
537  }
538  };
539 
540  template<int _Idx>
541  struct __try_lock_impl<_Idx, false>
542  {
543  template<typename... _Lock>
544  static void
545  __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
546  {
547  __idx = _Idx;
548  auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
549  if (__lock.owns_lock())
550  {
551  __idx = -1;
552  __lock.release();
553  }
554  }
555  };
556  /// @endcond
557 
558  /** @brief Generic try_lock.
559  * @param __l1 Meets Lockable requirements (try_lock() may throw).
560  * @param __l2 Meets Lockable requirements (try_lock() may throw).
561  * @param __l3 Meets Lockable requirements (try_lock() may throw).
562  * @return Returns -1 if all try_lock() calls return true. Otherwise returns
563  * a 0-based index corresponding to the argument that returned false.
564  * @post Either all arguments are locked, or none will be.
565  *
566  * Sequentially calls try_lock() on each argument.
567  */
568  template<typename _Lock1, typename _Lock2, typename... _Lock3>
569  int
570  try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
571  {
572  int __idx;
573  auto __locks = std::tie(__l1, __l2, __l3...);
574  __try_lock_impl<0>::__do_try_lock(__locks, __idx);
575  return __idx;
576  }
577 
578  /** @brief Generic lock.
579  * @param __l1 Meets Lockable requirements (try_lock() may throw).
580  * @param __l2 Meets Lockable requirements (try_lock() may throw).
581  * @param __l3 Meets Lockable requirements (try_lock() may throw).
582  * @throw An exception thrown by an argument's lock() or try_lock() member.
583  * @post All arguments are locked.
584  *
585  * All arguments are locked via a sequence of calls to lock(), try_lock()
586  * and unlock(). If the call exits via an exception any locks that were
587  * obtained will be released.
588  */
589  template<typename _L1, typename _L2, typename... _L3>
590  void
591  lock(_L1& __l1, _L2& __l2, _L3&... __l3)
592  {
593  while (true)
594  {
595  using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>;
596  unique_lock<_L1> __first(__l1);
597  int __idx;
598  auto __locks = std::tie(__l2, __l3...);
599  __try_locker::__do_try_lock(__locks, __idx);
600  if (__idx == -1)
601  {
602  __first.release();
603  return;
604  }
605  }
606  }
607 
608 #if __cplusplus >= 201703L
609 #define __cpp_lib_scoped_lock 201703
610  /** @brief A scoped lock type for multiple lockable objects.
611  *
612  * A scoped_lock controls mutex ownership within a scope, releasing
613  * ownership in the destructor.
614  */
615  template<typename... _MutexTypes>
617  {
618  public:
619  explicit scoped_lock(_MutexTypes&... __m) : _M_devices(std::tie(__m...))
620  { std::lock(__m...); }
621 
622  explicit scoped_lock(adopt_lock_t, _MutexTypes&... __m) noexcept
623  : _M_devices(std::tie(__m...))
624  { } // calling thread owns mutex
625 
626  ~scoped_lock()
627  { std::apply([](auto&... __m) { (__m.unlock(), ...); }, _M_devices); }
628 
629  scoped_lock(const scoped_lock&) = delete;
630  scoped_lock& operator=(const scoped_lock&) = delete;
631 
632  private:
633  tuple<_MutexTypes&...> _M_devices;
634  };
635 
636  template<>
637  class scoped_lock<>
638  {
639  public:
640  explicit scoped_lock() = default;
641  explicit scoped_lock(adopt_lock_t) noexcept { }
642  ~scoped_lock() = default;
643 
644  scoped_lock(const scoped_lock&) = delete;
645  scoped_lock& operator=(const scoped_lock&) = delete;
646  };
647 
648  template<typename _Mutex>
649  class scoped_lock<_Mutex>
650  {
651  public:
652  using mutex_type = _Mutex;
653 
654  explicit scoped_lock(mutex_type& __m) : _M_device(__m)
655  { _M_device.lock(); }
656 
657  explicit scoped_lock(adopt_lock_t, mutex_type& __m) noexcept
658  : _M_device(__m)
659  { } // calling thread owns mutex
660 
661  ~scoped_lock()
662  { _M_device.unlock(); }
663 
664  scoped_lock(const scoped_lock&) = delete;
665  scoped_lock& operator=(const scoped_lock&) = delete;
666 
667  private:
668  mutex_type& _M_device;
669  };
670 #endif // C++17
671 
672  /// Flag type used by std::call_once
673  struct once_flag
674  {
675  constexpr once_flag() noexcept = default;
676 
677  /// Deleted copy constructor
678  once_flag(const once_flag&) = delete;
679  /// Deleted assignment operator
680  once_flag& operator=(const once_flag&) = delete;
681 
682  private:
683  // There are two different std::once_flag interfaces, abstracting four
684  // different implementations.
685  // The preferred interface uses the _M_activate() and _M_finish(bool)
686  // member functions (introduced in GCC 11), which start and finish an
687  // active execution respectively. See [thread.once.callonce] in C++11
688  // for the definition of active/passive/returning/exceptional executions.
689  // This interface is supported for Linux (using atomics and futexes) and
690  // for single-threaded targets with no gthreads support.
691  // For other targets a pthread_once_t is used with pthread_once, but that
692  // doesn't work correctly for exceptional executions. That interface
693  // uses an object of type _Prepare_execution and a lambda expression.
694 #if defined _GLIBCXX_HAVE_LINUX_FUTEX || ! defined _GLIBCXX_HAS_GTHREADS
695  enum _Bits : int { _Init = 0, _Active = 1, _Done = 2 };
696 
697  int _M_once = _Bits::_Init;
698 
699  // Non-blocking check to see if all executions will be passive now.
700  bool
701  _M_passive() const noexcept;
702 
703  // Attempts to begin an active execution. Blocks until it either:
704  // - returns true if an active execution has started on this thread, or
705  // - returns false if a returning execution happens on another thread.
706  bool _M_activate();
707 
708  // Must be called to complete an active execution.
709  void _M_finish(bool __returning) noexcept;
710 
711  // RAII helper to call _M_finish.
712  struct _Active_execution
713  {
714  explicit _Active_execution(once_flag& __flag) : _M_flag(__flag) { }
715 
716  ~_Active_execution() { _M_flag._M_finish(_M_returning); }
717 
718  _Active_execution(const _Active_execution&) = delete;
719  _Active_execution& operator=(const _Active_execution&) = delete;
720 
721  once_flag& _M_flag;
722  bool _M_returning = false;
723  };
724 #else
725  __gthread_once_t _M_once = __GTHREAD_ONCE_INIT;
726 
727  struct _Prepare_execution;
728 #endif // ! GTHREADS
729 
730  template<typename _Callable, typename... _Args>
731  friend void
732  call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
733  };
734 
735 #if ! defined _GLIBCXX_HAS_GTHREADS
736  // Inline definitions of std::once_flag members for single-threaded targets.
737 
738  inline bool
739  once_flag::_M_passive() const noexcept
740  { return _M_once == _Bits::_Done; }
741 
742  inline bool
743  once_flag::_M_activate()
744  {
745  if (_M_once == _Bits::_Init)
746  {
747  _M_once = _Bits::_Active;
748  return true;
749  }
750  else if (!_M_passive())
751  __throw_system_error(EDEADLK);
752  }
753 
754  inline void
755  once_flag::_M_finish(bool returning) noexcept
756  { _M_once = returning ? _Bits::_Done : _Bits::_Init; }
757 
758 #elif defined _GLIBCXX_HAVE_LINUX_FUTEX
759 
760  // Define this inline to make passive executions fast.
761  inline bool
762  once_flag::_M_passive() const noexcept
763  {
764  if (__gnu_cxx::__is_single_threaded())
765  return _M_once == _Bits::_Done;
766  else
767  return __atomic_load_n(&_M_once, __ATOMIC_ACQUIRE) == _Bits::_Done;
768  }
769 
770 #else // GTHREADS && ! FUTEX
771 
772  /// @cond undocumented
773 # ifdef _GLIBCXX_HAVE_TLS
774  // If TLS is available use thread-local state for the type-erased callable
775  // that is being run by std::call_once in the current thread.
776  extern __thread void* __once_callable;
777  extern __thread void (*__once_call)();
778 # else
779  // Without TLS use a global std::mutex and store the callable in a
780  // global std::function.
781  extern function<void()> __once_functor;
782 
783  extern void
784  __set_once_functor_lock_ptr(unique_lock<mutex>*);
785 
786  extern mutex&
787  __get_once_mutex();
788 # endif
789 
790  // This function is passed to pthread_once by std::call_once.
791  // It runs __once_call() or __once_functor().
792  extern "C" void __once_proxy(void);
793 
794  // RAII type to set up state for pthread_once call.
795  struct once_flag::_Prepare_execution
796  {
797 #ifdef _GLIBCXX_HAVE_TLS
798  template<typename _Callable>
799  explicit
800  _Prepare_execution(_Callable& __c)
801  {
802  // Store address in thread-local pointer:
803  __once_callable = std::__addressof(__c);
804  // Trampoline function to invoke the closure via thread-local pointer:
805  __once_call = [] { (*static_cast<_Callable*>(__once_callable))(); };
806  }
807 
808  ~_Prepare_execution()
809  {
810  // PR libstdc++/82481
811  __once_callable = nullptr;
812  __once_call = nullptr;
813  }
814 #else // ! TLS
815  template<typename _Callable>
816  explicit
817  _Prepare_execution(_Callable& __c)
818  {
819  // Store the callable in the global std::function
820  __once_functor = __c;
821  __set_once_functor_lock_ptr(&_M_functor_lock);
822  }
823 
824  ~_Prepare_execution()
825  {
826  if (_M_functor_lock)
827  __set_once_functor_lock_ptr(nullptr);
828  }
829 
830  private:
831  unique_lock<mutex> _M_functor_lock{__get_once_mutex()};
832 #endif // ! TLS
833 
834  _Prepare_execution(const _Prepare_execution&) = delete;
835  _Prepare_execution& operator=(const _Prepare_execution&) = delete;
836  };
837  /// @endcond
838 #endif
839 
840  /// Invoke a callable and synchronize with other calls using the same flag
841  template<typename _Callable, typename... _Args>
842  void
843  call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
844  {
845 #if defined _GLIBCXX_HAVE_LINUX_FUTEX || ! defined _GLIBCXX_HAS_GTHREADS
846  if (__once._M_passive())
847  return;
848  else if (__once._M_activate())
849  {
850  once_flag::_Active_execution __exec(__once);
851 
852  // _GLIBCXX_RESOLVE_LIB_DEFECTS
853  // 2442. call_once() shouldn't DECAY_COPY()
854  std::__invoke(std::forward<_Callable>(__f),
855  std::forward<_Args>(__args)...);
856 
857  // __f(__args...) did not throw
858  __exec._M_returning = true;
859  }
860 #else
861  // Closure type that runs the function
862  auto __callable = [&] {
863  std::__invoke(std::forward<_Callable>(__f),
864  std::forward<_Args>(__args)...);
865  };
866 
867  once_flag::_Prepare_execution __exec(__callable);
868 
869  // XXX pthread_once does not reset the flag if an exception is thrown.
870  if (int __e = __gthread_once(&__once._M_once, &__once_proxy))
871  __throw_system_error(__e);
872 #endif
873  }
874 
875  // @} group mutexes
876 _GLIBCXX_END_NAMESPACE_VERSION
877 } // namespace
878 
879 #endif // C++11
880 
881 #endif // _GLIBCXX_MUTEX
auto_ptr & operator=(auto_ptr &__a)
auto_ptr assignment operator.
Definition: auto_ptr.h:47
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:49
constexpr tuple< _Elements &... > tie(_Elements &... __args) noexcept
tie
Definition: tuple:1698
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:89
friend void call_once(once_flag &__once, _Callable &&__f, _Args &&... __args)
Invoke a callable and synchronize with other calls using the same flag.
Definition: mutex:843
once_flag(const once_flag &)=delete
Deleted copy constructor.
void lock(_L1 &__l1, _L2 &__l2, _L3 &... __l3)
Generic lock.
Definition: mutex:591
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:212
int try_lock(_Lock1 &__l1, _Lock2 &__l2, _Lock3 &... __l3)
Generic try_lock.
Definition: mutex:570
once_flag & operator=(const once_flag &)=delete
Deleted assignment operator.
void call_once(once_flag &__once, _Callable &&__f, _Args &&... __args)
Invoke a callable and synchronize with other calls using the same flag.
Definition: mutex:843
ISO C++ entities toplevel namespace is std.
thread::id get_id() noexcept
this_thread::get_id
Definition: std_thread.h:307
time_point
Definition: chrono:852
System clock.
Definition: chrono:1102
Monotonic clock.
Definition: chrono:1142
condition_variable
The standard recursive mutex type.
Definition: mutex:95
timed_mutex
Definition: mutex:346
recursive_timed_mutex
Definition: mutex:411
A scoped lock type for multiple lockable objects.
Definition: mutex:617
Flag type used by std::call_once.
Definition: mutex:674
ratio_greater
Definition: ratio:411
Primary class template, tuple.
Definition: tuple:600
The standard mutex type.
Definition: std_mutex.h:84
Assume the calling thread has already obtained mutex ownership and manage it.
Definition: std_mutex.h:206
A simple scoped lock type.
Definition: std_mutex.h:224
thread::id
Definition: std_thread.h:82
A movable scoped lock type.
Definition: unique_lock.h:57