1142425Snectar//===-------------------- condition_variable.cpp --------------------------===//
2160814Ssimon//
3142425Snectar//                     The LLVM Compiler Infrastructure
4142425Snectar//
5142425Snectar// This file is dual licensed under the MIT and the University of Illinois Open
6142425Snectar// Source Licenses. See LICENSE.TXT for details.
7142425Snectar//
8142425Snectar//===----------------------------------------------------------------------===//
9142425Snectar
10142425Snectar#include "condition_variable"
11142425Snectar#include "thread"
12142425Snectar#include "system_error"
13142425Snectar#include "cassert"
14142425Snectar
15142425Snectar_LIBCPP_BEGIN_NAMESPACE_STD
16142425Snectar
17142425Snectarcondition_variable::~condition_variable()
18142425Snectar{
19142425Snectar    pthread_cond_destroy(&__cv_);
20142425Snectar}
21238405Sjkim
22142425Snectarvoid
23238405Sjkimcondition_variable::notify_one() _NOEXCEPT
24142425Snectar{
25142425Snectar    pthread_cond_signal(&__cv_);
26142425Snectar}
27142425Snectar
28142425Snectarvoid
29142425Snectarcondition_variable::notify_all() _NOEXCEPT
30142425Snectar{
31142425Snectar    pthread_cond_broadcast(&__cv_);
32142425Snectar}
33142425Snectar
34142425Snectarvoid
35142425Snectarcondition_variable::wait(unique_lock<mutex>& lk)
36142425Snectar{
37142425Snectar    if (!lk.owns_lock())
38238405Sjkim        __throw_system_error(EPERM,
39142425Snectar                                  "condition_variable::wait: mutex not locked");
40142425Snectar    int ec = pthread_cond_wait(&__cv_, lk.mutex()->native_handle());
41142425Snectar    if (ec)
42142425Snectar        __throw_system_error(ec, "condition_variable wait failed");
43142425Snectar}
44142425Snectar
45142425Snectarvoid
46142425Snectarcondition_variable::__do_timed_wait(unique_lock<mutex>& lk,
47142425Snectar               chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
48142425Snectar{
49142425Snectar    using namespace chrono;
50142425Snectar    if (!lk.owns_lock())
51160814Ssimon        __throw_system_error(EPERM,
52160814Ssimon                            "condition_variable::timed wait: mutex not locked");
53142425Snectar    nanoseconds d = tp.time_since_epoch();
54142425Snectar    if (d > nanoseconds(0x59682F000000E941))
55142425Snectar        d = nanoseconds(0x59682F000000E941);
56142425Snectar    timespec ts;
57142425Snectar    seconds s = duration_cast<seconds>(d);
58142425Snectar    typedef decltype(ts.tv_sec) ts_sec;
59142425Snectar    _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max();
60142425Snectar    if (s.count() < ts_sec_max)
61142425Snectar    {
62142425Snectar        ts.tv_sec = static_cast<ts_sec>(s.count());
63142425Snectar        ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count());
64142425Snectar    }
65142425Snectar    else
66284285Sjkim    {
67284285Sjkim        ts.tv_sec = ts_sec_max;
68142425Snectar        ts.tv_nsec = giga::num - 1;
69160814Ssimon    }
70142425Snectar    int ec = pthread_cond_timedwait(&__cv_, lk.mutex()->native_handle(), &ts);
71142425Snectar    if (ec != 0 && ec != ETIMEDOUT)
72142425Snectar        __throw_system_error(ec, "condition_variable timed_wait failed");
73142425Snectar}
74142425Snectar
75142425Snectarvoid
76142425Snectarnotify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
77142425Snectar{
78142425Snectar    __thread_local_data()->notify_all_at_thread_exit(&cond, lk.release());
79142425Snectar}
80142425Snectar
81238405Sjkim_LIBCPP_END_NAMESPACE_STD
82238405Sjkim