1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// <condition_variable>
11
12// class condition_variable_any;
13
14// template <class Lock, class Duration, class Predicate>
15//     bool
16//     wait_until(Lock& lock,
17//                const chrono::time_point<Clock, Duration>& abs_time,
18//                Predicate pred);
19
20#include <condition_variable>
21#include <mutex>
22#include <thread>
23#include <chrono>
24#include <cassert>
25
26struct Clock
27{
28    typedef std::chrono::milliseconds duration;
29    typedef duration::rep             rep;
30    typedef duration::period          period;
31    typedef std::chrono::time_point<Clock> time_point;
32    static const bool is_steady =  true;
33
34    static time_point now()
35    {
36        using namespace std::chrono;
37        return time_point(duration_cast<duration>(
38                steady_clock::now().time_since_epoch()
39                                                 ));
40    }
41};
42
43class Pred
44{
45    int& i_;
46public:
47    explicit Pred(int& i) : i_(i) {}
48
49    bool operator()() {return i_ != 0;}
50};
51
52std::condition_variable_any cv;
53
54typedef std::timed_mutex L0;
55typedef std::unique_lock<L0> L1;
56
57L0 m0;
58
59int test1 = 0;
60int test2 = 0;
61
62int runs = 0;
63
64void f()
65{
66    L1 lk(m0);
67    assert(test2 == 0);
68    test1 = 1;
69    cv.notify_one();
70    Clock::time_point t0 = Clock::now();
71    Clock::time_point t = t0 + Clock::duration(250);
72    bool r = cv.wait_until(lk, t, Pred(test2));
73    Clock::time_point t1 = Clock::now();
74    if (runs == 0)
75    {
76        assert(t1 - t0 < Clock::duration(250));
77        assert(test2 != 0);
78        assert(r);
79    }
80    else
81    {
82        assert(t1 - t0 - Clock::duration(250) < Clock::duration(50));
83        assert(test2 == 0);
84        assert(!r);
85    }
86    ++runs;
87}
88
89int main()
90{
91    {
92        L1 lk(m0);
93        std::thread t(f);
94        assert(test1 == 0);
95        while (test1 == 0)
96            cv.wait(lk);
97        assert(test1 != 0);
98        test2 = 1;
99        lk.unlock();
100        cv.notify_one();
101        t.join();
102    }
103    test1 = 0;
104    test2 = 0;
105    {
106        L1 lk(m0);
107        std::thread t(f);
108        assert(test1 == 0);
109        while (test1 == 0)
110            cv.wait(lk);
111        assert(test1 != 0);
112        lk.unlock();
113        t.join();
114    }
115}
116