Home | History | Annotate | Download | only in include
      1 // -*- C++ -*-
      2 //===---------------------- condition_variable ----------------------------===//
      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_CONDITION_VARIABLE
     12 #define _LIBCPP_CONDITION_VARIABLE
     13 
     14 /*
     15     condition_variable synopsis
     16 
     17 namespace std
     18 {
     19 
     20 enum class cv_status { no_timeout, timeout };
     21 
     22 class condition_variable
     23 {
     24 public:
     25     condition_variable();
     26     ~condition_variable();
     27 
     28     condition_variable(const condition_variable&) = delete;
     29     condition_variable& operator=(const condition_variable&) = delete;
     30 
     31     void notify_one() noexcept;
     32     void notify_all() noexcept;
     33 
     34     void wait(unique_lock<mutex>& lock);
     35     template <class Predicate>
     36         void wait(unique_lock<mutex>& lock, Predicate pred);
     37 
     38     template <class Clock, class Duration>
     39         cv_status
     40         wait_until(unique_lock<mutex>& lock,
     41                    const chrono::time_point<Clock, Duration>& abs_time);
     42 
     43     template <class Clock, class Duration, class Predicate>
     44         bool
     45         wait_until(unique_lock<mutex>& lock,
     46                    const chrono::time_point<Clock, Duration>& abs_time,
     47                    Predicate pred);
     48 
     49     template <class Rep, class Period>
     50         cv_status
     51         wait_for(unique_lock<mutex>& lock,
     52                  const chrono::duration<Rep, Period>& rel_time);
     53 
     54     template <class Rep, class Period, class Predicate>
     55         bool
     56         wait_for(unique_lock<mutex>& lock,
     57                  const chrono::duration<Rep, Period>& rel_time,
     58                  Predicate pred);
     59 
     60     typedef pthread_cond_t* native_handle_type;
     61     native_handle_type native_handle();
     62 };
     63 
     64 void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
     65 
     66 class condition_variable_any
     67 {
     68 public:
     69     condition_variable_any();
     70     ~condition_variable_any();
     71 
     72     condition_variable_any(const condition_variable_any&) = delete;
     73     condition_variable_any& operator=(const condition_variable_any&) = delete;
     74 
     75     void notify_one() noexcept;
     76     void notify_all() noexcept;
     77 
     78     template <class Lock>
     79         void wait(Lock& lock);
     80     template <class Lock, class Predicate>
     81         void wait(Lock& lock, Predicate pred);
     82 
     83     template <class Lock, class Clock, class Duration>
     84         cv_status
     85         wait_until(Lock& lock,
     86                    const chrono::time_point<Clock, Duration>& abs_time);
     87 
     88     template <class Lock, class Clock, class Duration, class Predicate>
     89         bool
     90         wait_until(Lock& lock,
     91                    const chrono::time_point<Clock, Duration>& abs_time,
     92                    Predicate pred);
     93 
     94     template <class Lock, class Rep, class Period>
     95         cv_status
     96         wait_for(Lock& lock,
     97                  const chrono::duration<Rep, Period>& rel_time);
     98 
     99     template <class Lock, class Rep, class Period, class Predicate>
    100         bool
    101         wait_for(Lock& lock,
    102                  const chrono::duration<Rep, Period>& rel_time,
    103                  Predicate pred);
    104 };
    105 
    106 }  // std
    107 
    108 */
    109 
    110 #include <__config>
    111 #include <__mutex_base>
    112 #include <memory>
    113 
    114 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
    115 #pragma GCC system_header
    116 #endif
    117 
    118 _LIBCPP_BEGIN_NAMESPACE_STD
    119 
    120 class _LIBCPP_VISIBLE condition_variable_any
    121 {
    122     condition_variable __cv_;
    123     shared_ptr<mutex>  __mut_;
    124 public:
    125     condition_variable_any();
    126 
    127     void notify_one() _NOEXCEPT;
    128     void notify_all() _NOEXCEPT;
    129 
    130     template <class _Lock>
    131         void wait(_Lock& __lock);
    132     template <class _Lock, class _Predicate>
    133         void wait(_Lock& __lock, _Predicate __pred);
    134 
    135     template <class _Lock, class _Clock, class _Duration>
    136         cv_status
    137         wait_until(_Lock& __lock,
    138                    const chrono::time_point<_Clock, _Duration>& __t);
    139 
    140     template <class _Lock, class _Clock, class _Duration, class _Predicate>
    141         bool
    142         wait_until(_Lock& __lock,
    143                    const chrono::time_point<_Clock, _Duration>& __t,
    144                    _Predicate __pred);
    145 
    146     template <class _Lock, class _Rep, class _Period>
    147         cv_status
    148         wait_for(_Lock& __lock,
    149                  const chrono::duration<_Rep, _Period>& __d);
    150 
    151     template <class _Lock, class _Rep, class _Period, class _Predicate>
    152         bool
    153         wait_for(_Lock& __lock,
    154                  const chrono::duration<_Rep, _Period>& __d,
    155                  _Predicate __pred);
    156 };
    157 
    158 inline _LIBCPP_INLINE_VISIBILITY
    159 condition_variable_any::condition_variable_any()
    160     : __mut_(make_shared<mutex>()) {}
    161 
    162 inline _LIBCPP_INLINE_VISIBILITY
    163 void
    164 condition_variable_any::notify_one() _NOEXCEPT
    165 {
    166     {lock_guard<mutex> __lx(*__mut_);}
    167     __cv_.notify_one();
    168 }
    169 
    170 inline _LIBCPP_INLINE_VISIBILITY
    171 void
    172 condition_variable_any::notify_all() _NOEXCEPT
    173 {
    174     {lock_guard<mutex> __lx(*__mut_);}
    175     __cv_.notify_all();
    176 }
    177 
    178 struct __lock_external
    179 {
    180     template <class _Lock>
    181     void operator()(_Lock* __m) {__m->lock();}
    182 };
    183 
    184 template <class _Lock>
    185 void
    186 condition_variable_any::wait(_Lock& __lock)
    187 {
    188     shared_ptr<mutex> __mut = __mut_;
    189     unique_lock<mutex> __lk(*__mut);
    190     __lock.unlock();
    191     unique_ptr<_Lock, __lock_external> __lxx(&__lock);
    192     lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
    193     __cv_.wait(__lk);
    194 }  // __mut_.unlock(), __lock.lock()
    195 
    196 template <class _Lock, class _Predicate>
    197 inline _LIBCPP_INLINE_VISIBILITY
    198 void
    199 condition_variable_any::wait(_Lock& __lock, _Predicate __pred)
    200 {
    201     while (!__pred())
    202         wait(__lock);
    203 }
    204 
    205 template <class _Lock, class _Clock, class _Duration>
    206 cv_status
    207 condition_variable_any::wait_until(_Lock& __lock,
    208                                    const chrono::time_point<_Clock, _Duration>& __t)
    209 {
    210     shared_ptr<mutex> __mut = __mut_;
    211     unique_lock<mutex> __lk(*__mut);
    212     __lock.unlock();
    213     unique_ptr<_Lock, __lock_external> __lxx(&__lock);
    214     lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
    215     return __cv_.wait_until(__lk, __t);
    216 }  // __mut_.unlock(), __lock.lock()
    217 
    218 template <class _Lock, class _Clock, class _Duration, class _Predicate>
    219 inline _LIBCPP_INLINE_VISIBILITY
    220 bool
    221 condition_variable_any::wait_until(_Lock& __lock,
    222                                    const chrono::time_point<_Clock, _Duration>& __t,
    223                                    _Predicate __pred)
    224 {
    225     while (!__pred())
    226         if (wait_until(__lock, __t) == cv_status::timeout)
    227             return __pred();
    228     return true;
    229 }
    230 
    231 template <class _Lock, class _Rep, class _Period>
    232 inline _LIBCPP_INLINE_VISIBILITY
    233 cv_status
    234 condition_variable_any::wait_for(_Lock& __lock,
    235                                  const chrono::duration<_Rep, _Period>& __d)
    236 {
    237     return wait_until(__lock, chrono::steady_clock::now() + __d);
    238 }
    239 
    240 template <class _Lock, class _Rep, class _Period, class _Predicate>
    241 inline _LIBCPP_INLINE_VISIBILITY
    242 bool
    243 condition_variable_any::wait_for(_Lock& __lock,
    244                                  const chrono::duration<_Rep, _Period>& __d,
    245                                  _Predicate __pred)
    246 {
    247     return wait_until(__lock, chrono::steady_clock::now() + __d,
    248                       _VSTD::move(__pred));
    249 }
    250 
    251 _LIBCPP_VISIBLE
    252 void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
    253 
    254 _LIBCPP_END_NAMESPACE_STD
    255 
    256 #endif  // _LIBCPP_CONDITION_VARIABLE
    257