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