1// <mutex> -*- C++ -*-
2
3// Copyright (C) 2003-2016 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/std_mutex.h>
45#if ! _GTHREAD_USE_MUTEX_TIMEDLOCK
46# include <condition_variable>
47# include <thread>
48#endif
49
50#ifdef _GLIBCXX_USE_C99_STDINT_TR1
51
52namespace std _GLIBCXX_VISIBILITY(default)
53{
54_GLIBCXX_BEGIN_NAMESPACE_VERSION
55
56  /**
57   * @ingroup mutexes
58   * @{
59   */
60
61#ifdef _GLIBCXX_HAS_GTHREADS
62
63  // Common base class for std::recursive_mutex and std::recursive_timed_mutex
64  class __recursive_mutex_base
65  {
66  protected:
67    typedef __gthread_recursive_mutex_t		__native_type;
68
69    __recursive_mutex_base(const __recursive_mutex_base&) = delete;
70    __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
71
72#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
73    __native_type  _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
74
75    __recursive_mutex_base() = default;
76#else
77    __native_type  _M_mutex;
78
79    __recursive_mutex_base()
80    {
81      // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
82      __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
83    }
84
85    ~__recursive_mutex_base()
86    { __gthread_recursive_mutex_destroy(&_M_mutex); }
87#endif
88  };
89
90  /// The standard recursive mutex type.
91  class recursive_mutex : private __recursive_mutex_base
92  {
93  public:
94    typedef __native_type* 			native_handle_type;
95
96    recursive_mutex() = default;
97    ~recursive_mutex() = default;
98
99    recursive_mutex(const recursive_mutex&) = delete;
100    recursive_mutex& operator=(const recursive_mutex&) = delete;
101
102    void
103    lock()
104    {
105      int __e = __gthread_recursive_mutex_lock(&_M_mutex);
106
107      // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
108      if (__e)
109	__throw_system_error(__e);
110    }
111
112    bool
113    try_lock() noexcept
114    {
115      // XXX EINVAL, EAGAIN, EBUSY
116      return !__gthread_recursive_mutex_trylock(&_M_mutex);
117    }
118
119    void
120    unlock()
121    {
122      // XXX EINVAL, EAGAIN, EBUSY
123      __gthread_recursive_mutex_unlock(&_M_mutex);
124    }
125
126    native_handle_type
127    native_handle()
128    { return &_M_mutex; }
129  };
130
131#if _GTHREAD_USE_MUTEX_TIMEDLOCK
132  template<typename _Derived>
133    class __timed_mutex_impl
134    {
135    protected:
136      typedef chrono::high_resolution_clock 	__clock_t;
137
138      template<typename _Rep, typename _Period>
139	bool
140	_M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
141	{
142	  using chrono::steady_clock;
143	  auto __rt = chrono::duration_cast<steady_clock::duration>(__rtime);
144	  if (ratio_greater<steady_clock::period, _Period>())
145	    ++__rt;
146	  return _M_try_lock_until(steady_clock::now() + __rt);
147	}
148
149      template<typename _Duration>
150	bool
151	_M_try_lock_until(const chrono::time_point<__clock_t,
152						   _Duration>& __atime)
153	{
154	  auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
155	  auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
156
157	  __gthread_time_t __ts = {
158	    static_cast<std::time_t>(__s.time_since_epoch().count()),
159	    static_cast<long>(__ns.count())
160	  };
161
162	  return static_cast<_Derived*>(this)->_M_timedlock(__ts);
163	}
164
165      template<typename _Clock, typename _Duration>
166	bool
167	_M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
168	{
169	  auto __rtime = __atime - _Clock::now();
170	  return _M_try_lock_until(__clock_t::now() + __rtime);
171	}
172    };
173
174  /// The standard timed mutex type.
175  class timed_mutex
176  : private __mutex_base, public __timed_mutex_impl<timed_mutex>
177  {
178  public:
179    typedef __native_type* 		  	native_handle_type;
180
181    timed_mutex() = default;
182    ~timed_mutex() = default;
183
184    timed_mutex(const timed_mutex&) = delete;
185    timed_mutex& operator=(const timed_mutex&) = delete;
186
187    void
188    lock()
189    {
190      int __e = __gthread_mutex_lock(&_M_mutex);
191
192      // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
193      if (__e)
194	__throw_system_error(__e);
195    }
196
197    bool
198    try_lock() noexcept
199    {
200      // XXX EINVAL, EAGAIN, EBUSY
201      return !__gthread_mutex_trylock(&_M_mutex);
202    }
203
204    template <class _Rep, class _Period>
205      bool
206      try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
207      { return _M_try_lock_for(__rtime); }
208
209    template <class _Clock, class _Duration>
210      bool
211      try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
212      { return _M_try_lock_until(__atime); }
213
214    void
215    unlock()
216    {
217      // XXX EINVAL, EAGAIN, EBUSY
218      __gthread_mutex_unlock(&_M_mutex);
219    }
220
221    native_handle_type
222    native_handle()
223    { return &_M_mutex; }
224
225    private:
226      friend class __timed_mutex_impl<timed_mutex>;
227
228      bool
229      _M_timedlock(const __gthread_time_t& __ts)
230      { return !__gthread_mutex_timedlock(&_M_mutex, &__ts); }
231  };
232
233  /// recursive_timed_mutex
234  class recursive_timed_mutex
235  : private __recursive_mutex_base,
236    public __timed_mutex_impl<recursive_timed_mutex>
237  {
238  public:
239    typedef __native_type* 			native_handle_type;
240
241    recursive_timed_mutex() = default;
242    ~recursive_timed_mutex() = default;
243
244    recursive_timed_mutex(const recursive_timed_mutex&) = delete;
245    recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
246
247    void
248    lock()
249    {
250      int __e = __gthread_recursive_mutex_lock(&_M_mutex);
251
252      // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
253      if (__e)
254	__throw_system_error(__e);
255    }
256
257    bool
258    try_lock() noexcept
259    {
260      // XXX EINVAL, EAGAIN, EBUSY
261      return !__gthread_recursive_mutex_trylock(&_M_mutex);
262    }
263
264    template <class _Rep, class _Period>
265      bool
266      try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
267      { return _M_try_lock_for(__rtime); }
268
269    template <class _Clock, class _Duration>
270      bool
271      try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
272      { return _M_try_lock_until(__atime); }
273
274    void
275    unlock()
276    {
277      // XXX EINVAL, EAGAIN, EBUSY
278      __gthread_recursive_mutex_unlock(&_M_mutex);
279    }
280
281    native_handle_type
282    native_handle()
283    { return &_M_mutex; }
284
285    private:
286      friend class __timed_mutex_impl<recursive_timed_mutex>;
287
288      bool
289      _M_timedlock(const __gthread_time_t& __ts)
290      { return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); }
291  };
292
293#else // !_GTHREAD_USE_MUTEX_TIMEDLOCK
294
295  /// timed_mutex
296  class timed_mutex
297  {
298    mutex		_M_mut;
299    condition_variable	_M_cv;
300    bool		_M_locked = false;
301
302  public:
303
304    timed_mutex() = default;
305    ~timed_mutex() { __glibcxx_assert( !_M_locked ); }
306
307    timed_mutex(const timed_mutex&) = delete;
308    timed_mutex& operator=(const timed_mutex&) = delete;
309
310    void
311    lock()
312    {
313      unique_lock<mutex> __lk(_M_mut);
314      _M_cv.wait(__lk, [&]{ return !_M_locked; });
315      _M_locked = true;
316    }
317
318    bool
319    try_lock()
320    {
321      lock_guard<mutex> __lk(_M_mut);
322      if (_M_locked)
323	return false;
324      _M_locked = true;
325      return true;
326    }
327
328    template<typename _Rep, typename _Period>
329      bool
330      try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
331      {
332	unique_lock<mutex> __lk(_M_mut);
333	if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; }))
334	  return false;
335	_M_locked = true;
336	return true;
337      }
338
339    template<typename _Clock, typename _Duration>
340      bool
341      try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
342      {
343	unique_lock<mutex> __lk(_M_mut);
344	if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; }))
345	  return false;
346	_M_locked = true;
347	return true;
348      }
349
350    void
351    unlock()
352    {
353      lock_guard<mutex> __lk(_M_mut);
354      __glibcxx_assert( _M_locked );
355      _M_locked = false;
356      _M_cv.notify_one();
357    }
358  };
359
360  /// recursive_timed_mutex
361  class recursive_timed_mutex
362  {
363    mutex		_M_mut;
364    condition_variable	_M_cv;
365    thread::id		_M_owner;
366    unsigned		_M_count = 0;
367
368    // Predicate type that tests whether the current thread can lock a mutex.
369    struct _Can_lock
370    {
371      // Returns true if the mutex is unlocked or is locked by _M_caller.
372      bool
373      operator()() const noexcept
374      { return _M_mx->_M_count == 0 || _M_mx->_M_owner == _M_caller; }
375
376      const recursive_timed_mutex* _M_mx;
377      thread::id _M_caller;
378    };
379
380  public:
381
382    recursive_timed_mutex() = default;
383    ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); }
384
385    recursive_timed_mutex(const recursive_timed_mutex&) = delete;
386    recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
387
388    void
389    lock()
390    {
391      auto __id = this_thread::get_id();
392      _Can_lock __can_lock{this, __id};
393      unique_lock<mutex> __lk(_M_mut);
394      _M_cv.wait(__lk, __can_lock);
395      if (_M_count == -1u)
396	__throw_system_error(EAGAIN); // [thread.timedmutex.recursive]/3
397      _M_owner = __id;
398      ++_M_count;
399    }
400
401    bool
402    try_lock()
403    {
404      auto __id = this_thread::get_id();
405      _Can_lock __can_lock{this, __id};
406      lock_guard<mutex> __lk(_M_mut);
407      if (!__can_lock())
408	return false;
409      if (_M_count == -1u)
410	return false;
411      _M_owner = __id;
412      ++_M_count;
413      return true;
414    }
415
416    template<typename _Rep, typename _Period>
417      bool
418      try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
419      {
420	auto __id = this_thread::get_id();
421	_Can_lock __can_lock{this, __id};
422	unique_lock<mutex> __lk(_M_mut);
423	if (!_M_cv.wait_for(__lk, __rtime, __can_lock))
424	  return false;
425	if (_M_count == -1u)
426	  return false;
427	_M_owner = __id;
428	++_M_count;
429	return true;
430      }
431
432    template<typename _Clock, typename _Duration>
433      bool
434      try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
435      {
436	auto __id = this_thread::get_id();
437	_Can_lock __can_lock{this, __id};
438	unique_lock<mutex> __lk(_M_mut);
439	if (!_M_cv.wait_until(__lk, __atime, __can_lock))
440	  return false;
441	if (_M_count == -1u)
442	  return false;
443	_M_owner = __id;
444	++_M_count;
445	return true;
446      }
447
448    void
449    unlock()
450    {
451      lock_guard<mutex> __lk(_M_mut);
452      __glibcxx_assert( _M_owner == this_thread::get_id() );
453      __glibcxx_assert( _M_count > 0 );
454      if (--_M_count == 0)
455	{
456	  _M_owner = {};
457	  _M_cv.notify_one();
458	}
459    }
460  };
461
462#endif
463#endif // _GLIBCXX_HAS_GTHREADS
464
465  template<typename _Lock>
466    inline unique_lock<_Lock>
467    __try_to_lock(_Lock& __l)
468    { return unique_lock<_Lock>{__l, try_to_lock}; }
469
470  template<int _Idx, bool _Continue = true>
471    struct __try_lock_impl
472    {
473      template<typename... _Lock>
474	static void
475	__do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
476	{
477          __idx = _Idx;
478          auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
479          if (__lock.owns_lock())
480            {
481	      constexpr bool __cont = _Idx + 2 < sizeof...(_Lock);
482	      using __try_locker = __try_lock_impl<_Idx + 1, __cont>;
483	      __try_locker::__do_try_lock(__locks, __idx);
484              if (__idx == -1)
485                __lock.release();
486            }
487	}
488    };
489
490  template<int _Idx>
491    struct __try_lock_impl<_Idx, false>
492    {
493      template<typename... _Lock>
494	static void
495	__do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
496	{
497          __idx = _Idx;
498          auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
499          if (__lock.owns_lock())
500            {
501              __idx = -1;
502              __lock.release();
503            }
504	}
505    };
506
507  /** @brief Generic try_lock.
508   *  @param __l1 Meets Mutex requirements (try_lock() may throw).
509   *  @param __l2 Meets Mutex requirements (try_lock() may throw).
510   *  @param __l3 Meets Mutex requirements (try_lock() may throw).
511   *  @return Returns -1 if all try_lock() calls return true. Otherwise returns
512   *          a 0-based index corresponding to the argument that returned false.
513   *  @post Either all arguments are locked, or none will be.
514   *
515   *  Sequentially calls try_lock() on each argument.
516   */
517  template<typename _Lock1, typename _Lock2, typename... _Lock3>
518    int
519    try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
520    {
521      int __idx;
522      auto __locks = std::tie(__l1, __l2, __l3...);
523      __try_lock_impl<0>::__do_try_lock(__locks, __idx);
524      return __idx;
525    }
526
527  /** @brief Generic lock.
528   *  @param __l1 Meets Mutex requirements (try_lock() may throw).
529   *  @param __l2 Meets Mutex requirements (try_lock() may throw).
530   *  @param __l3 Meets Mutex requirements (try_lock() may throw).
531   *  @throw An exception thrown by an argument's lock() or try_lock() member.
532   *  @post All arguments are locked.
533   *
534   *  All arguments are locked via a sequence of calls to lock(), try_lock()
535   *  and unlock().  If the call exits via an exception any locks that were
536   *  obtained will be released.
537   */
538  template<typename _L1, typename _L2, typename... _L3>
539    void
540    lock(_L1& __l1, _L2& __l2, _L3&... __l3)
541    {
542      while (true)
543        {
544          using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>;
545          unique_lock<_L1> __first(__l1);
546          int __idx;
547          auto __locks = std::tie(__l2, __l3...);
548          __try_locker::__do_try_lock(__locks, __idx);
549          if (__idx == -1)
550            {
551              __first.release();
552              return;
553            }
554        }
555    }
556
557#ifdef _GLIBCXX_HAS_GTHREADS
558  /// once_flag
559  struct once_flag
560  {
561  private:
562    typedef __gthread_once_t __native_type;
563    __native_type  _M_once = __GTHREAD_ONCE_INIT;
564
565  public:
566    /// Constructor
567    constexpr once_flag() noexcept = default;
568
569    /// Deleted copy constructor
570    once_flag(const once_flag&) = delete;
571    /// Deleted assignment operator
572    once_flag& operator=(const once_flag&) = delete;
573
574    template<typename _Callable, typename... _Args>
575      friend void
576      call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
577  };
578
579#ifdef _GLIBCXX_HAVE_TLS
580  extern __thread void* __once_callable;
581  extern __thread void (*__once_call)();
582#else
583  extern function<void()> __once_functor;
584
585  extern void
586  __set_once_functor_lock_ptr(unique_lock<mutex>*);
587
588  extern mutex&
589  __get_once_mutex();
590#endif
591
592  extern "C" void __once_proxy(void);
593
594  /// call_once
595  template<typename _Callable, typename... _Args>
596    void
597    call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
598    {
599      // _GLIBCXX_RESOLVE_LIB_DEFECTS
600      // 2442. call_once() shouldn't DECAY_COPY()
601      auto __callable = [&] {
602	  std::__invoke(std::forward<_Callable>(__f),
603			std::forward<_Args>(__args)...);
604      };
605#ifdef _GLIBCXX_HAVE_TLS
606      __once_callable = std::__addressof(__callable);
607      __once_call = []{ (*(decltype(__callable)*)__once_callable)(); };
608#else
609      unique_lock<mutex> __functor_lock(__get_once_mutex());
610      __once_functor = __callable;
611      __set_once_functor_lock_ptr(&__functor_lock);
612#endif
613
614      int __e = __gthread_once(&__once._M_once, &__once_proxy);
615
616#ifndef _GLIBCXX_HAVE_TLS
617      if (__functor_lock)
618        __set_once_functor_lock_ptr(0);
619#endif
620
621      if (__e)
622	__throw_system_error(__e);
623    }
624#endif // _GLIBCXX_HAS_GTHREADS
625
626  // @} group mutexes
627_GLIBCXX_END_NAMESPACE_VERSION
628} // namespace
629#endif // _GLIBCXX_USE_C99_STDINT_TR1
630
631#endif // C++11
632
633#endif // _GLIBCXX_MUTEX
634