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