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// UNSUPPORTED: libcpp-has-no-threads
11
12// <condition_variable>
13
14// class condition_variable_any;
15
16// template <class Lock, class Rep, class Period, class Predicate>
17//   bool
18//   wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time,
19//            Predicate pred);
20
21#include <condition_variable>
22#include <mutex>
23#include <thread>
24#include <chrono>
25#include <cassert>
26
27class Pred
28{
29    int& i_;
30public:
31    explicit Pred(int& i) : i_(i) {}
32
33    bool operator()() {return i_ != 0;}
34};
35
36std::condition_variable_any cv;
37
38typedef std::timed_mutex L0;
39typedef std::unique_lock<L0> L1;
40
41L0 m0;
42
43int test1 = 0;
44int test2 = 0;
45
46int runs = 0;
47bool expect_result = false;
48
49void f()
50{
51    typedef std::chrono::system_clock Clock;
52    typedef std::chrono::milliseconds milliseconds;
53    L1 lk(m0);
54    assert(test2 == 0);
55    test1 = 1;
56    cv.notify_one();
57    Clock::time_point t0 = Clock::now();
58    bool result = cv.wait_for(lk, milliseconds(250), Pred(test2));
59    assert(result == expect_result);
60    Clock::time_point t1 = Clock::now();
61    if (runs == 0)
62    {
63        assert(t1 - t0 < milliseconds(250));
64        assert(test2 != 0);
65    }
66    else
67    {
68        assert(t1 - t0 - milliseconds(250) < milliseconds(50));
69        assert(test2 == 0);
70    }
71    ++runs;
72}
73
74int main()
75{
76    {
77        expect_result = true;
78        L1 lk(m0);
79        std::thread t(f);
80        assert(test1 == 0);
81        while (test1 == 0)
82            cv.wait(lk);
83        assert(test1 != 0);
84        test2 = 1;
85        lk.unlock();
86        cv.notify_one();
87        t.join();
88    }
89    test1 = 0;
90    test2 = 0;
91    {
92        expect_result = false;
93        L1 lk(m0);
94        std::thread t(f);
95        assert(test1 == 0);
96        while (test1 == 0)
97            cv.wait(lk);
98        assert(test1 != 0);
99        lk.unlock();
100        t.join();
101    }
102}
103