15a83710eSEric Fiselier //===----------------------------------------------------------------------===//
25a83710eSEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65a83710eSEric Fiselier //
75a83710eSEric Fiselier //===----------------------------------------------------------------------===//
85a83710eSEric Fiselier //
9*a7f9895cSLouis Dionne // UNSUPPORTED: no-threads
1031cbe0f2SLouis Dionne // UNSUPPORTED: c++03
115a83710eSEric Fiselier 
125a83710eSEric Fiselier // <future>
135a83710eSEric Fiselier 
145a83710eSEric Fiselier // class shared_future<R>
155a83710eSEric Fiselier 
165a83710eSEric Fiselier // template <class Clock, class Duration>
175a83710eSEric Fiselier //   future_status
185a83710eSEric Fiselier //   wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
195a83710eSEric Fiselier 
20bb185a0aSEric Fiselier #include <atomic>
215a83710eSEric Fiselier #include <cassert>
22489637e6SNikolas Klauser #include <chrono>
23489637e6SNikolas Klauser #include <future>
245a83710eSEric Fiselier 
2556462801SLouis Dionne #include "make_test_thread.h"
267fc6a556SMarshall Clow #include "test_macros.h"
277fc6a556SMarshall Clow 
28bb185a0aSEric Fiselier enum class WorkerThreadState { Uninitialized, AllowedToRun, Exiting };
295a83710eSEric Fiselier typedef std::chrono::milliseconds ms;
305a83710eSEric Fiselier 
31bb185a0aSEric Fiselier std::atomic<WorkerThreadState> thread_state(WorkerThreadState::Uninitialized);
32bb185a0aSEric Fiselier 
set_worker_thread_state(WorkerThreadState state)33bb185a0aSEric Fiselier void set_worker_thread_state(WorkerThreadState state)
34bb185a0aSEric Fiselier {
35bb185a0aSEric Fiselier   thread_state.store(state, std::memory_order_relaxed);
36bb185a0aSEric Fiselier }
37bb185a0aSEric Fiselier 
wait_for_worker_thread_state(WorkerThreadState state)38bb185a0aSEric Fiselier void wait_for_worker_thread_state(WorkerThreadState state)
39bb185a0aSEric Fiselier {
4018589533SDavid Zarzycki   while (thread_state.load(std::memory_order_relaxed) != state)
4118589533SDavid Zarzycki     std::this_thread::yield();
42bb185a0aSEric Fiselier }
43bb185a0aSEric Fiselier 
func1(std::promise<int> p)445a83710eSEric Fiselier void func1(std::promise<int> p)
455a83710eSEric Fiselier {
46bb185a0aSEric Fiselier   wait_for_worker_thread_state(WorkerThreadState::AllowedToRun);
475a83710eSEric Fiselier   p.set_value(3);
48bb185a0aSEric Fiselier   set_worker_thread_state(WorkerThreadState::Exiting);
495a83710eSEric Fiselier }
505a83710eSEric Fiselier 
515a83710eSEric Fiselier int j = 0;
525a83710eSEric Fiselier 
func3(std::promise<int &> p)535a83710eSEric Fiselier void func3(std::promise<int&> p)
545a83710eSEric Fiselier {
55bb185a0aSEric Fiselier   wait_for_worker_thread_state(WorkerThreadState::AllowedToRun);
565a83710eSEric Fiselier   j = 5;
575a83710eSEric Fiselier   p.set_value(j);
58bb185a0aSEric Fiselier   set_worker_thread_state(WorkerThreadState::Exiting);
595a83710eSEric Fiselier }
605a83710eSEric Fiselier 
func5(std::promise<void> p)615a83710eSEric Fiselier void func5(std::promise<void> p)
625a83710eSEric Fiselier {
63bb185a0aSEric Fiselier   wait_for_worker_thread_state(WorkerThreadState::AllowedToRun);
645a83710eSEric Fiselier   p.set_value();
65bb185a0aSEric Fiselier   set_worker_thread_state(WorkerThreadState::Exiting);
665a83710eSEric Fiselier }
675a83710eSEric Fiselier 
main(int,char **)682df59c50SJF Bastien int main(int, char**)
695a83710eSEric Fiselier {
705a83710eSEric Fiselier   typedef std::chrono::high_resolution_clock Clock;
7118589533SDavid Zarzycki 
725a83710eSEric Fiselier   {
735a83710eSEric Fiselier     typedef int T;
745a83710eSEric Fiselier     std::promise<T> p;
755a83710eSEric Fiselier     std::shared_future<T> f = p.get_future();
7656462801SLouis Dionne     support::make_test_thread(func1, std::move(p)).detach();
775a83710eSEric Fiselier     assert(f.valid());
78bb185a0aSEric Fiselier     assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::timeout);
795a83710eSEric Fiselier     assert(f.valid());
80bb185a0aSEric Fiselier 
81bb185a0aSEric Fiselier     // allow the worker thread to produce the result and wait until the worker is done
82bb185a0aSEric Fiselier     set_worker_thread_state(WorkerThreadState::AllowedToRun);
83bb185a0aSEric Fiselier     wait_for_worker_thread_state(WorkerThreadState::Exiting);
84bb185a0aSEric Fiselier 
85bb185a0aSEric Fiselier     assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::ready);
865a83710eSEric Fiselier     assert(f.valid());
875a83710eSEric Fiselier     f.wait();
885a83710eSEric Fiselier     assert(f.valid());
895a83710eSEric Fiselier   }
905a83710eSEric Fiselier   {
915a83710eSEric Fiselier     typedef int& T;
925a83710eSEric Fiselier     std::promise<T> p;
935a83710eSEric Fiselier     std::shared_future<T> f = p.get_future();
9456462801SLouis Dionne     support::make_test_thread(func3, std::move(p)).detach();
955a83710eSEric Fiselier     assert(f.valid());
96bb185a0aSEric Fiselier     assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::timeout);
975a83710eSEric Fiselier     assert(f.valid());
98bb185a0aSEric Fiselier 
99bb185a0aSEric Fiselier     // allow the worker thread to produce the result and wait until the worker is done
100bb185a0aSEric Fiselier     set_worker_thread_state(WorkerThreadState::AllowedToRun);
101bb185a0aSEric Fiselier     wait_for_worker_thread_state(WorkerThreadState::Exiting);
102bb185a0aSEric Fiselier 
103bb185a0aSEric Fiselier     assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::ready);
1045a83710eSEric Fiselier     assert(f.valid());
1055a83710eSEric Fiselier     f.wait();
1065a83710eSEric Fiselier     assert(f.valid());
1075a83710eSEric Fiselier   }
1085a83710eSEric Fiselier   {
1095a83710eSEric Fiselier     typedef void T;
1105a83710eSEric Fiselier     std::promise<T> p;
1115a83710eSEric Fiselier     std::shared_future<T> f = p.get_future();
11256462801SLouis Dionne     support::make_test_thread(func5, std::move(p)).detach();
1135a83710eSEric Fiselier     assert(f.valid());
114bb185a0aSEric Fiselier     assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::timeout);
1155a83710eSEric Fiselier     assert(f.valid());
116bb185a0aSEric Fiselier 
117bb185a0aSEric Fiselier     // allow the worker thread to produce the result and wait until the worker is done
118bb185a0aSEric Fiselier     set_worker_thread_state(WorkerThreadState::AllowedToRun);
119bb185a0aSEric Fiselier     wait_for_worker_thread_state(WorkerThreadState::Exiting);
120bb185a0aSEric Fiselier 
121bb185a0aSEric Fiselier     assert(f.wait_until(Clock::now() + ms(10)) == std::future_status::ready);
1225a83710eSEric Fiselier     assert(f.valid());
1235a83710eSEric Fiselier     f.wait();
1245a83710eSEric Fiselier     assert(f.valid());
1255a83710eSEric Fiselier   }
1262df59c50SJF Bastien 
1272df59c50SJF Bastien   return 0;
1285a83710eSEric Fiselier }
129