Home | History | Annotate | Download | only in futures.shared_future
      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 
     32 void set_worker_thread_state(WorkerThreadState state)
     33 {
     34     thread_state.store(state, std::memory_order_relaxed);
     35 }
     36 
     37 void wait_for_worker_thread_state(WorkerThreadState state)
     38 {
     39     while (thread_state.load(std::memory_order_relaxed) != state);
     40 }
     41 
     42 void 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 
     51 void 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 
     59 void 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 
     66 int 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