17a984708SDavid Chisnall //===-------------------- condition_variable.cpp --------------------------===// 27a984708SDavid Chisnall // 37a984708SDavid Chisnall // The LLVM Compiler Infrastructure 47a984708SDavid Chisnall // 57a984708SDavid Chisnall // This file is dual licensed under the MIT and the University of Illinois Open 67a984708SDavid Chisnall // Source Licenses. See LICENSE.TXT for details. 77a984708SDavid Chisnall // 87a984708SDavid Chisnall //===----------------------------------------------------------------------===// 97a984708SDavid Chisnall 10d72607e9SDimitry Andric #include "__config" 11d72607e9SDimitry Andric 12d72607e9SDimitry Andric #ifndef _LIBCPP_HAS_NO_THREADS 13d72607e9SDimitry Andric 147a984708SDavid Chisnall #include "condition_variable" 157a984708SDavid Chisnall #include "thread" 167a984708SDavid Chisnall #include "system_error" 177a984708SDavid Chisnall #include "cassert" 187a984708SDavid Chisnall 197a984708SDavid Chisnall _LIBCPP_BEGIN_NAMESPACE_STD 207a984708SDavid Chisnall 217a984708SDavid Chisnall condition_variable::~condition_variable() 227a984708SDavid Chisnall { 237c82a1ecSDimitry Andric __libcpp_condvar_destroy(&__cv_); 247a984708SDavid Chisnall } 257a984708SDavid Chisnall 267a984708SDavid Chisnall void 27936e9439SDimitry Andric condition_variable::notify_one() _NOEXCEPT 287a984708SDavid Chisnall { 297c82a1ecSDimitry Andric __libcpp_condvar_signal(&__cv_); 307a984708SDavid Chisnall } 317a984708SDavid Chisnall 327a984708SDavid Chisnall void 33936e9439SDimitry Andric condition_variable::notify_all() _NOEXCEPT 347a984708SDavid Chisnall { 357c82a1ecSDimitry Andric __libcpp_condvar_broadcast(&__cv_); 367a984708SDavid Chisnall } 377a984708SDavid Chisnall 387a984708SDavid Chisnall void 39d72607e9SDimitry Andric condition_variable::wait(unique_lock<mutex>& lk) _NOEXCEPT 407a984708SDavid Chisnall { 417a984708SDavid Chisnall if (!lk.owns_lock()) 427a984708SDavid Chisnall __throw_system_error(EPERM, 437a984708SDavid Chisnall "condition_variable::wait: mutex not locked"); 447c82a1ecSDimitry Andric int ec = __libcpp_condvar_wait(&__cv_, lk.mutex()->native_handle()); 457a984708SDavid Chisnall if (ec) 467a984708SDavid Chisnall __throw_system_error(ec, "condition_variable wait failed"); 477a984708SDavid Chisnall } 487a984708SDavid Chisnall 497a984708SDavid Chisnall void 507a984708SDavid Chisnall condition_variable::__do_timed_wait(unique_lock<mutex>& lk, 51d72607e9SDimitry Andric chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) _NOEXCEPT 527a984708SDavid Chisnall { 537a984708SDavid Chisnall using namespace chrono; 547a984708SDavid Chisnall if (!lk.owns_lock()) 557a984708SDavid Chisnall __throw_system_error(EPERM, 567a984708SDavid Chisnall "condition_variable::timed wait: mutex not locked"); 577a984708SDavid Chisnall nanoseconds d = tp.time_since_epoch(); 58936e9439SDimitry Andric if (d > nanoseconds(0x59682F000000E941)) 59936e9439SDimitry Andric d = nanoseconds(0x59682F000000E941); 607a984708SDavid Chisnall timespec ts; 617a984708SDavid Chisnall seconds s = duration_cast<seconds>(d); 62936e9439SDimitry Andric typedef decltype(ts.tv_sec) ts_sec; 63936e9439SDimitry Andric _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); 64936e9439SDimitry Andric if (s.count() < ts_sec_max) 65936e9439SDimitry Andric { 66936e9439SDimitry Andric ts.tv_sec = static_cast<ts_sec>(s.count()); 677a984708SDavid Chisnall ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count()); 68936e9439SDimitry Andric } 69936e9439SDimitry Andric else 70936e9439SDimitry Andric { 71936e9439SDimitry Andric ts.tv_sec = ts_sec_max; 72936e9439SDimitry Andric ts.tv_nsec = giga::num - 1; 73936e9439SDimitry Andric } 747c82a1ecSDimitry Andric int ec = __libcpp_condvar_timedwait(&__cv_, lk.mutex()->native_handle(), &ts); 757a984708SDavid Chisnall if (ec != 0 && ec != ETIMEDOUT) 767a984708SDavid Chisnall __throw_system_error(ec, "condition_variable timed_wait failed"); 777a984708SDavid Chisnall } 787a984708SDavid Chisnall 797a984708SDavid Chisnall void 807a984708SDavid Chisnall notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk) 817a984708SDavid Chisnall { 82*aed8d94eSDimitry Andric auto& tl_ptr = __thread_local_data(); 83*aed8d94eSDimitry Andric // If this thread was not created using std::thread then it will not have 84*aed8d94eSDimitry Andric // previously allocated. 85*aed8d94eSDimitry Andric if (tl_ptr.get() == nullptr) { 86*aed8d94eSDimitry Andric tl_ptr.set_pointer(new __thread_struct); 87*aed8d94eSDimitry Andric } 887a984708SDavid Chisnall __thread_local_data()->notify_all_at_thread_exit(&cond, lk.release()); 897a984708SDavid Chisnall } 907a984708SDavid Chisnall 917a984708SDavid Chisnall _LIBCPP_END_NAMESPACE_STD 92d72607e9SDimitry Andric 93d72607e9SDimitry Andric #endif // !_LIBCPP_HAS_NO_THREADS 94