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> // Variadic lock_guard only provided in ABI V2.
    113 class lock_guard
    114 {
    115 public:
    116     explicit lock_guard(MutexTypes&... m);
    117     lock_guard(MutexTypes&... m, adopt_lock_t);
    118     ~lock_guard();
    119     lock_guard(lock_guard const&) = delete;
    120     lock_guard& operator=(lock_guard const&) = delete;
    121 private:
    122     tuple<MutexTypes&...> pm; // exposition only
    123 };
    124 
    125 template <class Mutex>
    126 class unique_lock
    127 {
    128 public:
    129     typedef Mutex mutex_type;
    130     unique_lock() noexcept;
    131     explicit unique_lock(mutex_type& m);
    132     unique_lock(mutex_type& m, defer_lock_t) noexcept;
    133     unique_lock(mutex_type& m, try_to_lock_t);
    134     unique_lock(mutex_type& m, adopt_lock_t);
    135     template <class Clock, class Duration>
    136         unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
    137     template <class Rep, class Period>
    138         unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
    139     ~unique_lock();
    140 
    141     unique_lock(unique_lock const&) = delete;
    142     unique_lock& operator=(unique_lock const&) = delete;
    143 
    144     unique_lock(unique_lock&& u) noexcept;
    145     unique_lock& operator=(unique_lock&& u) noexcept;
    146 
    147     void lock();
    148     bool try_lock();
    149 
    150     template <class Rep, class Period>
    151         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
    152     template <class Clock, class Duration>
    153         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
    154 
    155     void unlock();
    156 
    157     void swap(unique_lock& u) noexcept;
    158     mutex_type* release() noexcept;
    159 
    160     bool owns_lock() const noexcept;
    161     explicit operator bool () const noexcept;
    162     mutex_type* mutex() const noexcept;
    163 };
    164 
    165 template <class Mutex>
    166   void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
    167 
    168 template <class L1, class L2, class... L3>
    169   int try_lock(L1&, L2&, L3&...);
    170 template <class L1, class L2, class... L3>
    171   void lock(L1&, L2&, L3&...);
    172 
    173 struct once_flag
    174 {
    175     constexpr once_flag() noexcept;
    176 
    177     once_flag(const once_flag&) = delete;
    178     once_flag& operator=(const once_flag&) = delete;
    179 };
    180 
    181 template<class Callable, class ...Args>
    182   void call_once(once_flag& flag, Callable&& func, Args&&... args);
    183 
    184 }  // std
    185 
    186 */
    187 
    188 #include <__config>
    189 #include <__mutex_base>
    190 #include <functional>
    191 #include <memory>
    192 #ifndef _LIBCPP_HAS_NO_VARIADICS
    193 #include <tuple>
    194 #endif
    195 #include <__threading_support>
    196 
    197 #include <__undef_min_max>
    198 
    199 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
    200 #pragma GCC system_header
    201 #endif
    202 
    203 _LIBCPP_BEGIN_NAMESPACE_STD
    204 
    205 #ifndef _LIBCPP_HAS_NO_THREADS
    206 
    207 class _LIBCPP_TYPE_VIS recursive_mutex
    208 {
    209     __libcpp_recursive_mutex_t __m_;
    210 
    211 public:
    212      recursive_mutex();
    213      ~recursive_mutex();
    214 
    215 private:
    216     recursive_mutex(const recursive_mutex&); // = delete;
    217     recursive_mutex& operator=(const recursive_mutex&); // = delete;
    218 
    219 public:
    220     void lock();
    221     bool try_lock() _NOEXCEPT;
    222     void unlock()  _NOEXCEPT;
    223 
    224     typedef __libcpp_recursive_mutex_t* native_handle_type;
    225 
    226     _LIBCPP_INLINE_VISIBILITY
    227     native_handle_type native_handle() {return &__m_;}
    228 };
    229 
    230 class _LIBCPP_TYPE_VIS timed_mutex
    231 {
    232     mutex              __m_;
    233     condition_variable __cv_;
    234     bool               __locked_;
    235 public:
    236      timed_mutex();
    237      ~timed_mutex();
    238 
    239 private:
    240     timed_mutex(const timed_mutex&); // = delete;
    241     timed_mutex& operator=(const timed_mutex&); // = delete;
    242 
    243 public:
    244     void lock();
    245     bool try_lock() _NOEXCEPT;
    246     template <class _Rep, class _Period>
    247         _LIBCPP_INLINE_VISIBILITY
    248         bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
    249             {return try_lock_until(chrono::steady_clock::now() + __d);}
    250     template <class _Clock, class _Duration>
    251         _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
    252         bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
    253     void unlock() _NOEXCEPT;
    254 };
    255 
    256 template <class _Clock, class _Duration>
    257 bool
    258 timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
    259 {
    260     using namespace chrono;
    261     unique_lock<mutex> __lk(__m_);
    262     bool no_timeout = _Clock::now() < __t;
    263     while (no_timeout && __locked_)
    264         no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
    265     if (!__locked_)
    266     {
    267         __locked_ = true;
    268         return true;
    269     }
    270     return false;
    271 }
    272 
    273 class _LIBCPP_TYPE_VIS recursive_timed_mutex
    274 {
    275     mutex              __m_;
    276     condition_variable __cv_;
    277     size_t             __count_;
    278     __libcpp_thread_id __id_;
    279 public:
    280      recursive_timed_mutex();
    281      ~recursive_timed_mutex();
    282 
    283 private:
    284     recursive_timed_mutex(const recursive_timed_mutex&); // = delete;
    285     recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete;
    286 
    287 public:
    288     void lock();
    289     bool try_lock() _NOEXCEPT;
    290     template <class _Rep, class _Period>
    291         _LIBCPP_INLINE_VISIBILITY
    292         bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
    293             {return try_lock_until(chrono::steady_clock::now() + __d);}
    294     template <class _Clock, class _Duration>
    295         _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
    296         bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
    297     void unlock() _NOEXCEPT;
    298 };
    299 
    300 template <class _Clock, class _Duration>
    301 bool
    302 recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
    303 {
    304     using namespace chrono;
    305     __libcpp_thread_id __id = __libcpp_thread_get_current_id();
    306     unique_lock<mutex> lk(__m_);
    307     if (__libcpp_thread_id_equal(__id, __id_))
    308     {
    309         if (__count_ == numeric_limits<size_t>::max())
    310             return false;
    311         ++__count_;
    312         return true;
    313     }
    314     bool no_timeout = _Clock::now() < __t;
    315     while (no_timeout && __count_ != 0)
    316         no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout;
    317     if (__count_ == 0)
    318     {
    319         __count_ = 1;
    320         __id_ = __id;
    321         return true;
    322     }
    323     return false;
    324 }
    325 
    326 template <class _L0, class _L1>
    327 int
    328 try_lock(_L0& __l0, _L1& __l1)
    329 {
    330     unique_lock<_L0> __u0(__l0, try_to_lock);
    331     if (__u0.owns_lock())
    332     {
    333         if (__l1.try_lock())
    334         {
    335             __u0.release();
    336             return -1;
    337         }
    338         else
    339             return 1;
    340     }
    341     return 0;
    342 }
    343 
    344 #ifndef _LIBCPP_HAS_NO_VARIADICS
    345 
    346 template <class _L0, class _L1, class _L2, class... _L3>
    347 int
    348 try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3)
    349 {
    350     int __r = 0;
    351     unique_lock<_L0> __u0(__l0, try_to_lock);
    352     if (__u0.owns_lock())
    353     {
    354         __r = try_lock(__l1, __l2, __l3...);
    355         if (__r == -1)
    356             __u0.release();
    357         else
    358             ++__r;
    359     }
    360     return __r;
    361 }
    362 
    363 #endif  // _LIBCPP_HAS_NO_VARIADICS
    364 
    365 template <class _L0, class _L1>
    366 void
    367 lock(_L0& __l0, _L1& __l1)
    368 {
    369     while (true)
    370     {
    371         {
    372             unique_lock<_L0> __u0(__l0);
    373             if (__l1.try_lock())
    374             {
    375                 __u0.release();
    376                 break;
    377             }
    378         }
    379         __libcpp_thread_yield();
    380         {
    381             unique_lock<_L1> __u1(__l1);
    382             if (__l0.try_lock())
    383             {
    384                 __u1.release();
    385                 break;
    386             }
    387         }
    388         __libcpp_thread_yield();
    389     }
    390 }
    391 
    392 #ifndef _LIBCPP_HAS_NO_VARIADICS
    393 
    394 template <class _L0, class _L1, class _L2, class ..._L3>
    395 void
    396 __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
    397 {
    398     while (true)
    399     {
    400         switch (__i)
    401         {
    402         case 0:
    403             {
    404                 unique_lock<_L0> __u0(__l0);
    405                 __i = try_lock(__l1, __l2, __l3...);
    406                 if (__i == -1)
    407                 {
    408                     __u0.release();
    409                     return;
    410                 }
    411             }
    412             ++__i;
    413             __libcpp_thread_yield();
    414             break;
    415         case 1:
    416             {
    417                 unique_lock<_L1> __u1(__l1);
    418                 __i = try_lock(__l2, __l3..., __l0);
    419                 if (__i == -1)
    420                 {
    421                     __u1.release();
    422                     return;
    423                 }
    424             }
    425             if (__i == sizeof...(_L3) + 1)
    426                 __i = 0;
    427             else
    428                 __i += 2;
    429             __libcpp_thread_yield();
    430             break;
    431         default:
    432             __lock_first(__i - 2, __l2, __l3..., __l0, __l1);
    433             return;
    434         }
    435     }
    436 }
    437 
    438 template <class _L0, class _L1, class _L2, class ..._L3>
    439 inline _LIBCPP_INLINE_VISIBILITY
    440 void
    441 lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
    442 {
    443     __lock_first(0, __l0, __l1, __l2, __l3...);
    444 }
    445 
    446 template <class _L0>
    447 inline _LIBCPP_INLINE_VISIBILITY
    448 void __unlock(_L0& __l0) {
    449     __l0.unlock();
    450 }
    451 
    452 template <class _L0, class _L1>
    453 inline _LIBCPP_INLINE_VISIBILITY
    454 void __unlock(_L0& __l0, _L1& __l1) {
    455     __l0.unlock();
    456     __l1.unlock();
    457 }
    458 
    459 template <class _L0, class _L1, class _L2, class ..._L3>
    460 inline _LIBCPP_INLINE_VISIBILITY
    461 void __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
    462     __l0.unlock();
    463     __l1.unlock();
    464     _VSTD::__unlock(__l2, __l3...);
    465 }
    466 
    467 #endif  // _LIBCPP_HAS_NO_VARIADICS
    468 
    469 #endif // !_LIBCPP_HAS_NO_THREADS
    470 
    471 struct _LIBCPP_TEMPLATE_VIS once_flag;
    472 
    473 #ifndef _LIBCPP_HAS_NO_VARIADICS
    474 
    475 template<class _Callable, class... _Args>
    476 _LIBCPP_INLINE_VISIBILITY
    477 void call_once(once_flag&, _Callable&&, _Args&&...);
    478 
    479 #else  // _LIBCPP_HAS_NO_VARIADICS
    480 
    481 template<class _Callable>
    482 _LIBCPP_INLINE_VISIBILITY
    483 void call_once(once_flag&, _Callable&);
    484 
    485 template<class _Callable>
    486 _LIBCPP_INLINE_VISIBILITY
    487 void call_once(once_flag&, const _Callable&);
    488 
    489 #endif  // _LIBCPP_HAS_NO_VARIADICS
    490 
    491 struct _LIBCPP_TEMPLATE_VIS once_flag
    492 {
    493     _LIBCPP_INLINE_VISIBILITY
    494     _LIBCPP_CONSTEXPR
    495         once_flag() _NOEXCEPT : __state_(0) {}
    496 
    497 private:
    498     once_flag(const once_flag&); // = delete;
    499     once_flag& operator=(const once_flag&); // = delete;
    500 
    501     unsigned long __state_;
    502 
    503 #ifndef _LIBCPP_HAS_NO_VARIADICS
    504     template<class _Callable, class... _Args>
    505     friend
    506     void call_once(once_flag&, _Callable&&, _Args&&...);
    507 #else  // _LIBCPP_HAS_NO_VARIADICS
    508     template<class _Callable>
    509     friend
    510     void call_once(once_flag&, _Callable&);
    511 
    512     template<class _Callable>
    513     friend
    514     void call_once(once_flag&, const _Callable&);
    515 #endif  // _LIBCPP_HAS_NO_VARIADICS
    516 };
    517 
    518 #ifndef _LIBCPP_HAS_NO_VARIADICS
    519 
    520 template <class _Fp>
    521 class __call_once_param
    522 {
    523     _Fp& __f_;
    524 public:
    525     _LIBCPP_INLINE_VISIBILITY
    526     explicit __call_once_param(_Fp& __f) : __f_(__f) {}
    527 
    528     _LIBCPP_INLINE_VISIBILITY
    529     void operator()()
    530     {
    531         typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
    532         __execute(_Index());
    533     }
    534 
    535 private:
    536     template <size_t ..._Indices>
    537     _LIBCPP_INLINE_VISIBILITY
    538     void __execute(__tuple_indices<_Indices...>)
    539     {
    540         __invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...);
    541     }
    542 };
    543 
    544 #else
    545 
    546 template <class _Fp>
    547 class __call_once_param
    548 {
    549     _Fp& __f_;
    550 public:
    551     _LIBCPP_INLINE_VISIBILITY
    552     explicit __call_once_param(_Fp& __f) : __f_(__f) {}
    553 
    554     _LIBCPP_INLINE_VISIBILITY
    555     void operator()()
    556     {
    557         __f_();
    558     }
    559 };
    560 
    561 #endif
    562 
    563 template <class _Fp>
    564 void
    565 __call_once_proxy(void* __vp)
    566 {
    567     __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);
    568     (*__p)();
    569 }
    570 
    571 _LIBCPP_FUNC_VIS void __call_once(volatile unsigned long&, void*, void(*)(void*));
    572 
    573 #ifndef _LIBCPP_HAS_NO_VARIADICS
    574 
    575 template<class _Callable, class... _Args>
    576 inline _LIBCPP_INLINE_VISIBILITY
    577 void
    578 call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args)
    579 {
    580     if (__libcpp_acquire_load(&__flag.__state_) != ~0ul)
    581     {
    582         typedef tuple<_Callable&&, _Args&&...> _Gp;
    583         _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...);
    584         __call_once_param<_Gp> __p(__f);
    585         __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
    586     }
    587 }
    588 
    589 #else  // _LIBCPP_HAS_NO_VARIADICS
    590 
    591 template<class _Callable>
    592 inline _LIBCPP_INLINE_VISIBILITY
    593 void
    594 call_once(once_flag& __flag, _Callable& __func)
    595 {
    596     if (__libcpp_acquire_load(&__flag.__state_) != ~0ul)
    597     {
    598         __call_once_param<_Callable> __p(__func);
    599         __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>);
    600     }
    601 }
    602 
    603 template<class _Callable>
    604 inline _LIBCPP_INLINE_VISIBILITY
    605 void
    606 call_once(once_flag& __flag, const _Callable& __func)
    607 {
    608     if (__flag.__state_ != ~0ul)
    609     {
    610         __call_once_param<const _Callable> __p(__func);
    611         __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>);
    612     }
    613 }
    614 
    615 #endif  // _LIBCPP_HAS_NO_VARIADICS
    616 
    617 
    618 #if defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD) \
    619     && !defined(_LIBCPP_CXX03_LANG)
    620 template <>
    621 class _LIBCPP_TEMPLATE_VIS lock_guard<> {
    622 public:
    623     explicit lock_guard() {}
    624     ~lock_guard() = default;
    625 
    626     _LIBCPP_INLINE_VISIBILITY
    627     explicit lock_guard(adopt_lock_t) {}
    628 
    629     lock_guard(lock_guard const&) = delete;
    630     lock_guard& operator=(lock_guard const&) = delete;
    631 };
    632 
    633 template <class ..._MArgs>
    634 class _LIBCPP_TEMPLATE_VIS lock_guard
    635 {
    636     static_assert(sizeof...(_MArgs) >= 2, "At least 2 lock types required");
    637     typedef tuple<_MArgs&...> _MutexTuple;
    638 
    639 public:
    640     _LIBCPP_INLINE_VISIBILITY
    641     explicit lock_guard(_MArgs&... __margs)
    642       : __t_(__margs...)
    643     {
    644         _VSTD::lock(__margs...);
    645     }
    646 
    647     _LIBCPP_INLINE_VISIBILITY
    648     lock_guard(_MArgs&... __margs, adopt_lock_t)
    649         : __t_(__margs...)
    650     {
    651     }
    652 
    653     _LIBCPP_INLINE_VISIBILITY
    654     ~lock_guard() {
    655         typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
    656         __unlock_unpack(_Indices{}, __t_);
    657     }
    658 
    659     lock_guard(lock_guard const&) = delete;
    660     lock_guard& operator=(lock_guard const&) = delete;
    661 
    662 private:
    663     template <size_t ..._Indx>
    664     _LIBCPP_INLINE_VISIBILITY
    665     static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) {
    666         _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...);
    667     }
    668 
    669     _MutexTuple __t_;
    670 };
    671 
    672 #endif // _LIBCPP_ABI_VARIADIC_LOCK_GUARD
    673 
    674 _LIBCPP_END_NAMESPACE_STD
    675 
    676 #endif  // _LIBCPP_MUTEX
    677