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 // UNSUPPORTED: c++98, c++03
11 
12 // FLAKY_TEST.
13 
14 // <future>
15 
16 // class shared_future<R>
17 
18 // template <class Clock, class Duration>
19 //   future_status
20 //   wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
21 
22 #include <future>
23 #include <atomic>
24 #include <cassert>
25 
26 #include "test_macros.h"
27 
28 enum class WorkerThreadState { Uninitialized, AllowedToRun, Exiting };
29 typedef std::chrono::milliseconds ms;
30 
31 std::atomic<WorkerThreadState> thread_state(WorkerThreadState::Uninitialized);
32 
33 void set_worker_thread_state(WorkerThreadState state)
34 {
35     thread_state.store(state, std::memory_order_relaxed);
36 }
37 
38 void wait_for_worker_thread_state(WorkerThreadState state)
39 {
40     while (thread_state.load(std::memory_order_relaxed) != state);
41 }
42 
43 void func1(std::promise<int> p)
44 {
45     wait_for_worker_thread_state(WorkerThreadState::AllowedToRun);
46     p.set_value(3);
47     set_worker_thread_state(WorkerThreadState::Exiting);
48 }
49 
50 int j = 0;
51 
52 void func3(std::promise<int&> p)
53 {
54     wait_for_worker_thread_state(WorkerThreadState::AllowedToRun);
55     j = 5;
56     p.set_value(j);
57     set_worker_thread_state(WorkerThreadState::Exiting);
58 }
59 
60 void func5(std::promise<void> p)
61 {
62     wait_for_worker_thread_state(WorkerThreadState::AllowedToRun);
63     p.set_value();
64     set_worker_thread_state(WorkerThreadState::Exiting);
65 }
66 
67 int main(int, char**)
68 {
69     typedef std::chrono::high_resolution_clock Clock;
70     {
71         typedef int T;
72         std::promise<T> p;
73         std::shared_future<T> f = p.get_future();
74         std::thread(func1, std::move(p)).detach();
75         assert(f.valid());
76         assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::timeout);
77         assert(f.valid());
78 
79         // allow the worker thread to produce the result and wait until the worker is done
80         set_worker_thread_state(WorkerThreadState::AllowedToRun);
81         wait_for_worker_thread_state(WorkerThreadState::Exiting);
82 
83         assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::ready);
84         assert(f.valid());
85         Clock::time_point t0 = Clock::now();
86         f.wait();
87         Clock::time_point t1 = Clock::now();
88         assert(f.valid());
89         assert(t1-t0 < ms(5));
90     }
91     {
92         typedef int& T;
93         std::promise<T> p;
94         std::shared_future<T> f = p.get_future();
95         std::thread(func3, std::move(p)).detach();
96         assert(f.valid());
97         assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::timeout);
98         assert(f.valid());
99 
100         // allow the worker thread to produce the result and wait until the worker is done
101         set_worker_thread_state(WorkerThreadState::AllowedToRun);
102         wait_for_worker_thread_state(WorkerThreadState::Exiting);
103 
104         assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::ready);
105         assert(f.valid());
106         Clock::time_point t0 = Clock::now();
107         f.wait();
108         Clock::time_point t1 = Clock::now();
109         assert(f.valid());
110         assert(t1-t0 < ms(5));
111     }
112     {
113         typedef void T;
114         std::promise<T> p;
115         std::shared_future<T> f = p.get_future();
116         std::thread(func5, std::move(p)).detach();
117         assert(f.valid());
118         assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::timeout);
119         assert(f.valid());
120 
121         // allow the worker thread to produce the result and wait until the worker is done
122         set_worker_thread_state(WorkerThreadState::AllowedToRun);
123         wait_for_worker_thread_state(WorkerThreadState::Exiting);
124 
125         assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::ready);
126         assert(f.valid());
127         Clock::time_point t0 = Clock::now();
128         f.wait();
129         Clock::time_point t1 = Clock::now();
130         assert(f.valid());
131         assert(t1-t0 < ms(5));
132     }
133 
134   return 0;
135 }
136