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;
13
14// template <class Clock, class Duration, class Predicate>
15//     bool
16//     wait_until(unique_lock<mutex>& 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 cv;
53std::mutex mut;
54
55int test1 = 0;
56int test2 = 0;
57
58int runs = 0;
59
60void f()
61{
62    std::unique_lock<std::mutex> lk(mut);
63    assert(test2 == 0);
64    test1 = 1;
65    cv.notify_one();
66    Clock::time_point t0 = Clock::now();
67    Clock::time_point t = t0 + Clock::duration(250);
68    bool r = cv.wait_until(lk, t, Pred(test2));
69    Clock::time_point t1 = Clock::now();
70    if (runs == 0)
71    {
72        assert(t1 - t0 < Clock::duration(250));
73        assert(test2 != 0);
74        assert(r);
75    }
76    else
77    {
78        assert(t1 - t0 - Clock::duration(250) < Clock::duration(50));
79        assert(test2 == 0);
80        assert(!r);
81    }
82    ++runs;
83}
84
85int main()
86{
87    {
88        std::unique_lock<std::mutex>lk(mut);
89        std::thread t(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        std::unique_lock<std::mutex>lk(mut);
103        std::thread t(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