1 //===----------------------------------------------------------------------===// 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 // UNSUPPORTED: libcpp-has-no-threads 10 // ALLOW_RETRIES: 2 11 12 // TODO(ldionne): This test fails on Ubuntu Focal on our CI nodes (and only there), in 32 bit mode. 13 // UNSUPPORTED: linux && 32bits-on-64bits 14 15 // <condition_variable> 16 17 // class condition_variable; 18 19 // template <class Clock, class Duration> 20 // cv_status 21 // wait_until(unique_lock<mutex>& lock, 22 // const chrono::time_point<Clock, Duration>& abs_time); 23 24 #include <condition_variable> 25 #include <mutex> 26 #include <thread> 27 #include <chrono> 28 #include <cassert> 29 30 #include "make_test_thread.h" 31 #include "test_macros.h" 32 33 struct TestClock 34 { 35 typedef std::chrono::milliseconds duration; 36 typedef duration::rep rep; 37 typedef duration::period period; 38 typedef std::chrono::time_point<TestClock> time_point; 39 static const bool is_steady = true; 40 41 static time_point now() 42 { 43 using namespace std::chrono; 44 return time_point(duration_cast<duration>( 45 steady_clock::now().time_since_epoch() 46 )); 47 } 48 }; 49 50 std::condition_variable cv; 51 std::mutex mut; 52 53 int test1 = 0; 54 int test2 = 0; 55 56 int runs = 0; 57 58 template <typename Clock> 59 void f() 60 { 61 std::unique_lock<std::mutex> lk(mut); 62 assert(test2 == 0); 63 test1 = 1; 64 cv.notify_one(); 65 typename Clock::time_point t0 = Clock::now(); 66 typename Clock::time_point t = t0 + std::chrono::milliseconds(250); 67 while (test2 == 0 && cv.wait_until(lk, t) == std::cv_status::no_timeout) 68 ; 69 typename Clock::time_point t1 = Clock::now(); 70 if (runs == 0) 71 { 72 assert(t1 - t0 < std::chrono::milliseconds(250)); 73 assert(test2 != 0); 74 } 75 else 76 { 77 assert(t1 - t0 - std::chrono::milliseconds(250) < std::chrono::milliseconds(50)); 78 assert(test2 == 0); 79 } 80 ++runs; 81 } 82 83 template <typename Clock> 84 void run_test() 85 { 86 runs = 0; 87 test1 = 0; 88 test2 = 0; 89 { 90 std::unique_lock<std::mutex>lk(mut); 91 std::thread t = support::make_test_thread(f<Clock>); 92 assert(test1 == 0); 93 while (test1 == 0) 94 cv.wait(lk); 95 assert(test1 != 0); 96 test2 = 1; 97 lk.unlock(); 98 cv.notify_one(); 99 t.join(); 100 } 101 test1 = 0; 102 test2 = 0; 103 { 104 std::unique_lock<std::mutex>lk(mut); 105 std::thread t = support::make_test_thread(f<Clock>); 106 assert(test1 == 0); 107 while (test1 == 0) 108 cv.wait(lk); 109 assert(test1 != 0); 110 lk.unlock(); 111 t.join(); 112 } 113 } 114 115 int main(int, char**) 116 { 117 run_test<TestClock>(); 118 run_test<std::chrono::steady_clock>(); 119 run_test<std::chrono::system_clock>(); 120 return 0; 121 } 122