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 #if !_LIBCPP_SINGLE_THREADED
    119 
    120 _LIBCPP_BEGIN_NAMESPACE_STD
    121 
    122 class _LIBCPP_TYPE_VIS condition_variable_any
    123 {
    124     condition_variable __cv_;
    125     shared_ptr<mutex>  __mut_;
    126 public:
    127     condition_variable_any();
    128 
    129     void notify_one() _NOEXCEPT;
    130     void notify_all() _NOEXCEPT;
    131 
    132     template <class _Lock>
    133         void wait(_Lock& __lock);
    134     template <class _Lock, class _Predicate>
    135         void wait(_Lock& __lock, _Predicate __pred);
    136 
    137     template <class _Lock, class _Clock, class _Duration>
    138         cv_status
    139         wait_until(_Lock& __lock,
    140                    const chrono::time_point<_Clock, _Duration>& __t);
    141 
    142     template <class _Lock, class _Clock, class _Duration, class _Predicate>
    143         bool
    144         wait_until(_Lock& __lock,
    145                    const chrono::time_point<_Clock, _Duration>& __t,
    146                    _Predicate __pred);
    147 
    148     template <class _Lock, class _Rep, class _Period>
    149         cv_status
    150         wait_for(_Lock& __lock,
    151                  const chrono::duration<_Rep, _Period>& __d);
    152 
    153     template <class _Lock, class _Rep, class _Period, class _Predicate>
    154         bool
    155         wait_for(_Lock& __lock,
    156                  const chrono::duration<_Rep, _Period>& __d,
    157                  _Predicate __pred);
    158 };
    159 
    160 inline _LIBCPP_INLINE_VISIBILITY
    161 condition_variable_any::condition_variable_any()
    162     : __mut_(make_shared<mutex>()) {}
    163 
    164 inline _LIBCPP_INLINE_VISIBILITY
    165 void
    166 condition_variable_any::notify_one() _NOEXCEPT
    167 {
    168     {lock_guard<mutex> __lx(*__mut_);}
    169     __cv_.notify_one();
    170 }
    171 
    172 inline _LIBCPP_INLINE_VISIBILITY
    173 void
    174 condition_variable_any::notify_all() _NOEXCEPT
    175 {
    176     {lock_guard<mutex> __lx(*__mut_);}
    177     __cv_.notify_all();
    178 }
    179 
    180 struct __lock_external
    181 {
    182     template <class _Lock>
    183     void operator()(_Lock* __m) {__m->lock();}
    184 };
    185 
    186 template <class _Lock>
    187 void
    188 condition_variable_any::wait(_Lock& __lock)
    189 {
    190     shared_ptr<mutex> __mut = __mut_;
    191     unique_lock<mutex> __lk(*__mut);
    192     __lock.unlock();
    193     unique_ptr<_Lock, __lock_external> __lxx(&__lock);
    194     lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
    195     __cv_.wait(__lk);
    196 }  // __mut_.unlock(), __lock.lock()
    197 
    198 template <class _Lock, class _Predicate>
    199 inline _LIBCPP_INLINE_VISIBILITY
    200 void
    201 condition_variable_any::wait(_Lock& __lock, _Predicate __pred)
    202 {
    203     while (!__pred())
    204         wait(__lock);
    205 }
    206 
    207 template <class _Lock, class _Clock, class _Duration>
    208 cv_status
    209 condition_variable_any::wait_until(_Lock& __lock,
    210                                    const chrono::time_point<_Clock, _Duration>& __t)
    211 {
    212     shared_ptr<mutex> __mut = __mut_;
    213     unique_lock<mutex> __lk(*__mut);
    214     __lock.unlock();
    215     unique_ptr<_Lock, __lock_external> __lxx(&__lock);
    216     lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
    217     return __cv_.wait_until(__lk, __t);
    218 }  // __mut_.unlock(), __lock.lock()
    219 
    220 template <class _Lock, class _Clock, class _Duration, class _Predicate>
    221 inline _LIBCPP_INLINE_VISIBILITY
    222 bool
    223 condition_variable_any::wait_until(_Lock& __lock,
    224                                    const chrono::time_point<_Clock, _Duration>& __t,
    225                                    _Predicate __pred)
    226 {
    227     while (!__pred())
    228         if (wait_until(__lock, __t) == cv_status::timeout)
    229             return __pred();
    230     return true;
    231 }
    232 
    233 template <class _Lock, class _Rep, class _Period>
    234 inline _LIBCPP_INLINE_VISIBILITY
    235 cv_status
    236 condition_variable_any::wait_for(_Lock& __lock,
    237                                  const chrono::duration<_Rep, _Period>& __d)
    238 {
    239     return wait_until(__lock, chrono::steady_clock::now() + __d);
    240 }
    241 
    242 template <class _Lock, class _Rep, class _Period, class _Predicate>
    243 inline _LIBCPP_INLINE_VISIBILITY
    244 bool
    245 condition_variable_any::wait_for(_Lock& __lock,
    246                                  const chrono::duration<_Rep, _Period>& __d,
    247                                  _Predicate __pred)
    248 {
    249     return wait_until(__lock, chrono::steady_clock::now() + __d,
    250                       _VSTD::move(__pred));
    251 }
    252 
    253 _LIBCPP_FUNC_VIS
    254 void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
    255 
    256 _LIBCPP_END_NAMESPACE_STD
    257 
    258 #endif // !_LIBCPP_SINGLE_THREADED
    259 
    260 #endif  // _LIBCPP_CONDITION_VARIABLE
    261