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