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  // <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 
     30  void set_worker_thread_state(WorkerThreadState state)
     31  {
     32      thread_state.store(state, std::memory_order_relaxed);
     33  }
     34 
     35  void wait_for_worker_thread_state(WorkerThreadState state)
     36  {
     37      while (thread_state.load(std::memory_order_relaxed) != state);
     38  }
     39 
     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 
     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 
     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 
     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