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