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