14684ddb6SLionel Sambuc //===-------------------- condition_variable.cpp --------------------------===//
24684ddb6SLionel Sambuc //
34684ddb6SLionel Sambuc // The LLVM Compiler Infrastructure
44684ddb6SLionel Sambuc //
54684ddb6SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open
64684ddb6SLionel Sambuc // Source Licenses. See LICENSE.TXT for details.
74684ddb6SLionel Sambuc //
84684ddb6SLionel Sambuc //===----------------------------------------------------------------------===//
94684ddb6SLionel Sambuc
10*0a6a1f1dSLionel Sambuc #include "__config"
11*0a6a1f1dSLionel Sambuc
12*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
13*0a6a1f1dSLionel Sambuc
144684ddb6SLionel Sambuc #include "condition_variable"
154684ddb6SLionel Sambuc #include "thread"
164684ddb6SLionel Sambuc #include "system_error"
174684ddb6SLionel Sambuc #include "cassert"
184684ddb6SLionel Sambuc
194684ddb6SLionel Sambuc _LIBCPP_BEGIN_NAMESPACE_STD
204684ddb6SLionel Sambuc
~condition_variable()214684ddb6SLionel Sambuc condition_variable::~condition_variable()
224684ddb6SLionel Sambuc {
234684ddb6SLionel Sambuc pthread_cond_destroy(&__cv_);
244684ddb6SLionel Sambuc }
254684ddb6SLionel Sambuc
264684ddb6SLionel Sambuc void
notify_one()274684ddb6SLionel Sambuc condition_variable::notify_one() _NOEXCEPT
284684ddb6SLionel Sambuc {
294684ddb6SLionel Sambuc pthread_cond_signal(&__cv_);
304684ddb6SLionel Sambuc }
314684ddb6SLionel Sambuc
324684ddb6SLionel Sambuc void
notify_all()334684ddb6SLionel Sambuc condition_variable::notify_all() _NOEXCEPT
344684ddb6SLionel Sambuc {
354684ddb6SLionel Sambuc pthread_cond_broadcast(&__cv_);
364684ddb6SLionel Sambuc }
374684ddb6SLionel Sambuc
384684ddb6SLionel Sambuc void
wait(unique_lock<mutex> & lk)39*0a6a1f1dSLionel Sambuc condition_variable::wait(unique_lock<mutex>& lk) _NOEXCEPT
404684ddb6SLionel Sambuc {
414684ddb6SLionel Sambuc if (!lk.owns_lock())
424684ddb6SLionel Sambuc __throw_system_error(EPERM,
434684ddb6SLionel Sambuc "condition_variable::wait: mutex not locked");
444684ddb6SLionel Sambuc int ec = pthread_cond_wait(&__cv_, lk.mutex()->native_handle());
454684ddb6SLionel Sambuc if (ec)
464684ddb6SLionel Sambuc __throw_system_error(ec, "condition_variable wait failed");
474684ddb6SLionel Sambuc }
484684ddb6SLionel Sambuc
494684ddb6SLionel Sambuc void
__do_timed_wait(unique_lock<mutex> & lk,chrono::time_point<chrono::system_clock,chrono::nanoseconds> tp)504684ddb6SLionel Sambuc condition_variable::__do_timed_wait(unique_lock<mutex>& lk,
51*0a6a1f1dSLionel Sambuc chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) _NOEXCEPT
524684ddb6SLionel Sambuc {
534684ddb6SLionel Sambuc using namespace chrono;
544684ddb6SLionel Sambuc if (!lk.owns_lock())
554684ddb6SLionel Sambuc __throw_system_error(EPERM,
564684ddb6SLionel Sambuc "condition_variable::timed wait: mutex not locked");
574684ddb6SLionel Sambuc nanoseconds d = tp.time_since_epoch();
584684ddb6SLionel Sambuc if (d > nanoseconds(0x59682F000000E941))
594684ddb6SLionel Sambuc d = nanoseconds(0x59682F000000E941);
604684ddb6SLionel Sambuc timespec ts;
614684ddb6SLionel Sambuc seconds s = duration_cast<seconds>(d);
624684ddb6SLionel Sambuc typedef decltype(ts.tv_sec) ts_sec;
634684ddb6SLionel Sambuc _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max();
644684ddb6SLionel Sambuc if (s.count() < ts_sec_max)
654684ddb6SLionel Sambuc {
664684ddb6SLionel Sambuc ts.tv_sec = static_cast<ts_sec>(s.count());
674684ddb6SLionel Sambuc ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count());
684684ddb6SLionel Sambuc }
694684ddb6SLionel Sambuc else
704684ddb6SLionel Sambuc {
714684ddb6SLionel Sambuc ts.tv_sec = ts_sec_max;
724684ddb6SLionel Sambuc ts.tv_nsec = giga::num - 1;
734684ddb6SLionel Sambuc }
744684ddb6SLionel Sambuc int ec = pthread_cond_timedwait(&__cv_, lk.mutex()->native_handle(), &ts);
754684ddb6SLionel Sambuc if (ec != 0 && ec != ETIMEDOUT)
764684ddb6SLionel Sambuc __throw_system_error(ec, "condition_variable timed_wait failed");
774684ddb6SLionel Sambuc }
784684ddb6SLionel Sambuc
794684ddb6SLionel Sambuc void
notify_all_at_thread_exit(condition_variable & cond,unique_lock<mutex> lk)804684ddb6SLionel Sambuc notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
814684ddb6SLionel Sambuc {
824684ddb6SLionel Sambuc __thread_local_data()->notify_all_at_thread_exit(&cond, lk.release());
834684ddb6SLionel Sambuc }
844684ddb6SLionel Sambuc
854684ddb6SLionel Sambuc _LIBCPP_END_NAMESPACE_STD
86*0a6a1f1dSLionel Sambuc
87*0a6a1f1dSLionel Sambuc #endif // !_LIBCPP_HAS_NO_THREADS
88