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