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_any;
18 
19 // template <class Lock, class Clock, class Duration>
20 //   cv_status
21 //   wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time);
22 
23 #include <condition_variable>
24 #include <mutex>
25 #include <thread>
26 #include <chrono>
27 #include <cassert>
28 
29 #include "make_test_thread.h"
30 #include "test_macros.h"
31 
32 struct Clock
33 {
34     typedef std::chrono::milliseconds duration;
35     typedef duration::rep             rep;
36     typedef duration::period          period;
37     typedef std::chrono::time_point<Clock> time_point;
38     static const bool is_steady =  true;
39 
40     static time_point now()
41     {
42         using namespace std::chrono;
43         return time_point(duration_cast<duration>(
44                 steady_clock::now().time_since_epoch()
45                                                  ));
46     }
47 };
48 
49 std::condition_variable_any cv;
50 
51 typedef std::timed_mutex L0;
52 typedef std::unique_lock<L0> L1;
53 
54 L0 m0;
55 
56 int test1 = 0;
57 int test2 = 0;
58 
59 int runs = 0;
60 
61 void f()
62 {
63     L1 lk(m0);
64     assert(test2 == 0);
65     test1 = 1;
66     cv.notify_one();
67     Clock::time_point t0 = Clock::now();
68     Clock::time_point t = t0 + Clock::duration(250);
69     while (test2 == 0 && cv.wait_until(lk, t) == std::cv_status::no_timeout)
70         ;
71     Clock::time_point t1 = Clock::now();
72     if (runs == 0)
73     {
74         assert(t1 - t0 < Clock::duration(250));
75         assert(test2 != 0);
76     }
77     else
78     {
79         assert(t1 - t0 - Clock::duration(250) < Clock::duration(50));
80         assert(test2 == 0);
81     }
82     ++runs;
83 }
84 
85 int main(int, char**)
86 {
87     {
88         L1 lk(m0);
89         std::thread t = support::make_test_thread(f);
90         assert(test1 == 0);
91         while (test1 == 0)
92             cv.wait(lk);
93         assert(test1 != 0);
94         test2 = 1;
95         lk.unlock();
96         cv.notify_one();
97         t.join();
98     }
99     test1 = 0;
100     test2 = 0;
101     {
102         L1 lk(m0);
103         std::thread t = support::make_test_thread(f);
104         assert(test1 == 0);
105         while (test1 == 0)
106             cv.wait(lk);
107         assert(test1 != 0);
108         lk.unlock();
109         t.join();
110     }
111 
112   return 0;
113 }
114