Home | History | Annotate | Download | only in v1
      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 constexpr defer_lock_t  defer_lock{};
     95 constexpr try_to_lock_t try_to_lock{};
     96 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 <__threading_support>
    198 
    199 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
    200 #pragma GCC system_header
    201 #endif
    202 
    203 _LIBCPP_PUSH_MACROS
    204 #include <__undef_macros>
    205 
    206 
    207 _LIBCPP_BEGIN_NAMESPACE_STD
    208 
    209 #ifndef _LIBCPP_HAS_NO_THREADS
    210 
    211 class _LIBCPP_TYPE_VIS recursive_mutex
    212 {
    213     __libcpp_recursive_mutex_t __m_;
    214 
    215 public:
    216      recursive_mutex();
    217      ~recursive_mutex();
    218 
    219 private:
    220     recursive_mutex(const recursive_mutex&); // = delete;
    221     recursive_mutex& operator=(const recursive_mutex&); // = delete;
    222 
    223 public:
    224     void lock();
    225     bool try_lock() _NOEXCEPT;
    226     void unlock()  _NOEXCEPT;
    227 
    228     typedef __libcpp_recursive_mutex_t* native_handle_type;
    229 
    230     _LIBCPP_INLINE_VISIBILITY
    231     native_handle_type native_handle() {return &__m_;}
    232 };
    233 
    234 class _LIBCPP_TYPE_VIS timed_mutex
    235 {
    236     mutex              __m_;
    237     condition_variable __cv_;
    238     bool               __locked_;
    239 public:
    240      timed_mutex();
    241      ~timed_mutex();
    242 
    243 private:
    244     timed_mutex(const timed_mutex&); // = delete;
    245     timed_mutex& operator=(const timed_mutex&); // = delete;
    246 
    247 public:
    248     void lock();
    249     bool try_lock() _NOEXCEPT;
    250     template <class _Rep, class _Period>
    251         _LIBCPP_INLINE_VISIBILITY
    252         bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
    253             {return try_lock_until(chrono::steady_clock::now() + __d);}
    254     template <class _Clock, class _Duration>
    255         _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
    256         bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
    257     void unlock() _NOEXCEPT;
    258 };
    259 
    260 template <class _Clock, class _Duration>
    261 bool
    262 timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
    263 {
    264     using namespace chrono;
    265     unique_lock<mutex> __lk(__m_);
    266     bool no_timeout = _Clock::now() < __t;
    267     while (no_timeout && __locked_)
    268         no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
    269     if (!__locked_)
    270     {
    271         __locked_ = true;
    272         return true;
    273     }
    274     return false;
    275 }
    276 
    277 class _LIBCPP_TYPE_VIS recursive_timed_mutex
    278 {
    279     mutex              __m_;
    280     condition_variable __cv_;
    281     size_t             __count_;
    282     __libcpp_thread_id __id_;
    283 public:
    284      recursive_timed_mutex();
    285      ~recursive_timed_mutex();
    286 
    287 private:
    288     recursive_timed_mutex(const recursive_timed_mutex&); // = delete;
    289     recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete;
    290 
    291 public:
    292     void lock();
    293     bool try_lock() _NOEXCEPT;
    294     template <class _Rep, class _Period>
    295         _LIBCPP_INLINE_VISIBILITY
    296         bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
    297             {return try_lock_until(chrono::steady_clock::now() + __d);}
    298     template <class _Clock, class _Duration>
    299         _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
    300         bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
    301     void unlock() _NOEXCEPT;
    302 };
    303 
    304 template <class _Clock, class _Duration>
    305 bool
    306 recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
    307 {
    308     using namespace chrono;
    309     __libcpp_thread_id __id = __libcpp_thread_get_current_id();
    310     unique_lock<mutex> lk(__m_);
    311     if (__libcpp_thread_id_equal(__id, __id_))
    312     {
    313         if (__count_ == numeric_limits<size_t>::max())
    314             return false;
    315         ++__count_;
    316         return true;
    317     }
    318     bool no_timeout = _Clock::now() < __t;
    319     while (no_timeout && __count_ != 0)
    320         no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout;
    321     if (__count_ == 0)
    322     {
    323         __count_ = 1;
    324         __id_ = __id;
    325         return true;
    326     }
    327     return false;
    328 }
    329 
    330 template <class _L0, class _L1>
    331 int
    332 try_lock(_L0& __l0, _L1& __l1)
    333 {
    334     unique_lock<_L0> __u0(__l0, try_to_lock);
    335     if (__u0.owns_lock())
    336     {
    337         if (__l1.try_lock())
    338         {
    339             __u0.release();
    340             return -1;
    341         }
    342         else
    343             return 1;
    344     }
    345     return 0;
    346 }
    347 
    348 #ifndef _LIBCPP_CXX03_LANG
    349 
    350 template <class _L0, class _L1, class _L2, class... _L3>
    351 int
    352 try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3)
    353 {
    354     int __r = 0;
    355     unique_lock<_L0> __u0(__l0, try_to_lock);
    356     if (__u0.owns_lock())
    357     {
    358         __r = try_lock(__l1, __l2, __l3...);
    359         if (__r == -1)
    360             __u0.release();
    361         else
    362             ++__r;
    363     }
    364     return __r;
    365 }
    366 
    367 #endif  // _LIBCPP_CXX03_LANG
    368 
    369 template <class _L0, class _L1>
    370 void
    371 lock(_L0& __l0, _L1& __l1)
    372 {
    373     while (true)
    374     {
    375         {
    376             unique_lock<_L0> __u0(__l0);
    377             if (__l1.try_lock())
    378             {
    379                 __u0.release();
    380                 break;
    381             }
    382         }
    383         __libcpp_thread_yield();
    384         {
    385             unique_lock<_L1> __u1(__l1);
    386             if (__l0.try_lock())
    387             {
    388                 __u1.release();
    389                 break;
    390             }
    391         }
    392         __libcpp_thread_yield();
    393     }
    394 }
    395 
    396 #ifndef _LIBCPP_CXX03_LANG
    397 
    398 template <class _L0, class _L1, class _L2, class ..._L3>
    399 void
    400 __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
    401 {
    402     while (true)
    403     {
    404         switch (__i)
    405         {
    406         case 0:
    407             {
    408                 unique_lock<_L0> __u0(__l0);
    409                 __i = try_lock(__l1, __l2, __l3...);
    410                 if (__i == -1)
    411                 {
    412                     __u0.release();
    413                     return;
    414                 }
    415             }
    416             ++__i;
    417             __libcpp_thread_yield();
    418             break;
    419         case 1:
    420             {
    421                 unique_lock<_L1> __u1(__l1);
    422                 __i = try_lock(__l2, __l3..., __l0);
    423                 if (__i == -1)
    424                 {
    425                     __u1.release();
    426                     return;
    427                 }
    428             }
    429             if (__i == sizeof...(_L3) + 1)
    430                 __i = 0;
    431             else
    432                 __i += 2;
    433             __libcpp_thread_yield();
    434             break;
    435         default:
    436             __lock_first(__i - 2, __l2, __l3..., __l0, __l1);
    437             return;
    438         }
    439     }
    440 }
    441 
    442 template <class _L0, class _L1, class _L2, class ..._L3>
    443 inline _LIBCPP_INLINE_VISIBILITY
    444 void
    445 lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
    446 {
    447     __lock_first(0, __l0, __l1, __l2, __l3...);
    448 }
    449 
    450 template <class _L0>
    451 inline _LIBCPP_INLINE_VISIBILITY
    452 void __unlock(_L0& __l0) {
    453     __l0.unlock();
    454 }
    455 
    456 template <class _L0, class _L1>
    457 inline _LIBCPP_INLINE_VISIBILITY
    458 void __unlock(_L0& __l0, _L1& __l1) {
    459     __l0.unlock();
    460     __l1.unlock();
    461 }
    462 
    463 template <class _L0, class _L1, class _L2, class ..._L3>
    464 inline _LIBCPP_INLINE_VISIBILITY
    465 void __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
    466     __l0.unlock();
    467     __l1.unlock();
    468     _VSTD::__unlock(__l2, __l3...);
    469 }
    470 
    471 #endif  // _LIBCPP_CXX03_LANG
    472 
    473 #if _LIBCPP_STD_VER > 14
    474 template <class ..._Mutexes>
    475 class _LIBCPP_TEMPLATE_VIS scoped_lock;
    476 
    477 template <>
    478 class _LIBCPP_TEMPLATE_VIS scoped_lock<> {
    479 public:
    480     explicit scoped_lock() {}
    481     ~scoped_lock() = default;
    482 
    483     _LIBCPP_INLINE_VISIBILITY
    484     explicit scoped_lock(adopt_lock_t) {}
    485 
    486     scoped_lock(scoped_lock const&) = delete;
    487     scoped_lock& operator=(scoped_lock const&) = delete;
    488 };
    489 
    490 template <class _Mutex>
    491 class _LIBCPP_TEMPLATE_VIS scoped_lock<_Mutex> {
    492 public:
    493     typedef _Mutex  mutex_type;
    494 private:
    495     mutex_type& __m_;
    496 public:
    497     explicit scoped_lock(mutex_type & __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
    498         : __m_(__m) {__m_.lock();}
    499 
    500     ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
    501 
    502     _LIBCPP_INLINE_VISIBILITY
    503     explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
    504         : __m_(__m) {}
    505 
    506     scoped_lock(scoped_lock const&) = delete;
    507     scoped_lock& operator=(scoped_lock const&) = delete;
    508 };
    509 
    510 template <class ..._MArgs>
    511 class _LIBCPP_TEMPLATE_VIS scoped_lock
    512 {
    513     static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required");
    514     typedef tuple<_MArgs&...> _MutexTuple;
    515 
    516 public:
    517     _LIBCPP_INLINE_VISIBILITY
    518     explicit scoped_lock(_MArgs&... __margs)
    519       : __t_(__margs...)
    520     {
    521         _VSTD::lock(__margs...);
    522     }
    523 
    524     _LIBCPP_INLINE_VISIBILITY
    525     scoped_lock(adopt_lock_t, _MArgs&... __margs)
    526         : __t_(__margs...)
    527     {
    528     }
    529 
    530     _LIBCPP_INLINE_VISIBILITY
    531     ~scoped_lock() {
    532         typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
    533         __unlock_unpack(_Indices{}, __t_);
    534     }
    535 
    536     scoped_lock(scoped_lock const&) = delete;
    537     scoped_lock& operator=(scoped_lock const&) = delete;
    538 
    539 private:
    540     template <size_t ..._Indx>
    541     _LIBCPP_INLINE_VISIBILITY
    542     static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) {
    543         _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...);
    544     }
    545 
    546     _MutexTuple __t_;
    547 };
    548 
    549 #endif // _LIBCPP_STD_VER > 14
    550 #endif // !_LIBCPP_HAS_NO_THREADS
    551 
    552 struct _LIBCPP_TEMPLATE_VIS once_flag;
    553 
    554 #ifndef _LIBCPP_CXX03_LANG
    555 
    556 template<class _Callable, class... _Args>
    557 _LIBCPP_INLINE_VISIBILITY
    558 void call_once(once_flag&, _Callable&&, _Args&&...);
    559 
    560 #else  // _LIBCPP_CXX03_LANG
    561 
    562 template<class _Callable>
    563 _LIBCPP_INLINE_VISIBILITY
    564 void call_once(once_flag&, _Callable&);
    565 
    566 template<class _Callable>
    567 _LIBCPP_INLINE_VISIBILITY
    568 void call_once(once_flag&, const _Callable&);
    569 
    570 #endif  // _LIBCPP_CXX03_LANG
    571 
    572 struct _LIBCPP_TEMPLATE_VIS once_flag
    573 {
    574     _LIBCPP_INLINE_VISIBILITY
    575     _LIBCPP_CONSTEXPR
    576         once_flag() _NOEXCEPT : __state_(0) {}
    577 
    578 private:
    579     once_flag(const once_flag&); // = delete;
    580     once_flag& operator=(const once_flag&); // = delete;
    581 
    582     unsigned long __state_;
    583 
    584 #ifndef _LIBCPP_CXX03_LANG
    585     template<class _Callable, class... _Args>
    586     friend
    587     void call_once(once_flag&, _Callable&&, _Args&&...);
    588 #else  // _LIBCPP_CXX03_LANG
    589     template<class _Callable>
    590     friend
    591     void call_once(once_flag&, _Callable&);
    592 
    593     template<class _Callable>
    594     friend
    595     void call_once(once_flag&, const _Callable&);
    596 #endif  // _LIBCPP_CXX03_LANG
    597 };
    598 
    599 #ifndef _LIBCPP_CXX03_LANG
    600 
    601 template <class _Fp>
    602 class __call_once_param
    603 {
    604     _Fp& __f_;
    605 public:
    606     _LIBCPP_INLINE_VISIBILITY
    607     explicit __call_once_param(_Fp& __f) : __f_(__f) {}
    608 
    609     _LIBCPP_INLINE_VISIBILITY
    610     void operator()()
    611     {
    612         typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
    613         __execute(_Index());
    614     }
    615 
    616 private:
    617     template <size_t ..._Indices>
    618     _LIBCPP_INLINE_VISIBILITY
    619     void __execute(__tuple_indices<_Indices...>)
    620     {
    621         __invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...);
    622     }
    623 };
    624 
    625 #else
    626 
    627 template <class _Fp>
    628 class __call_once_param
    629 {
    630     _Fp& __f_;
    631 public:
    632     _LIBCPP_INLINE_VISIBILITY
    633     explicit __call_once_param(_Fp& __f) : __f_(__f) {}
    634 
    635     _LIBCPP_INLINE_VISIBILITY
    636     void operator()()
    637     {
    638         __f_();
    639     }
    640 };
    641 
    642 #endif
    643 
    644 template <class _Fp>
    645 void
    646 __call_once_proxy(void* __vp)
    647 {
    648     __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);
    649     (*__p)();
    650 }
    651 
    652 _LIBCPP_FUNC_VIS void __call_once(volatile unsigned long&, void*, void(*)(void*));
    653 
    654 #ifndef _LIBCPP_CXX03_LANG
    655 
    656 template<class _Callable, class... _Args>
    657 inline _LIBCPP_INLINE_VISIBILITY
    658 void
    659 call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args)
    660 {
    661     if (__libcpp_acquire_load(&__flag.__state_) != ~0ul)
    662     {
    663         typedef tuple<_Callable&&, _Args&&...> _Gp;
    664         _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...);
    665         __call_once_param<_Gp> __p(__f);
    666         __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
    667     }
    668 }
    669 
    670 #else  // _LIBCPP_CXX03_LANG
    671 
    672 template<class _Callable>
    673 inline _LIBCPP_INLINE_VISIBILITY
    674 void
    675 call_once(once_flag& __flag, _Callable& __func)
    676 {
    677     if (__libcpp_acquire_load(&__flag.__state_) != ~0ul)
    678     {
    679         __call_once_param<_Callable> __p(__func);
    680         __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>);
    681     }
    682 }
    683 
    684 template<class _Callable>
    685 inline _LIBCPP_INLINE_VISIBILITY
    686 void
    687 call_once(once_flag& __flag, const _Callable& __func)
    688 {
    689     if (__libcpp_acquire_load(&__flag.__state_) != ~0ul)
    690     {
    691         __call_once_param<const _Callable> __p(__func);
    692         __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>);
    693     }
    694 }
    695 
    696 #endif  // _LIBCPP_CXX03_LANG
    697 
    698 _LIBCPP_END_NAMESPACE_STD
    699 
    700 _LIBCPP_POP_MACROS
    701 
    702 #endif  // _LIBCPP_MUTEX
    703