128 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// UNSUPPORTED: no-threads10// UNSUPPORTED: c++0311 12// <future>13 14// class future<R>15 16// template <class Clock, class Duration>17// future_status18// wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;19 20#include <atomic>21#include <cassert>22#include <chrono>23#include <future>24 25#include "make_test_thread.h"26#include "test_macros.h"27 28enum class WorkerThreadState { Uninitialized, AllowedToRun, Exiting };29typedef std::chrono::milliseconds ms;30 31std::atomic<WorkerThreadState> thread_state(WorkerThreadState::Uninitialized);32 33void set_worker_thread_state(WorkerThreadState state)34{35 thread_state.store(state, std::memory_order_relaxed);36}37 38void wait_for_worker_thread_state(WorkerThreadState state)39{40 while (thread_state.load(std::memory_order_relaxed) != state)41 std::this_thread::yield();42}43 44void func1(std::promise<int> p)45{46 wait_for_worker_thread_state(WorkerThreadState::AllowedToRun);47 p.set_value(3);48 set_worker_thread_state(WorkerThreadState::Exiting);49}50 51int j = 0;52 53void func3(std::promise<int&> p)54{55 wait_for_worker_thread_state(WorkerThreadState::AllowedToRun);56 j = 5;57 p.set_value(j);58 set_worker_thread_state(WorkerThreadState::Exiting);59}60 61void func5(std::promise<void> p)62{63 wait_for_worker_thread_state(WorkerThreadState::AllowedToRun);64 p.set_value();65 set_worker_thread_state(WorkerThreadState::Exiting);66}67 68int main(int, char**)69{70 typedef std::chrono::high_resolution_clock Clock;71 {72 typedef int T;73 std::promise<T> p;74 std::future<T> f = p.get_future();75 support::make_test_thread(func1, std::move(p)).detach();76 assert(f.valid());77 assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::timeout);78 assert(f.valid());79 80 // allow the worker thread to produce the result and wait until the worker is done81 set_worker_thread_state(WorkerThreadState::AllowedToRun);82 wait_for_worker_thread_state(WorkerThreadState::Exiting);83 84 assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::ready);85 assert(f.valid());86 f.wait();87 assert(f.valid());88 }89 {90 typedef int& T;91 std::promise<T> p;92 std::future<T> f = p.get_future();93 support::make_test_thread(func3, std::move(p)).detach();94 assert(f.valid());95 assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::timeout);96 assert(f.valid());97 98 // allow the worker thread to produce the result and wait until the worker is done99 set_worker_thread_state(WorkerThreadState::AllowedToRun);100 wait_for_worker_thread_state(WorkerThreadState::Exiting);101 102 assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::ready);103 assert(f.valid());104 f.wait();105 assert(f.valid());106 }107 {108 typedef void T;109 std::promise<T> p;110 std::future<T> f = p.get_future();111 support::make_test_thread(func5, std::move(p)).detach();112 assert(f.valid());113 assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::timeout);114 assert(f.valid());115 116 // allow the worker thread to produce the result and wait until the worker is done117 set_worker_thread_state(WorkerThreadState::AllowedToRun);118 wait_for_worker_thread_state(WorkerThreadState::Exiting);119 120 assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::ready);121 assert(f.valid());122 f.wait();123 assert(f.valid());124 }125 126 return 0;127}128