xref: /minix3/external/bsd/libc++/dist/libcxx/src/condition_variable.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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