3 // Copyright (C) 2003-2014 Free Software Foundation, Inc.
 
    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)
 
   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.
 
   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.
 
   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/>.
 
   25 /** @file include/mutex
 
   26  *  This is a Standard C++ Library header.
 
   29 #ifndef _GLIBCXX_MUTEX
 
   30 #define _GLIBCXX_MUTEX 1
 
   32 #pragma GCC system_header
 
   34 #if __cplusplus < 201103L
 
   35 # include <bits/c++0x_warning.h>
 
   41 #include <type_traits>
 
   43 #include <system_error>
 
   44 #include <bits/functexcept.h>
 
   45 #include <bits/gthr.h>
 
   46 #include <bits/move.h> // for std::swap
 
   47 #include <bits/cxxabi_forced.h>
 
   49 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
 
   51 namespace std _GLIBCXX_VISIBILITY(default)
 
   53 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   55 #ifdef _GLIBCXX_HAS_GTHREADS
 
   56   // Common base class for std::mutex and std::timed_mutex
 
   60     typedef __gthread_mutex_t          __native_type;
 
   62 #ifdef __GTHREAD_MUTEX_INIT
 
   63     __native_type  _M_mutex = __GTHREAD_MUTEX_INIT;
 
   65     constexpr __mutex_base() noexcept = default;
 
   67     __native_type  _M_mutex;
 
   69     __mutex_base() noexcept
 
   71       // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
 
   72       __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
 
   75     ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); }
 
   78     __mutex_base(const __mutex_base&) = delete;
 
   79     __mutex_base& operator=(const __mutex_base&) = delete;
 
   82   // Common base class for std::recursive_mutex and std::recursive_timed_mutex
 
   83   class __recursive_mutex_base
 
   86     typedef __gthread_recursive_mutex_t        __native_type;
 
   88     __recursive_mutex_base(const __recursive_mutex_base&) = delete;
 
   89     __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
 
   91 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
 
   92     __native_type  _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
 
   94     __recursive_mutex_base() = default;
 
   96     __native_type  _M_mutex;
 
   98     __recursive_mutex_base()
 
  100       // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
 
  101       __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
 
  104     ~__recursive_mutex_base()
 
  105     { __gthread_recursive_mutex_destroy(&_M_mutex); }
 
  110    * @defgroup mutexes Mutexes
 
  111    * @ingroup concurrency
 
  113    * Classes for mutex support.
 
  118   class mutex : private __mutex_base
 
  121     typedef __native_type*             native_handle_type;
 
  123 #ifdef __GTHREAD_MUTEX_INIT
 
  126     mutex() noexcept = default;
 
  129     mutex(const mutex&) = delete;
 
  130     mutex& operator=(const mutex&) = delete;
 
  135       int __e = __gthread_mutex_lock(&_M_mutex);
 
  137       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
 
  139    __throw_system_error(__e);
 
  145       // XXX EINVAL, EAGAIN, EBUSY
 
  146       return !__gthread_mutex_trylock(&_M_mutex);
 
  152       // XXX EINVAL, EAGAIN, EPERM
 
  153       __gthread_mutex_unlock(&_M_mutex);
 
  158     { return &_M_mutex; }
 
  162   class recursive_mutex : private __recursive_mutex_base
 
  165     typedef __native_type*             native_handle_type;
 
  167     recursive_mutex() = default;
 
  168     ~recursive_mutex() = default;
 
  170     recursive_mutex(const recursive_mutex&) = delete;
 
  171     recursive_mutex& operator=(const recursive_mutex&) = delete;
 
  176       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
 
  178       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
 
  180    __throw_system_error(__e);
 
  186       // XXX EINVAL, EAGAIN, EBUSY
 
  187       return !__gthread_recursive_mutex_trylock(&_M_mutex);
 
  193       // XXX EINVAL, EAGAIN, EBUSY
 
  194       __gthread_recursive_mutex_unlock(&_M_mutex);
 
  199     { return &_M_mutex; }
 
  202 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
 
  203   template<typename _Derived>
 
  204     class __timed_mutex_impl
 
  207       typedef chrono::high_resolution_clock    __clock_t;
 
  209       template<typename _Rep, typename _Period>
 
  211    _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
 
  213      using chrono::steady_clock;
 
  214      auto __rt = chrono::duration_cast<steady_clock::duration>(__rtime);
 
  215      if (ratio_greater<steady_clock::period, _Period>())
 
  217      return _M_try_lock_until(steady_clock::now() + __rt);
 
  220       template<typename _Duration>
 
  222    _M_try_lock_until(const chrono::time_point<__clock_t,
 
  225      auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
 
  226      auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
 
  228      __gthread_time_t __ts = {
 
  229        static_cast<std::time_t>(__s.time_since_epoch().count()),
 
  230        static_cast<long>(__ns.count())
 
  233      auto __mutex = static_cast<_Derived*>(this)->native_handle();
 
  234      return !__gthread_mutex_timedlock(__mutex, &__ts);
 
  237       template<typename _Clock, typename _Duration>
 
  239    _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
 
  241      auto __rtime = __atime - _Clock::now();
 
  242      return _M_try_lock_until(__clock_t::now() + __rtime);
 
  248   : private __mutex_base, public __timed_mutex_impl<timed_mutex>
 
  251     typedef __native_type*             native_handle_type;
 
  253     timed_mutex() = default;
 
  254     ~timed_mutex() = default;
 
  256     timed_mutex(const timed_mutex&) = delete;
 
  257     timed_mutex& operator=(const timed_mutex&) = delete;
 
  262       int __e = __gthread_mutex_lock(&_M_mutex);
 
  264       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
 
  266    __throw_system_error(__e);
 
  272       // XXX EINVAL, EAGAIN, EBUSY
 
  273       return !__gthread_mutex_trylock(&_M_mutex);
 
  276     template <class _Rep, class _Period>
 
  278       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
 
  279       { return _M_try_lock_for(__rtime); }
 
  281     template <class _Clock, class _Duration>
 
  283       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
 
  284       { return _M_try_lock_until(__atime); }
 
  289       // XXX EINVAL, EAGAIN, EBUSY
 
  290       __gthread_mutex_unlock(&_M_mutex);
 
  295     { return &_M_mutex; }
 
  298   /// recursive_timed_mutex
 
  299   class recursive_timed_mutex
 
  300   : private __recursive_mutex_base,
 
  301     public __timed_mutex_impl<recursive_timed_mutex>
 
  304     typedef __native_type*             native_handle_type;
 
  306     recursive_timed_mutex() = default;
 
  307     ~recursive_timed_mutex() = default;
 
  309     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
 
  310     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
 
  315       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
 
  317       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
 
  319    __throw_system_error(__e);
 
  325       // XXX EINVAL, EAGAIN, EBUSY
 
  326       return !__gthread_recursive_mutex_trylock(&_M_mutex);
 
  329     template <class _Rep, class _Period>
 
  331       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
 
  332       { return _M_try_lock_for(__rtime); }
 
  334     template <class _Clock, class _Duration>
 
  336       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
 
  337       { return _M_try_lock_until(__atime); }
 
  342       // XXX EINVAL, EAGAIN, EBUSY
 
  343       __gthread_recursive_mutex_unlock(&_M_mutex);
 
  348     { return &_M_mutex; }
 
  351 #endif // _GLIBCXX_HAS_GTHREADS
 
  353   /// Do not acquire ownership of the mutex.
 
  354   struct defer_lock_t { };
 
  356   /// Try to acquire ownership of the mutex without blocking.
 
  357   struct try_to_lock_t { };
 
  359   /// Assume the calling thread has already obtained mutex ownership
 
  361   struct adopt_lock_t { };
 
  363   constexpr defer_lock_t   defer_lock { };
 
  364   constexpr try_to_lock_t  try_to_lock { };
 
  365   constexpr adopt_lock_t   adopt_lock { };
 
  367   /// @brief  Scoped lock idiom.
 
  368   // Acquire the mutex here with a constructor call, then release with
 
  369   // the destructor call in accordance with RAII style.
 
  370   template<typename _Mutex>
 
  374       typedef _Mutex mutex_type;
 
  376       explicit lock_guard(mutex_type& __m) : _M_device(__m)
 
  377       { _M_device.lock(); }
 
  379       lock_guard(mutex_type& __m, adopt_lock_t) : _M_device(__m)
 
  380       { } // calling thread owns mutex
 
  383       { _M_device.unlock(); }
 
  385       lock_guard(const lock_guard&) = delete;
 
  386       lock_guard& operator=(const lock_guard&) = delete;
 
  389       mutex_type&  _M_device;
 
  393   template<typename _Mutex>
 
  397       typedef _Mutex mutex_type;
 
  399       unique_lock() noexcept
 
  400       : _M_device(0), _M_owns(false)
 
  403       explicit unique_lock(mutex_type& __m)
 
  404       : _M_device(&__m), _M_owns(false)
 
  410       unique_lock(mutex_type& __m, defer_lock_t) noexcept
 
  411       : _M_device(&__m), _M_owns(false)
 
  414       unique_lock(mutex_type& __m, try_to_lock_t)
 
  415       : _M_device(&__m), _M_owns(_M_device->try_lock())
 
  418       unique_lock(mutex_type& __m, adopt_lock_t)
 
  419       : _M_device(&__m), _M_owns(true)
 
  421    // XXX calling thread owns mutex
 
  424       template<typename _Clock, typename _Duration>
 
  425    unique_lock(mutex_type& __m,
 
  426            const chrono::time_point<_Clock, _Duration>& __atime)
 
  427    : _M_device(&__m), _M_owns(_M_device->try_lock_until(__atime))
 
  430       template<typename _Rep, typename _Period>
 
  431    unique_lock(mutex_type& __m,
 
  432            const chrono::duration<_Rep, _Period>& __rtime)
 
  433    : _M_device(&__m), _M_owns(_M_device->try_lock_for(__rtime))
 
  442       unique_lock(const unique_lock&) = delete;
 
  443       unique_lock& operator=(const unique_lock&) = delete;
 
  445       unique_lock(unique_lock&& __u) noexcept
 
  446       : _M_device(__u._M_device), _M_owns(__u._M_owns)
 
  452       unique_lock& operator=(unique_lock&& __u) noexcept
 
  457    unique_lock(std::move(__u)).swap(*this);
 
  469      __throw_system_error(int(errc::operation_not_permitted));
 
  471      __throw_system_error(int(errc::resource_deadlock_would_occur));
 
  483      __throw_system_error(int(errc::operation_not_permitted));
 
  485      __throw_system_error(int(errc::resource_deadlock_would_occur));
 
  488        _M_owns = _M_device->try_lock();
 
  493       template<typename _Clock, typename _Duration>
 
  495    try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
 
  498        __throw_system_error(int(errc::operation_not_permitted));
 
  500        __throw_system_error(int(errc::resource_deadlock_would_occur));
 
  503          _M_owns = _M_device->try_lock_until(__atime);
 
  508       template<typename _Rep, typename _Period>
 
  510    try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
 
  513        __throw_system_error(int(errc::operation_not_permitted));
 
  515        __throw_system_error(int(errc::resource_deadlock_would_occur));
 
  518          _M_owns = _M_device->try_lock_for(__rtime);
 
  527      __throw_system_error(int(errc::operation_not_permitted));
 
  536       swap(unique_lock& __u) noexcept
 
  538    std::swap(_M_device, __u._M_device);
 
  539    std::swap(_M_owns, __u._M_owns);
 
  545    mutex_type* __ret = _M_device;
 
  552       owns_lock() const noexcept
 
  555       explicit operator bool() const noexcept
 
  556       { return owns_lock(); }
 
  559       mutex() const noexcept
 
  560       { return _M_device; }
 
  563       mutex_type*  _M_device;
 
  564       bool     _M_owns; // XXX use atomic_bool
 
  567   /// Partial specialization for unique_lock objects.
 
  568   template<typename _Mutex>
 
  570     swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
 
  576       template<typename... _Lock>
 
  578    __do_unlock(tuple<_Lock&...>& __locks)
 
  580      std::get<_Idx>(__locks).unlock();
 
  581      __unlock_impl<_Idx - 1>::__do_unlock(__locks);
 
  586     struct __unlock_impl<-1>
 
  588       template<typename... _Lock>
 
  590    __do_unlock(tuple<_Lock&...>&)
 
  594   template<typename _Lock>
 
  596     __try_to_lock(_Lock& __l)
 
  597     { return unique_lock<_Lock>(__l, try_to_lock); }
 
  599   template<int _Idx, bool _Continue = true>
 
  600     struct __try_lock_impl
 
  602       template<typename... _Lock>
 
  604    __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
 
  607           auto __lock = __try_to_lock(std::get<_Idx>(__locks));
 
  608           if (__lock.owns_lock())
 
  610               __try_lock_impl<_Idx + 1, _Idx + 2 < sizeof...(_Lock)>::
 
  611                 __do_try_lock(__locks, __idx);
 
  619     struct __try_lock_impl<_Idx, false>
 
  621       template<typename... _Lock>
 
  623    __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
 
  626           auto __lock = __try_to_lock(std::get<_Idx>(__locks));
 
  627           if (__lock.owns_lock())
 
  635   /** @brief Generic try_lock.
 
  636    *  @param __l1 Meets Mutex requirements (try_lock() may throw).
 
  637    *  @param __l2 Meets Mutex requirements (try_lock() may throw).
 
  638    *  @param __l3 Meets Mutex requirements (try_lock() may throw).
 
  639    *  @return Returns -1 if all try_lock() calls return true. Otherwise returns
 
  640    *          a 0-based index corresponding to the argument that returned false.
 
  641    *  @post Either all arguments are locked, or none will be.
 
  643    *  Sequentially calls try_lock() on each argument.
 
  645   template<typename _Lock1, typename _Lock2, typename... _Lock3>
 
  647     try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
 
  650       auto __locks = std::tie(__l1, __l2, __l3...);
 
  651       __try_lock_impl<0>::__do_try_lock(__locks, __idx);
 
  655   /** @brief Generic lock.
 
  656    *  @param __l1 Meets Mutex requirements (try_lock() may throw).
 
  657    *  @param __l2 Meets Mutex requirements (try_lock() may throw).
 
  658    *  @param __l3 Meets Mutex requirements (try_lock() may throw).
 
  659    *  @throw An exception thrown by an argument's lock() or try_lock() member.
 
  660    *  @post All arguments are locked.
 
  662    *  All arguments are locked via a sequence of calls to lock(), try_lock()
 
  663    *  and unlock().  If the call exits via an exception any locks that were
 
  664    *  obtained will be released.
 
  666   template<typename _L1, typename _L2, typename ..._L3>
 
  668     lock(_L1& __l1, _L2& __l2, _L3&... __l3)
 
  672           unique_lock<_L1> __first(__l1);
 
  674           auto __locks = std::tie(__l2, __l3...);
 
  675           __try_lock_impl<0, sizeof...(_L3)>::__do_try_lock(__locks, __idx);
 
  684 #ifdef _GLIBCXX_HAS_GTHREADS
 
  689     typedef __gthread_once_t __native_type;
 
  690     __native_type  _M_once = __GTHREAD_ONCE_INIT;
 
  694     constexpr once_flag() noexcept = default;
 
  696     /// Deleted copy constructor
 
  697     once_flag(const once_flag&) = delete;
 
  698     /// Deleted assignment operator
 
  699     once_flag& operator=(const once_flag&) = delete;
 
  701     template<typename _Callable, typename... _Args>
 
  703       call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
 
  706 #ifdef _GLIBCXX_HAVE_TLS
 
  707   extern __thread void* __once_callable;
 
  708   extern __thread void (*__once_call)();
 
  710   template<typename _Callable>
 
  714       (*(_Callable*)__once_callable)();
 
  717   extern function<void()> __once_functor;
 
  720   __set_once_functor_lock_ptr(unique_lock<mutex>*);
 
  726   extern "C" void __once_proxy(void);
 
  729   template<typename _Callable, typename... _Args>
 
  731     call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
 
  733 #ifdef _GLIBCXX_HAVE_TLS
 
  734       auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f),
 
  735           std::forward<_Args>(__args)...);
 
  736       __once_callable = &__bound_functor;
 
  737       __once_call = &__once_call_impl<decltype(__bound_functor)>;
 
  739       unique_lock<mutex> __functor_lock(__get_once_mutex());
 
  740       auto __callable = std::__bind_simple(std::forward<_Callable>(__f),
 
  741           std::forward<_Args>(__args)...);
 
  742       __once_functor = [&]() { __callable(); };
 
  743       __set_once_functor_lock_ptr(&__functor_lock);
 
  746       int __e = __gthread_once(&__once._M_once, &__once_proxy);
 
  748 #ifndef _GLIBCXX_HAVE_TLS
 
  750         __set_once_functor_lock_ptr(0);
 
  754    __throw_system_error(__e);
 
  756 #endif // _GLIBCXX_HAS_GTHREADS
 
  759 _GLIBCXX_END_NAMESPACE_VERSION
 
  761 #endif // _GLIBCXX_USE_C99_STDINT_TR1
 
  765 #endif // _GLIBCXX_MUTEX