Home | History | Annotate | Download | only in include
      1 // -*- C++ -*-
      2 //===--------------------------- mutex ------------------------------------===//
      3 //
      4 //                     The LLVM Compiler Infrastructure
      5 //
      6 // This file is dual licensed under the MIT and the University of Illinois Open
      7 // Source Licenses. See LICENSE.TXT for details.
      8 //
      9 //===----------------------------------------------------------------------===//
     10 
     11 #ifndef _LIBCPP_MUTEX
     12 #define _LIBCPP_MUTEX
     13 
     14 /*
     15     mutex synopsis
     16 
     17 namespace std
     18 {
     19 
     20 class mutex
     21 {
     22 public:
     23      constexpr mutex() noexcept;
     24      ~mutex();
     25 
     26     mutex(const mutex&) = delete;
     27     mutex& operator=(const mutex&) = delete;
     28 
     29     void lock();
     30     bool try_lock();
     31     void unlock();
     32 
     33     typedef pthread_mutex_t* native_handle_type;
     34     native_handle_type native_handle();
     35 };
     36 
     37 class recursive_mutex
     38 {
     39 public:
     40      recursive_mutex();
     41      ~recursive_mutex();
     42 
     43     recursive_mutex(const recursive_mutex&) = delete;
     44     recursive_mutex& operator=(const recursive_mutex&) = delete;
     45 
     46     void lock();
     47     bool try_lock() noexcept;
     48     void unlock();
     49 
     50     typedef pthread_mutex_t* native_handle_type;
     51     native_handle_type native_handle();
     52 };
     53 
     54 class timed_mutex
     55 {
     56 public:
     57      timed_mutex();
     58      ~timed_mutex();
     59 
     60     timed_mutex(const timed_mutex&) = delete;
     61     timed_mutex& operator=(const timed_mutex&) = delete;
     62 
     63     void lock();
     64     bool try_lock();
     65     template <class Rep, class Period>
     66         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
     67     template <class Clock, class Duration>
     68         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
     69     void unlock();
     70 };
     71 
     72 class recursive_timed_mutex
     73 {
     74 public:
     75      recursive_timed_mutex();
     76      ~recursive_timed_mutex();
     77 
     78     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
     79     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
     80 
     81     void lock();
     82     bool try_lock() noexcept;
     83     template <class Rep, class Period>
     84         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
     85     template <class Clock, class Duration>
     86         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
     87     void unlock();
     88 };
     89 
     90 struct defer_lock_t {};
     91 struct try_to_lock_t {};
     92 struct adopt_lock_t {};
     93 
     94 inline constexpr defer_lock_t  defer_lock{};
     95 inline constexpr try_to_lock_t try_to_lock{};
     96 inline constexpr adopt_lock_t  adopt_lock{};
     97 
     98 template <class Mutex>
     99 class lock_guard
    100 {
    101 public:
    102     typedef Mutex mutex_type;
    103 
    104     explicit lock_guard(mutex_type& m);
    105     lock_guard(mutex_type& m, adopt_lock_t);
    106     ~lock_guard();
    107 
    108     lock_guard(lock_guard const&) = delete;
    109     lock_guard& operator=(lock_guard const&) = delete;
    110 };
    111 
    112 template <class... MutexTypes>
    113 class scoped_lock // C++17
    114 {
    115 public:
    116     using mutex_type = Mutex;  // If MutexTypes... consists of the single type Mutex
    117 
    118     explicit scoped_lock(MutexTypes&... m);
    119     scoped_lock(adopt_lock_t, MutexTypes&... m);
    120     ~scoped_lock();
    121     scoped_lock(scoped_lock const&) = delete;
    122     scoped_lock& operator=(scoped_lock const&) = delete;
    123 private:
    124     tuple<MutexTypes&...> pm; // exposition only
    125 };
    126 
    127 template <class Mutex>
    128 class unique_lock
    129 {
    130 public:
    131     typedef Mutex mutex_type;
    132     unique_lock() noexcept;
    133     explicit unique_lock(mutex_type& m);
    134     unique_lock(mutex_type& m, defer_lock_t) noexcept;
    135     unique_lock(mutex_type& m, try_to_lock_t);
    136     unique_lock(mutex_type& m, adopt_lock_t);
    137     template <class Clock, class Duration>
    138         unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
    139     template <class Rep, class Period>
    140         unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
    141     ~unique_lock();
    142 
    143     unique_lock(unique_lock const&) = delete;
    144     unique_lock& operator=(unique_lock const&) = delete;
    145 
    146     unique_lock(unique_lock&& u) noexcept;
    147     unique_lock& operator=(unique_lock&& u) noexcept;
    148 
    149     void lock();
    150     bool try_lock();
    151 
    152     template <class Rep, class Period>
    153         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
    154     template <class Clock, class Duration>
    155         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
    156 
    157     void unlock();
    158 
    159     void swap(unique_lock& u) noexcept;
    160     mutex_type* release() noexcept;
    161 
    162     bool owns_lock() const noexcept;
    163     explicit operator bool () const noexcept;
    164     mutex_type* mutex() const noexcept;
    165 };
    166 
    167 template <class Mutex>
    168   void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
    169 
    170 template <class L1, class L2, class... L3>
    171   int try_lock(L1&, L2&, L3&...);
    172 template <class L1, class L2, class... L3>
    173   void lock(L1&, L2&, L3&...);
    174 
    175 struct once_flag
    176 {
    177     constexpr once_flag() noexcept;
    178 
    179     once_flag(const once_flag&) = delete;
    180     once_flag& operator=(const once_flag&) = delete;
    181 };
    182 
    183 template<class Callable, class ...Args>
    184   void call_once(once_flag& flag, Callable&& func, Args&&... args);
    185 
    186 }  // std
    187 
    188 */
    189 
    190 #include <__config>
    191 #include <__mutex_base>
    192 #include <functional>
    193 #include <memory>
    194 #ifndef _LIBCPP_CXX03_LANG
    195 #include <tuple>
    196 #endif
    197 #include <version>
    198 #include <__threading_support>
    199 
    200 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
    201 #pragma GCC system_header
    202 #endif
    203 
    204 _LIBCPP_PUSH_MACROS
    205 #include <__undef_macros>
    206 
    207 
    208 _LIBCPP_BEGIN_NAMESPACE_STD
    209 
    210 #ifndef _LIBCPP_HAS_NO_THREADS
    211 
    212 class _LIBCPP_TYPE_VIS recursive_mutex
    213 {
    214     __libcpp_recursive_mutex_t __m_;
    215 
    216 public:
    217      recursive_mutex();
    218      ~recursive_mutex();
    219 
    220 private:
    221     recursive_mutex(const recursive_mutex&); // = delete;
    222     recursive_mutex& operator=(const recursive_mutex&); // = delete;
    223 
    224 public:
    225     void lock();
    226     bool try_lock() _NOEXCEPT;
    227     void unlock()  _NOEXCEPT;
    228 
    229     typedef __libcpp_recursive_mutex_t* native_handle_type;
    230 
    231     _LIBCPP_INLINE_VISIBILITY
    232     native_handle_type native_handle() {return &__m_;}
    233 };
    234 
    235 class _LIBCPP_TYPE_VIS timed_mutex
    236 {
    237     mutex              __m_;
    238     condition_variable __cv_;
    239     bool               __locked_;
    240 public:
    241      timed_mutex();
    242      ~timed_mutex();
    243 
    244 private:
    245     timed_mutex(const timed_mutex&); // = delete;
    246     timed_mutex& operator=(const timed_mutex&); // = delete;
    247 
    248 public:
    249     void lock();
    250     bool try_lock() _NOEXCEPT;
    251     template <class _Rep, class _Period>
    252         _LIBCPP_INLINE_VISIBILITY
    253         bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
    254             {return try_lock_until(chrono::steady_clock::now() + __d);}
    255     template <class _Clock, class _Duration>
    256         _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
    257         bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
    258     void unlock() _NOEXCEPT;
    259 };
    260 
    261 template <class _Clock, class _Duration>
    262 bool
    263 timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
    264 {
    265     using namespace chrono;
    266     unique_lock<mutex> __lk(__m_);
    267     bool no_timeout = _Clock::now() < __t;
    268     while (no_timeout && __locked_)
    269         no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
    270     if (!__locked_)
    271     {
    272         __locked_ = true;
    273         return true;
    274     }
    275     return false;
    276 }
    277 
    278 class _LIBCPP_TYPE_VIS recursive_timed_mutex
    279 {
    280     mutex              __m_;
    281     condition_variable __cv_;
    282     size_t             __count_;
    283     __libcpp_thread_id __id_;
    284 public:
    285      recursive_timed_mutex();
    286      ~recursive_timed_mutex();
    287 
    288 private:
    289     recursive_timed_mutex(const recursive_timed_mutex&); // = delete;
    290     recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete;
    291 
    292 public:
    293     void lock();
    294     bool try_lock() _NOEXCEPT;
    295     template <class _Rep, class _Period>
    296         _LIBCPP_INLINE_VISIBILITY
    297         bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
    298             {return try_lock_until(chrono::steady_clock::now() + __d);}
    299     template <class _Clock, class _Duration>
    300         _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
    301         bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
    302     void unlock() _NOEXCEPT;
    303 };
    304 
    305 template <class _Clock, class _Duration>
    306 bool
    307 recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
    308 {
    309     using namespace chrono;
    310     __libcpp_thread_id __id = __libcpp_thread_get_current_id();
    311     unique_lock<mutex> lk(__m_);
    312     if (__libcpp_thread_id_equal(__id, __id_))
    313     {
    314         if (__count_ == numeric_limits<size_t>::max())
    315             return false;
    316         ++__count_;
    317         return true;
    318     }
    319     bool no_timeout = _Clock::now() < __t;
    320     while (no_timeout && __count_ != 0)
    321         no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout;
    322     if (__count_ == 0)
    323     {
    324         __count_ = 1;
    325         __id_ = __id;
    326         return true;
    327     }
    328     return false;
    329 }
    330 
    331 template <class _L0, class _L1>
    332 int
    333 try_lock(_L0& __l0, _L1& __l1)
    334 {
    335     unique_lock<_L0> __u0(__l0, try_to_lock);
    336     if (__u0.owns_lock())
    337     {
    338         if (__l1.try_lock())
    339         {
    340             __u0.release();
    341             return -1;
    342         }
    343         else
    344             return 1;
    345     }
    346     return 0;
    347 }
    348 
    349 #ifndef _LIBCPP_CXX03_LANG
    350 
    351 template <class _L0, class _L1, class _L2, class... _L3>
    352 int
    353 try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3)
    354 {
    355     int __r = 0;
    356     unique_lock<_L0> __u0(__l0, try_to_lock);
    357     if (__u0.owns_lock())
    358     {
    359         __r = try_lock(__l1, __l2, __l3...);
    360         if (__r == -1)
    361             __u0.release();
    362         else
    363             ++__r;
    364     }
    365     return __r;
    366 }
    367 
    368 #endif  // _LIBCPP_CXX03_LANG
    369 
    370 template <class _L0, class _L1>
    371 void
    372 lock(_L0& __l0, _L1& __l1)
    373 {
    374     while (true)
    375     {
    376         {
    377             unique_lock<_L0> __u0(__l0);
    378             if (__l1.try_lock())
    379             {
    380                 __u0.release();
    381                 break;
    382             }
    383         }
    384         __libcpp_thread_yield();
    385         {
    386             unique_lock<_L1> __u1(__l1);
    387             if (__l0.try_lock())
    388             {
    389                 __u1.release();
    390                 break;
    391             }
    392         }
    393         __libcpp_thread_yield();
    394     }
    395 }
    396 
    397 #ifndef _LIBCPP_CXX03_LANG
    398 
    399 template <class _L0, class _L1, class _L2, class ..._L3>
    400 void
    401 __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
    402 {
    403     while (true)
    404     {
    405         switch (__i)
    406         {
    407         case 0:
    408             {
    409                 unique_lock<_L0> __u0(__l0);
    410                 __i = try_lock(__l1, __l2, __l3...);
    411                 if (__i == -1)
    412                 {
    413                     __u0.release();
    414                     return;
    415                 }
    416             }
    417             ++__i;
    418             __libcpp_thread_yield();
    419             break;
    420         case 1:
    421             {
    422                 unique_lock<_L1> __u1(__l1);
    423                 __i = try_lock(__l2, __l3..., __l0);
    424                 if (__i == -1)
    425                 {
    426                     __u1.release();
    427                     return;
    428                 }
    429             }
    430             if (__i == sizeof...(_L3) + 1)
    431                 __i = 0;
    432             else
    433                 __i += 2;
    434             __libcpp_thread_yield();
    435             break;
    436         default:
    437             __lock_first(__i - 2, __l2, __l3..., __l0, __l1);
    438             return;
    439         }
    440     }
    441 }
    442 
    443 template <class _L0, class _L1, class _L2, class ..._L3>
    444 inline _LIBCPP_INLINE_VISIBILITY
    445 void
    446 lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
    447 {
    448     __lock_first(0, __l0, __l1, __l2, __l3...);
    449 }
    450 
    451 template <class _L0>
    452 inline _LIBCPP_INLINE_VISIBILITY
    453 void __unlock(_L0& __l0) {
    454     __l0.unlock();
    455 }
    456 
    457 template <class _L0, class _L1>
    458 inline _LIBCPP_INLINE_VISIBILITY
    459 void __unlock(_L0& __l0, _L1& __l1) {
    460     __l0.unlock();
    461     __l1.unlock();
    462 }
    463 
    464 template <class _L0, class _L1, class _L2, class ..._L3>
    465 inline _LIBCPP_INLINE_VISIBILITY
    466 void __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
    467     __l0.unlock();
    468     __l1.unlock();
    469     _VSTD::__unlock(__l2, __l3...);
    470 }
    471 
    472 #endif  // _LIBCPP_CXX03_LANG
    473 
    474 #if _LIBCPP_STD_VER > 14
    475 template <class ..._Mutexes>
    476 class _LIBCPP_TEMPLATE_VIS scoped_lock;
    477 
    478 template <>
    479 class _LIBCPP_TEMPLATE_VIS scoped_lock<> {
    480 public:
    481     explicit scoped_lock() {}
    482     ~scoped_lock() = default;
    483 
    484     _LIBCPP_INLINE_VISIBILITY
    485     explicit scoped_lock(adopt_lock_t) {}
    486 
    487     scoped_lock(scoped_lock const&) = delete;
    488     scoped_lock& operator=(scoped_lock const&) = delete;
    489 };
    490 
    491 template <class _Mutex>
    492 class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> {
    493 public:
    494     typedef _Mutex  mutex_type;
    495 private:
    496     mutex_type& __m_;
    497 public:
    498     explicit scoped_lock(mutex_type & __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
    499         : __m_(__m) {__m_.lock();}
    500 
    501     ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
    502 
    503     _LIBCPP_INLINE_VISIBILITY
    504     explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
    505         : __m_(__m) {}
    506 
    507     scoped_lock(scoped_lock const&) = delete;
    508     scoped_lock& operator=(scoped_lock const&) = delete;
    509 };
    510 
    511 template <class ..._MArgs>
    512 class _LIBCPP_TEMPLATE_VIS scoped_lock
    513 {
    514     static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required");
    515     typedef tuple<_MArgs&...> _MutexTuple;
    516 
    517 public:
    518     _LIBCPP_INLINE_VISIBILITY
    519     explicit scoped_lock(_MArgs&... __margs)
    520       : __t_(__margs...)
    521     {
    522         _VSTD::lock(__margs...);
    523     }
    524 
    525     _LIBCPP_INLINE_VISIBILITY
    526     scoped_lock(adopt_lock_t, _MArgs&... __margs)
    527         : __t_(__margs...)
    528     {
    529     }
    530 
    531     _LIBCPP_INLINE_VISIBILITY
    532     ~scoped_lock() {
    533         typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
    534         __unlock_unpack(_Indices{}, __t_);
    535     }
    536 
    537     scoped_lock(scoped_lock const&) = delete;
    538     scoped_lock& operator=(scoped_lock const&) = delete;
    539 
    540 private:
    541     template <size_t ..._Indx>
    542     _LIBCPP_INLINE_VISIBILITY
    543     static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) {
    544         _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...);
    545     }
    546 
    547     _MutexTuple __t_;
    548 };
    549 
    550 #endif // _LIBCPP_STD_VER > 14
    551 #endif // !_LIBCPP_HAS_NO_THREADS
    552 
    553 struct _LIBCPP_TEMPLATE_VIS once_flag;
    554 
    555 #ifndef _LIBCPP_CXX03_LANG
    556 
    557 template<class _Callable, class... _Args>
    558 _LIBCPP_INLINE_VISIBILITY
    559 void call_once(once_flag&, _Callable&&, _Args&&...);
    560 
    561 #else  // _LIBCPP_CXX03_LANG
    562 
    563 template<class _Callable>
    564 _LIBCPP_INLINE_VISIBILITY
    565 void call_once(once_flag&, _Callable&);
    566 
    567 template<class _Callable>
    568 _LIBCPP_INLINE_VISIBILITY
    569 void call_once(once_flag&, const _Callable&);
    570 
    571 #endif  // _LIBCPP_CXX03_LANG
    572 
    573 struct _LIBCPP_TEMPLATE_VIS once_flag
    574 {
    575     _LIBCPP_INLINE_VISIBILITY
    576     _LIBCPP_CONSTEXPR
    577         once_flag() _NOEXCEPT : __state_(0) {}
    578 
    579 private:
    580     once_flag(const once_flag&); // = delete;
    581     once_flag& operator=(const once_flag&); // = delete;
    582 
    583     unsigned long __state_;
    584 
    585 #ifndef _LIBCPP_CXX03_LANG
    586     template<class _Callable, class... _Args>
    587     friend
    588     void call_once(once_flag&, _Callable&&, _Args&&...);
    589 #else  // _LIBCPP_CXX03_LANG
    590     template<class _Callable>
    591     friend
    592     void call_once(once_flag&, _Callable&);
    593 
    594     template<class _Callable>
    595     friend
    596     void call_once(once_flag&, const _Callable&);
    597 #endif  // _LIBCPP_CXX03_LANG
    598 };
    599 
    600 #ifndef _LIBCPP_CXX03_LANG
    601 
    602 template <class _Fp>
    603 class __call_once_param
    604 {
    605     _Fp& __f_;
    606 public:
    607     _LIBCPP_INLINE_VISIBILITY
    608     explicit __call_once_param(_Fp& __f) : __f_(__f) {}
    609 
    610     _LIBCPP_INLINE_VISIBILITY
    611     void operator()()
    612     {
    613         typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
    614         __execute(_Index());
    615     }
    616 
    617 private:
    618     template <size_t ..._Indices>
    619     _LIBCPP_INLINE_VISIBILITY
    620     void __execute(__tuple_indices<_Indices...>)
    621     {
    622         __invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...);
    623     }
    624 };
    625 
    626 #else
    627 
    628 template <class _Fp>
    629 class __call_once_param
    630 {
    631     _Fp& __f_;
    632 public:
    633     _LIBCPP_INLINE_VISIBILITY
    634     explicit __call_once_param(_Fp& __f) : __f_(__f) {}
    635 
    636     _LIBCPP_INLINE_VISIBILITY
    637     void operator()()
    638     {
    639         __f_();
    640     }
    641 };
    642 
    643 #endif
    644 
    645 template <class _Fp>
    646 void
    647 __call_once_proxy(void* __vp)
    648 {
    649     __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);
    650     (*__p)();
    651 }
    652 
    653 _LIBCPP_FUNC_VIS void __call_once(volatile unsigned long&, void*, void(*)(void*));
    654 
    655 #ifndef _LIBCPP_CXX03_LANG
    656 
    657 template<class _Callable, class... _Args>
    658 inline _LIBCPP_INLINE_VISIBILITY
    659 void
    660 call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args)
    661 {
    662     if (__libcpp_acquire_load(&__flag.__state_) != ~0ul)
    663     {
    664         typedef tuple<_Callable&&, _Args&&...> _Gp;
    665         _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...);
    666         __call_once_param<_Gp> __p(__f);
    667         __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
    668     }
    669 }
    670 
    671 #else  // _LIBCPP_CXX03_LANG
    672 
    673 template<class _Callable>
    674 inline _LIBCPP_INLINE_VISIBILITY
    675 void
    676 call_once(once_flag& __flag, _Callable& __func)
    677 {
    678     if (__libcpp_acquire_load(&__flag.__state_) != ~0ul)
    679     {
    680         __call_once_param<_Callable> __p(__func);
    681         __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>);
    682     }
    683 }
    684 
    685 template<class _Callable>
    686 inline _LIBCPP_INLINE_VISIBILITY
    687 void
    688 call_once(once_flag& __flag, const _Callable& __func)
    689 {
    690     if (__libcpp_acquire_load(&__flag.__state_) != ~0ul)
    691     {
    692         __call_once_param<const _Callable> __p(__func);
    693         __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>);
    694     }
    695 }
    696 
    697 #endif  // _LIBCPP_CXX03_LANG
    698 
    699 _LIBCPP_END_NAMESPACE_STD
    700 
    701 _LIBCPP_POP_MACROS
    702 
    703 #endif  // _LIBCPP_MUTEX
    704