xref: /minix3/external/bsd/libc++/dist/libcxx/src/condition_variable.cpp (revision 4684ddb6aab0b36791c8099bc705d6140b3d05d0)
1*4684ddb6SLionel Sambuc //===-------------------- condition_variable.cpp --------------------------===//
2*4684ddb6SLionel Sambuc //
3*4684ddb6SLionel Sambuc //                     The LLVM Compiler Infrastructure
4*4684ddb6SLionel Sambuc //
5*4684ddb6SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open
6*4684ddb6SLionel Sambuc // Source Licenses. See LICENSE.TXT for details.
7*4684ddb6SLionel Sambuc //
8*4684ddb6SLionel Sambuc //===----------------------------------------------------------------------===//
9*4684ddb6SLionel Sambuc 
10*4684ddb6SLionel Sambuc #include "condition_variable"
11*4684ddb6SLionel Sambuc #include "thread"
12*4684ddb6SLionel Sambuc #include "system_error"
13*4684ddb6SLionel Sambuc #include "cassert"
14*4684ddb6SLionel Sambuc 
15*4684ddb6SLionel Sambuc _LIBCPP_BEGIN_NAMESPACE_STD
16*4684ddb6SLionel Sambuc 
17*4684ddb6SLionel Sambuc condition_variable::~condition_variable()
18*4684ddb6SLionel Sambuc {
19*4684ddb6SLionel Sambuc     pthread_cond_destroy(&__cv_);
20*4684ddb6SLionel Sambuc }
21*4684ddb6SLionel Sambuc 
22*4684ddb6SLionel Sambuc void
23*4684ddb6SLionel Sambuc condition_variable::notify_one() _NOEXCEPT
24*4684ddb6SLionel Sambuc {
25*4684ddb6SLionel Sambuc     pthread_cond_signal(&__cv_);
26*4684ddb6SLionel Sambuc }
27*4684ddb6SLionel Sambuc 
28*4684ddb6SLionel Sambuc void
29*4684ddb6SLionel Sambuc condition_variable::notify_all() _NOEXCEPT
30*4684ddb6SLionel Sambuc {
31*4684ddb6SLionel Sambuc     pthread_cond_broadcast(&__cv_);
32*4684ddb6SLionel Sambuc }
33*4684ddb6SLionel Sambuc 
34*4684ddb6SLionel Sambuc void
35*4684ddb6SLionel Sambuc condition_variable::wait(unique_lock<mutex>& lk)
36*4684ddb6SLionel Sambuc {
37*4684ddb6SLionel Sambuc     if (!lk.owns_lock())
38*4684ddb6SLionel Sambuc         __throw_system_error(EPERM,
39*4684ddb6SLionel Sambuc                                   "condition_variable::wait: mutex not locked");
40*4684ddb6SLionel Sambuc     int ec = pthread_cond_wait(&__cv_, lk.mutex()->native_handle());
41*4684ddb6SLionel Sambuc     if (ec)
42*4684ddb6SLionel Sambuc         __throw_system_error(ec, "condition_variable wait failed");
43*4684ddb6SLionel Sambuc }
44*4684ddb6SLionel Sambuc 
45*4684ddb6SLionel Sambuc void
46*4684ddb6SLionel Sambuc condition_variable::__do_timed_wait(unique_lock<mutex>& lk,
47*4684ddb6SLionel Sambuc                chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
48*4684ddb6SLionel Sambuc {
49*4684ddb6SLionel Sambuc #if !defined(__minix) /* LSC: FIXME a loop with yield plus sleep? */
50*4684ddb6SLionel Sambuc     using namespace chrono;
51*4684ddb6SLionel Sambuc     if (!lk.owns_lock())
52*4684ddb6SLionel Sambuc         __throw_system_error(EPERM,
53*4684ddb6SLionel Sambuc                             "condition_variable::timed wait: mutex not locked");
54*4684ddb6SLionel Sambuc     nanoseconds d = tp.time_since_epoch();
55*4684ddb6SLionel Sambuc     if (d > nanoseconds(0x59682F000000E941))
56*4684ddb6SLionel Sambuc         d = nanoseconds(0x59682F000000E941);
57*4684ddb6SLionel Sambuc     timespec ts;
58*4684ddb6SLionel Sambuc     seconds s = duration_cast<seconds>(d);
59*4684ddb6SLionel Sambuc     typedef decltype(ts.tv_sec) ts_sec;
60*4684ddb6SLionel Sambuc     _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max();
61*4684ddb6SLionel Sambuc     if (s.count() < ts_sec_max)
62*4684ddb6SLionel Sambuc     {
63*4684ddb6SLionel Sambuc         ts.tv_sec = static_cast<ts_sec>(s.count());
64*4684ddb6SLionel Sambuc         ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count());
65*4684ddb6SLionel Sambuc     }
66*4684ddb6SLionel Sambuc     else
67*4684ddb6SLionel Sambuc     {
68*4684ddb6SLionel Sambuc         ts.tv_sec = ts_sec_max;
69*4684ddb6SLionel Sambuc         ts.tv_nsec = giga::num - 1;
70*4684ddb6SLionel Sambuc     }
71*4684ddb6SLionel Sambuc     int ec = pthread_cond_timedwait(&__cv_, lk.mutex()->native_handle(), &ts);
72*4684ddb6SLionel Sambuc     if (ec != 0 && ec != ETIMEDOUT)
73*4684ddb6SLionel Sambuc #else
74*4684ddb6SLionel Sambuc     int ec = EINVAL;
75*4684ddb6SLionel Sambuc #endif /* !defined(__minix) */
76*4684ddb6SLionel Sambuc         __throw_system_error(ec, "condition_variable timed_wait failed");
77*4684ddb6SLionel Sambuc }
78*4684ddb6SLionel Sambuc 
79*4684ddb6SLionel Sambuc void
80*4684ddb6SLionel Sambuc notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
81*4684ddb6SLionel Sambuc {
82*4684ddb6SLionel Sambuc     __thread_local_data()->notify_all_at_thread_exit(&cond, lk.release());
83*4684ddb6SLionel Sambuc }
84*4684ddb6SLionel Sambuc 
85*4684ddb6SLionel Sambuc _LIBCPP_END_NAMESPACE_STD
86