129 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 shared_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 {73 typedef int T;74 std::promise<T> p;75 std::shared_future<T> f = p.get_future();76 support::make_test_thread(func1, std::move(p)).detach();77 assert(f.valid());78 assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::timeout);79 assert(f.valid());80 81 // allow the worker thread to produce the result and wait until the worker is done82 set_worker_thread_state(WorkerThreadState::AllowedToRun);83 wait_for_worker_thread_state(WorkerThreadState::Exiting);84 85 assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::ready);86 assert(f.valid());87 f.wait();88 assert(f.valid());89 }90 {91 typedef int& T;92 std::promise<T> p;93 std::shared_future<T> f = p.get_future();94 support::make_test_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 done100 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 f.wait();106 assert(f.valid());107 }108 {109 typedef void T;110 std::promise<T> p;111 std::shared_future<T> f = p.get_future();112 support::make_test_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 done118 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 f.wait();124 assert(f.valid());125 }126 127 return 0;128}129