1eb8650a7SLouis Dionne //===----------------------------------------------------------------------===//
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
9*bbb0f2c7SArthur O'Dwyer #include <__config>
10b3fcc67fSJonathan Roelofs
11b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
12b3fcc67fSJonathan Roelofs
13*bbb0f2c7SArthur O'Dwyer #include <condition_variable>
14*bbb0f2c7SArthur O'Dwyer #include <thread>
15*bbb0f2c7SArthur O'Dwyer #include <system_error>
163e519524SHoward Hinnant
17a9b5fff5SMichał Górny #if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
18996e62eeSPetr Hosek # pragma comment(lib, "pthread")
19996e62eeSPetr Hosek #endif
20996e62eeSPetr Hosek
21*bbb0f2c7SArthur O'Dwyer _LIBCPP_PUSH_MACROS
22*bbb0f2c7SArthur O'Dwyer #include <__undef_macros>
23*bbb0f2c7SArthur O'Dwyer
243e519524SHoward Hinnant _LIBCPP_BEGIN_NAMESPACE_STD
253e519524SHoward Hinnant
268cedf04aSEric Fiselier // ~condition_variable is defined elsewhere.
273e519524SHoward Hinnant
283e519524SHoward Hinnant void
notify_one()295601305fSLouis Dionne condition_variable::notify_one() noexcept
303e519524SHoward Hinnant {
31c7e4239fSAsiri Rathnayake __libcpp_condvar_signal(&__cv_);
323e519524SHoward Hinnant }
333e519524SHoward Hinnant
343e519524SHoward Hinnant void
notify_all()355601305fSLouis Dionne condition_variable::notify_all() noexcept
363e519524SHoward Hinnant {
37c7e4239fSAsiri Rathnayake __libcpp_condvar_broadcast(&__cv_);
383e519524SHoward Hinnant }
393e519524SHoward Hinnant
403e519524SHoward Hinnant void
wait(unique_lock<mutex> & lk)415601305fSLouis Dionne condition_variable::wait(unique_lock<mutex>& lk) noexcept
423e519524SHoward Hinnant {
433e519524SHoward Hinnant if (!lk.owns_lock())
443e519524SHoward Hinnant __throw_system_error(EPERM,
453e519524SHoward Hinnant "condition_variable::wait: mutex not locked");
46c7e4239fSAsiri Rathnayake int ec = __libcpp_condvar_wait(&__cv_, lk.mutex()->native_handle());
473e519524SHoward Hinnant if (ec)
483e519524SHoward Hinnant __throw_system_error(ec, "condition_variable wait failed");
493e519524SHoward Hinnant }
503e519524SHoward Hinnant
513e519524SHoward Hinnant void
__do_timed_wait(unique_lock<mutex> & lk,chrono::time_point<chrono::system_clock,chrono::nanoseconds> tp)523e519524SHoward Hinnant condition_variable::__do_timed_wait(unique_lock<mutex>& lk,
535601305fSLouis Dionne chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) noexcept
543e519524SHoward Hinnant {
553e519524SHoward Hinnant using namespace chrono;
563e519524SHoward Hinnant if (!lk.owns_lock())
573e519524SHoward Hinnant __throw_system_error(EPERM,
583e519524SHoward Hinnant "condition_variable::timed wait: mutex not locked");
593e519524SHoward Hinnant nanoseconds d = tp.time_since_epoch();
60aad745a0SHoward Hinnant if (d > nanoseconds(0x59682F000000E941))
61aad745a0SHoward Hinnant d = nanoseconds(0x59682F000000E941);
62cfdc7f0dSMikhail Maltsev __libcpp_timespec_t ts;
633e519524SHoward Hinnant seconds s = duration_cast<seconds>(d);
64aad745a0SHoward Hinnant typedef decltype(ts.tv_sec) ts_sec;
65aad745a0SHoward Hinnant _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max();
66aad745a0SHoward Hinnant if (s.count() < ts_sec_max)
67aad745a0SHoward Hinnant {
68aad745a0SHoward Hinnant ts.tv_sec = static_cast<ts_sec>(s.count());
693e519524SHoward Hinnant ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count());
70aad745a0SHoward Hinnant }
71aad745a0SHoward Hinnant else
72aad745a0SHoward Hinnant {
73aad745a0SHoward Hinnant ts.tv_sec = ts_sec_max;
74aad745a0SHoward Hinnant ts.tv_nsec = giga::num - 1;
75aad745a0SHoward Hinnant }
76c7e4239fSAsiri Rathnayake int ec = __libcpp_condvar_timedwait(&__cv_, lk.mutex()->native_handle(), &ts);
773e519524SHoward Hinnant if (ec != 0 && ec != ETIMEDOUT)
783e519524SHoward Hinnant __throw_system_error(ec, "condition_variable timed_wait failed");
793e519524SHoward Hinnant }
803e519524SHoward Hinnant
81b77c0c03SHoward Hinnant void
notify_all_at_thread_exit(condition_variable & cond,unique_lock<mutex> lk)82b77c0c03SHoward Hinnant notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
83b77c0c03SHoward Hinnant {
84ff94d250SEric Fiselier auto& tl_ptr = __thread_local_data();
85ff94d250SEric Fiselier // If this thread was not created using std::thread then it will not have
86ff94d250SEric Fiselier // previously allocated.
87ff94d250SEric Fiselier if (tl_ptr.get() == nullptr) {
88ff94d250SEric Fiselier tl_ptr.set_pointer(new __thread_struct);
89ff94d250SEric Fiselier }
9010e4a48aSHoward Hinnant __thread_local_data()->notify_all_at_thread_exit(&cond, lk.release());
91b77c0c03SHoward Hinnant }
92b77c0c03SHoward Hinnant
933e519524SHoward Hinnant _LIBCPP_END_NAMESPACE_STD
94b3fcc67fSJonathan Roelofs
95*bbb0f2c7SArthur O'Dwyer _LIBCPP_POP_MACROS
96*bbb0f2c7SArthur O'Dwyer
97b3fcc67fSJonathan Roelofs #endif // !_LIBCPP_HAS_NO_THREADS
98