3 // Copyright (C) 2003-2018 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>
    42 #include <system_error>
    43 #include <bits/std_mutex.h>
    44 #if ! _GTHREAD_USE_MUTEX_TIMEDLOCK
    45 # include <condition_variable>
    48 #ifndef _GLIBCXX_HAVE_TLS
    49 # include <bits/std_function.h>
    52 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
    54 namespace std _GLIBCXX_VISIBILITY(default)
    56 _GLIBCXX_BEGIN_NAMESPACE_VERSION
    63 #ifdef _GLIBCXX_HAS_GTHREADS
    65   // Common base class for std::recursive_mutex and std::recursive_timed_mutex
    66   class __recursive_mutex_base
    69     typedef __gthread_recursive_mutex_t            __native_type;
    71     __recursive_mutex_base(const __recursive_mutex_base&) = delete;
    72     __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
    74 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
    75     __native_type  _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
    77     __recursive_mutex_base() = default;
    79     __native_type  _M_mutex;
    81     __recursive_mutex_base()
    83       // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
    84       __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
    87     ~__recursive_mutex_base()
    88     { __gthread_recursive_mutex_destroy(&_M_mutex); }
    92   /// The standard recursive mutex type.
    93   class recursive_mutex : private __recursive_mutex_base
    96     typedef __native_type*                         native_handle_type;
    98     recursive_mutex() = default;
    99     ~recursive_mutex() = default;
   101     recursive_mutex(const recursive_mutex&) = delete;
   102     recursive_mutex& operator=(const recursive_mutex&) = delete;
   107       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
   109       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
   111    __throw_system_error(__e);
   117       // XXX EINVAL, EAGAIN, EBUSY
   118       return !__gthread_recursive_mutex_trylock(&_M_mutex);
   124       // XXX EINVAL, EAGAIN, EBUSY
   125       __gthread_recursive_mutex_unlock(&_M_mutex);
   129     native_handle() noexcept
   130     { return &_M_mutex; }
   133 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
   134   template<typename _Derived>
   135     class __timed_mutex_impl
   138       typedef chrono::high_resolution_clock        __clock_t;
   140       template<typename _Rep, typename _Period>
   142    _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
   144      using chrono::steady_clock;
   145      auto __rt = chrono::duration_cast<steady_clock::duration>(__rtime);
   146      if (ratio_greater<steady_clock::period, _Period>())
   148      return _M_try_lock_until(steady_clock::now() + __rt);
   151       template<typename _Duration>
   153    _M_try_lock_until(const chrono::time_point<__clock_t,
   156      auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
   157      auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
   159      __gthread_time_t __ts = {
   160        static_cast<std::time_t>(__s.time_since_epoch().count()),
   161        static_cast<long>(__ns.count())
   164      return static_cast<_Derived*>(this)->_M_timedlock(__ts);
   167       template<typename _Clock, typename _Duration>
   169    _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
   171      auto __rtime = __atime - _Clock::now();
   172      return _M_try_lock_until(__clock_t::now() + __rtime);
   176   /// The standard timed mutex type.
   178   : private __mutex_base, public __timed_mutex_impl<timed_mutex>
   181     typedef __native_type*                         native_handle_type;
   183     timed_mutex() = default;
   184     ~timed_mutex() = default;
   186     timed_mutex(const timed_mutex&) = delete;
   187     timed_mutex& operator=(const timed_mutex&) = delete;
   192       int __e = __gthread_mutex_lock(&_M_mutex);
   194       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
   196    __throw_system_error(__e);
   202       // XXX EINVAL, EAGAIN, EBUSY
   203       return !__gthread_mutex_trylock(&_M_mutex);
   206     template <class _Rep, class _Period>
   208       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
   209       { return _M_try_lock_for(__rtime); }
   211     template <class _Clock, class _Duration>
   213       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
   214       { return _M_try_lock_until(__atime); }
   219       // XXX EINVAL, EAGAIN, EBUSY
   220       __gthread_mutex_unlock(&_M_mutex);
   224     native_handle() noexcept
   225     { return &_M_mutex; }
   228       friend class __timed_mutex_impl<timed_mutex>;
   231       _M_timedlock(const __gthread_time_t& __ts)
   232       { return !__gthread_mutex_timedlock(&_M_mutex, &__ts); }
   235   /// recursive_timed_mutex
   236   class recursive_timed_mutex
   237   : private __recursive_mutex_base,
   238     public __timed_mutex_impl<recursive_timed_mutex>
   241     typedef __native_type*                         native_handle_type;
   243     recursive_timed_mutex() = default;
   244     ~recursive_timed_mutex() = default;
   246     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
   247     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
   252       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
   254       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
   256    __throw_system_error(__e);
   262       // XXX EINVAL, EAGAIN, EBUSY
   263       return !__gthread_recursive_mutex_trylock(&_M_mutex);
   266     template <class _Rep, class _Period>
   268       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
   269       { return _M_try_lock_for(__rtime); }
   271     template <class _Clock, class _Duration>
   273       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
   274       { return _M_try_lock_until(__atime); }
   279       // XXX EINVAL, EAGAIN, EBUSY
   280       __gthread_recursive_mutex_unlock(&_M_mutex);
   284     native_handle() noexcept
   285     { return &_M_mutex; }
   288       friend class __timed_mutex_impl<recursive_timed_mutex>;
   291       _M_timedlock(const __gthread_time_t& __ts)
   292       { return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); }
   295 #else // !_GTHREAD_USE_MUTEX_TIMEDLOCK
   301     condition_variable     _M_cv;
   302     bool           _M_locked = false;
   306     timed_mutex() = default;
   307     ~timed_mutex() { __glibcxx_assert( !_M_locked ); }
   309     timed_mutex(const timed_mutex&) = delete;
   310     timed_mutex& operator=(const timed_mutex&) = delete;
   315       unique_lock<mutex> __lk(_M_mut);
   316       _M_cv.wait(__lk, [&]{ return !_M_locked; });
   323       lock_guard<mutex> __lk(_M_mut);
   330     template<typename _Rep, typename _Period>
   332       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
   334    unique_lock<mutex> __lk(_M_mut);
   335    if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; }))
   341     template<typename _Clock, typename _Duration>
   343       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
   345    unique_lock<mutex> __lk(_M_mut);
   346    if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; }))
   355       lock_guard<mutex> __lk(_M_mut);
   356       __glibcxx_assert( _M_locked );
   362   /// recursive_timed_mutex
   363   class recursive_timed_mutex
   366     condition_variable     _M_cv;
   368     unsigned               _M_count = 0;
   370     // Predicate type that tests whether the current thread can lock a mutex.
   373       // Returns true if the mutex is unlocked or is locked by _M_caller.
   375       operator()() const noexcept
   376       { return _M_mx->_M_count == 0 || _M_mx->_M_owner == _M_caller; }
   378       const recursive_timed_mutex* _M_mx;
   379       thread::id _M_caller;
   384     recursive_timed_mutex() = default;
   385     ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); }
   387     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
   388     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
   393       auto __id = this_thread::get_id();
   394       _Can_lock __can_lock{this, __id};
   395       unique_lock<mutex> __lk(_M_mut);
   396       _M_cv.wait(__lk, __can_lock);
   398    __throw_system_error(EAGAIN); // [thread.timedmutex.recursive]/3
   406       auto __id = this_thread::get_id();
   407       _Can_lock __can_lock{this, __id};
   408       lock_guard<mutex> __lk(_M_mut);
   418     template<typename _Rep, typename _Period>
   420       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
   422    auto __id = this_thread::get_id();
   423    _Can_lock __can_lock{this, __id};
   424    unique_lock<mutex> __lk(_M_mut);
   425    if (!_M_cv.wait_for(__lk, __rtime, __can_lock))
   434     template<typename _Clock, typename _Duration>
   436       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
   438    auto __id = this_thread::get_id();
   439    _Can_lock __can_lock{this, __id};
   440    unique_lock<mutex> __lk(_M_mut);
   441    if (!_M_cv.wait_until(__lk, __atime, __can_lock))
   453       lock_guard<mutex> __lk(_M_mut);
   454       __glibcxx_assert( _M_owner == this_thread::get_id() );
   455       __glibcxx_assert( _M_count > 0 );
   465 #endif // _GLIBCXX_HAS_GTHREADS
   467   template<typename _Lock>
   468     inline unique_lock<_Lock>
   469     __try_to_lock(_Lock& __l)
   470     { return unique_lock<_Lock>{__l, try_to_lock}; }
   472   template<int _Idx, bool _Continue = true>
   473     struct __try_lock_impl
   475       template<typename... _Lock>
   477    __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
   480           auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
   481           if (__lock.owns_lock())
   483          constexpr bool __cont = _Idx + 2 < sizeof...(_Lock);
   484          using __try_locker = __try_lock_impl<_Idx + 1, __cont>;
   485          __try_locker::__do_try_lock(__locks, __idx);
   493     struct __try_lock_impl<_Idx, false>
   495       template<typename... _Lock>
   497    __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
   500           auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
   501           if (__lock.owns_lock())
   509   /** @brief Generic try_lock.
   510    *  @param __l1 Meets Lockable requirements (try_lock() may throw).
   511    *  @param __l2 Meets Lockable requirements (try_lock() may throw).
   512    *  @param __l3 Meets Lockable requirements (try_lock() may throw).
   513    *  @return Returns -1 if all try_lock() calls return true. Otherwise returns
   514    *          a 0-based index corresponding to the argument that returned false.
   515    *  @post Either all arguments are locked, or none will be.
   517    *  Sequentially calls try_lock() on each argument.
   519   template<typename _Lock1, typename _Lock2, typename... _Lock3>
   521     try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
   524       auto __locks = std::tie(__l1, __l2, __l3...);
   525       __try_lock_impl<0>::__do_try_lock(__locks, __idx);
   529   /** @brief Generic lock.
   530    *  @param __l1 Meets Lockable requirements (try_lock() may throw).
   531    *  @param __l2 Meets Lockable requirements (try_lock() may throw).
   532    *  @param __l3 Meets Lockable requirements (try_lock() may throw).
   533    *  @throw An exception thrown by an argument's lock() or try_lock() member.
   534    *  @post All arguments are locked.
   536    *  All arguments are locked via a sequence of calls to lock(), try_lock()
   537    *  and unlock().  If the call exits via an exception any locks that were
   538    *  obtained will be released.
   540   template<typename _L1, typename _L2, typename... _L3>
   542     lock(_L1& __l1, _L2& __l2, _L3&... __l3)
   546           using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>;
   547           unique_lock<_L1> __first(__l1);
   549           auto __locks = std::tie(__l2, __l3...);
   550           __try_locker::__do_try_lock(__locks, __idx);
   559 #if __cplusplus >= 201703L
   560 #define __cpp_lib_scoped_lock 201703
   561   /** @brief A scoped lock type for multiple lockable objects.
   563    * A scoped_lock controls mutex ownership within a scope, releasing
   564    * ownership in the destructor.
   566   template<typename... _MutexTypes>
   570       explicit scoped_lock(_MutexTypes&... __m) : _M_devices(std::tie(__m...))
   571       { std::lock(__m...); }
   573       explicit scoped_lock(adopt_lock_t, _MutexTypes&... __m) noexcept
   574       : _M_devices(std::tie(__m...))
   575       { } // calling thread owns mutex
   579    std::apply([](_MutexTypes&... __m) {
   580      char __i[] __attribute__((__unused__)) = { (__m.unlock(), 0)... };
   584       scoped_lock(const scoped_lock&) = delete;
   585       scoped_lock& operator=(const scoped_lock&) = delete;
   588       tuple<_MutexTypes&...> _M_devices;
   595       explicit scoped_lock() = default;
   596       explicit scoped_lock(adopt_lock_t) noexcept { }
   597       ~scoped_lock() = default;
   599       scoped_lock(const scoped_lock&) = delete;
   600       scoped_lock& operator=(const scoped_lock&) = delete;
   603   template<typename _Mutex>
   604     class scoped_lock<_Mutex>
   607       using mutex_type = _Mutex;
   609       explicit scoped_lock(mutex_type& __m) : _M_device(__m)
   610       { _M_device.lock(); }
   612       explicit scoped_lock(adopt_lock_t, mutex_type& __m) noexcept
   614       { } // calling thread owns mutex
   617       { _M_device.unlock(); }
   619       scoped_lock(const scoped_lock&) = delete;
   620       scoped_lock& operator=(const scoped_lock&) = delete;
   623       mutex_type&  _M_device;
   627 #ifdef _GLIBCXX_HAS_GTHREADS
   632     typedef __gthread_once_t __native_type;
   633     __native_type  _M_once = __GTHREAD_ONCE_INIT;
   637     constexpr once_flag() noexcept = default;
   639     /// Deleted copy constructor
   640     once_flag(const once_flag&) = delete;
   641     /// Deleted assignment operator
   642     once_flag& operator=(const once_flag&) = delete;
   644     template<typename _Callable, typename... _Args>
   646       call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
   649 #ifdef _GLIBCXX_HAVE_TLS
   650   extern __thread void* __once_callable;
   651   extern __thread void (*__once_call)();
   653   extern function<void()> __once_functor;
   656   __set_once_functor_lock_ptr(unique_lock<mutex>*);
   662   extern "C" void __once_proxy(void);
   665   template<typename _Callable, typename... _Args>
   667     call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
   669       // _GLIBCXX_RESOLVE_LIB_DEFECTS
   670       // 2442. call_once() shouldn't DECAY_COPY()
   671       auto __callable = [&] {
   672      std::__invoke(std::forward<_Callable>(__f),
   673                    std::forward<_Args>(__args)...);
   675 #ifdef _GLIBCXX_HAVE_TLS
   676       __once_callable = std::__addressof(__callable);
   677       __once_call = []{ (*(decltype(__callable)*)__once_callable)(); };
   679       unique_lock<mutex> __functor_lock(__get_once_mutex());
   680       __once_functor = __callable;
   681       __set_once_functor_lock_ptr(&__functor_lock);
   684       int __e = __gthread_once(&__once._M_once, &__once_proxy);
   686 #ifndef _GLIBCXX_HAVE_TLS
   688         __set_once_functor_lock_ptr(0);
   691 #ifdef __clang_analyzer__
   692       // PR libstdc++/82481
   693       __once_callable = nullptr;
   694       __once_call = nullptr;
   698    __throw_system_error(__e);
   700 #endif // _GLIBCXX_HAS_GTHREADS
   703 _GLIBCXX_END_NAMESPACE_VERSION
   705 #endif // _GLIBCXX_USE_C99_STDINT_TR1
   709 #endif // _GLIBCXX_MUTEX