13e519524SHoward Hinnant //===-------------------- condition_variable.cpp --------------------------===// 23e519524SHoward Hinnant // 357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63e519524SHoward Hinnant // 73e519524SHoward Hinnant //===----------------------------------------------------------------------===// 83e519524SHoward Hinnant 9b3fcc67fSJonathan Roelofs #include "__config" 10b3fcc67fSJonathan Roelofs 11b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 12b3fcc67fSJonathan Roelofs 133e519524SHoward Hinnant #include "condition_variable" 143e519524SHoward Hinnant #include "thread" 153e519524SHoward Hinnant #include "system_error" 16a016efb1SEric Fiselier #include "__undef_macros" 173e519524SHoward Hinnant 18*b19977d5SPetr Hosek #if defined(__unix__) && defined(__ELF__) && defined(_LIBCPP_HAS_COMMENT_LIB_PRAGMA) 19996e62eeSPetr Hosek #pragma comment(lib, "pthread") 20996e62eeSPetr Hosek #endif 21996e62eeSPetr Hosek 223e519524SHoward Hinnant _LIBCPP_BEGIN_NAMESPACE_STD 233e519524SHoward Hinnant 243e519524SHoward Hinnant condition_variable::~condition_variable() 253e519524SHoward Hinnant { 26c7e4239fSAsiri Rathnayake __libcpp_condvar_destroy(&__cv_); 273e519524SHoward Hinnant } 283e519524SHoward Hinnant 293e519524SHoward Hinnant void 3045c663dbSHoward Hinnant condition_variable::notify_one() _NOEXCEPT 313e519524SHoward Hinnant { 32c7e4239fSAsiri Rathnayake __libcpp_condvar_signal(&__cv_); 333e519524SHoward Hinnant } 343e519524SHoward Hinnant 353e519524SHoward Hinnant void 3645c663dbSHoward Hinnant condition_variable::notify_all() _NOEXCEPT 373e519524SHoward Hinnant { 38c7e4239fSAsiri Rathnayake __libcpp_condvar_broadcast(&__cv_); 393e519524SHoward Hinnant } 403e519524SHoward Hinnant 413e519524SHoward Hinnant void 421641a7c1SMarshall Clow condition_variable::wait(unique_lock<mutex>& lk) _NOEXCEPT 433e519524SHoward Hinnant { 443e519524SHoward Hinnant if (!lk.owns_lock()) 453e519524SHoward Hinnant __throw_system_error(EPERM, 463e519524SHoward Hinnant "condition_variable::wait: mutex not locked"); 47c7e4239fSAsiri Rathnayake int ec = __libcpp_condvar_wait(&__cv_, lk.mutex()->native_handle()); 483e519524SHoward Hinnant if (ec) 493e519524SHoward Hinnant __throw_system_error(ec, "condition_variable wait failed"); 503e519524SHoward Hinnant } 513e519524SHoward Hinnant 523e519524SHoward Hinnant void 533e519524SHoward Hinnant condition_variable::__do_timed_wait(unique_lock<mutex>& lk, 541641a7c1SMarshall Clow chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) _NOEXCEPT 553e519524SHoward Hinnant { 563e519524SHoward Hinnant using namespace chrono; 573e519524SHoward Hinnant if (!lk.owns_lock()) 583e519524SHoward Hinnant __throw_system_error(EPERM, 593e519524SHoward Hinnant "condition_variable::timed wait: mutex not locked"); 603e519524SHoward Hinnant nanoseconds d = tp.time_since_epoch(); 61aad745a0SHoward Hinnant if (d > nanoseconds(0x59682F000000E941)) 62aad745a0SHoward Hinnant d = nanoseconds(0x59682F000000E941); 633e519524SHoward Hinnant timespec ts; 643e519524SHoward Hinnant seconds s = duration_cast<seconds>(d); 65aad745a0SHoward Hinnant typedef decltype(ts.tv_sec) ts_sec; 66aad745a0SHoward Hinnant _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); 67aad745a0SHoward Hinnant if (s.count() < ts_sec_max) 68aad745a0SHoward Hinnant { 69aad745a0SHoward Hinnant ts.tv_sec = static_cast<ts_sec>(s.count()); 703e519524SHoward Hinnant ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count()); 71aad745a0SHoward Hinnant } 72aad745a0SHoward Hinnant else 73aad745a0SHoward Hinnant { 74aad745a0SHoward Hinnant ts.tv_sec = ts_sec_max; 75aad745a0SHoward Hinnant ts.tv_nsec = giga::num - 1; 76aad745a0SHoward Hinnant } 77c7e4239fSAsiri Rathnayake int ec = __libcpp_condvar_timedwait(&__cv_, lk.mutex()->native_handle(), &ts); 783e519524SHoward Hinnant if (ec != 0 && ec != ETIMEDOUT) 793e519524SHoward Hinnant __throw_system_error(ec, "condition_variable timed_wait failed"); 803e519524SHoward Hinnant } 813e519524SHoward Hinnant 82b77c0c03SHoward Hinnant void 83b77c0c03SHoward Hinnant notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk) 84b77c0c03SHoward Hinnant { 85ff94d250SEric Fiselier auto& tl_ptr = __thread_local_data(); 86ff94d250SEric Fiselier // If this thread was not created using std::thread then it will not have 87ff94d250SEric Fiselier // previously allocated. 88ff94d250SEric Fiselier if (tl_ptr.get() == nullptr) { 89ff94d250SEric Fiselier tl_ptr.set_pointer(new __thread_struct); 90ff94d250SEric Fiselier } 9110e4a48aSHoward Hinnant __thread_local_data()->notify_all_at_thread_exit(&cond, lk.release()); 92b77c0c03SHoward Hinnant } 93b77c0c03SHoward Hinnant 943e519524SHoward Hinnant _LIBCPP_END_NAMESPACE_STD 95b3fcc67fSJonathan Roelofs 96b3fcc67fSJonathan Roelofs #endif // !_LIBCPP_HAS_NO_THREADS 97