1 //===-------------------- condition_variable.cpp --------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "__config" 10 11 #ifndef _LIBCPP_HAS_NO_THREADS 12 13 #include "condition_variable" 14 #include "thread" 15 #include "system_error" 16 #include "__undef_macros" 17 18 #if defined(__unix__) && defined(__ELF__) && defined(_LIBCPP_HAS_COMMENT_LIB_PRAGMA) 19 #pragma comment(lib, "pthread") 20 #endif 21 22 _LIBCPP_BEGIN_NAMESPACE_STD 23 24 condition_variable::~condition_variable() 25 { 26 __libcpp_condvar_destroy(&__cv_); 27 } 28 29 void 30 condition_variable::notify_one() _NOEXCEPT 31 { 32 __libcpp_condvar_signal(&__cv_); 33 } 34 35 void 36 condition_variable::notify_all() _NOEXCEPT 37 { 38 __libcpp_condvar_broadcast(&__cv_); 39 } 40 41 void 42 condition_variable::wait(unique_lock<mutex>& lk) _NOEXCEPT 43 { 44 if (!lk.owns_lock()) 45 __throw_system_error(EPERM, 46 "condition_variable::wait: mutex not locked"); 47 int ec = __libcpp_condvar_wait(&__cv_, lk.mutex()->native_handle()); 48 if (ec) 49 __throw_system_error(ec, "condition_variable wait failed"); 50 } 51 52 void 53 condition_variable::__do_timed_wait(unique_lock<mutex>& lk, 54 chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) _NOEXCEPT 55 { 56 using namespace chrono; 57 if (!lk.owns_lock()) 58 __throw_system_error(EPERM, 59 "condition_variable::timed wait: mutex not locked"); 60 nanoseconds d = tp.time_since_epoch(); 61 if (d > nanoseconds(0x59682F000000E941)) 62 d = nanoseconds(0x59682F000000E941); 63 __libcpp_timespec_t ts; 64 seconds s = duration_cast<seconds>(d); 65 typedef decltype(ts.tv_sec) ts_sec; 66 _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); 67 if (s.count() < ts_sec_max) 68 { 69 ts.tv_sec = static_cast<ts_sec>(s.count()); 70 ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count()); 71 } 72 else 73 { 74 ts.tv_sec = ts_sec_max; 75 ts.tv_nsec = giga::num - 1; 76 } 77 int ec = __libcpp_condvar_timedwait(&__cv_, lk.mutex()->native_handle(), &ts); 78 if (ec != 0 && ec != ETIMEDOUT) 79 __throw_system_error(ec, "condition_variable timed_wait failed"); 80 } 81 82 void 83 notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk) 84 { 85 auto& tl_ptr = __thread_local_data(); 86 // If this thread was not created using std::thread then it will not have 87 // previously allocated. 88 if (tl_ptr.get() == nullptr) { 89 tl_ptr.set_pointer(new __thread_struct); 90 } 91 __thread_local_data()->notify_all_at_thread_exit(&cond, lk.release()); 92 } 93 94 _LIBCPP_END_NAMESPACE_STD 95 96 #endif // !_LIBCPP_HAS_NO_THREADS 97