//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // UNSUPPORTED: no-threads // UNSUPPORTED: c++03 // ALLOW_RETRIES: 3 // // template // future::type> // async(F&& f, Args&&... args); // template // future::type> // async(launch policy, F&& f, Args&&... args); #include #include #include #include #include #include #include "test_macros.h" typedef cuda::std::chrono::high_resolution_clock Clock; typedef cuda::std::chrono::milliseconds ms; ::std::atomic_bool invoked{false}; int f0() { invoked = true; hip::this_thread::sleep_for(ms(200)); return 3; } int i = 0; int& f1() { invoked = true; hip::this_thread::sleep_for(ms(200)); return i; } void f2() { invoked = true; hip::this_thread::sleep_for(ms(200)); } ::std::unique_ptr f3(int j) { invoked = true; hip::this_thread::sleep_for(ms(200)); return ::std::unique_ptr(new int(j)); } ::std::unique_ptr f4(::std::unique_ptr&& p) { invoked = true; hip::this_thread::sleep_for(ms(200)); return ::std::move(p); } void f5(int j) { hip::this_thread::sleep_for(ms(200)); ((void)j); TEST_THROW(j); } template void test(CheckLambda&& getAndCheckFn, bool IsDeferred, Args&&... args) { // Reset global state. invoked = false; // Create the future and wait ::std::future f = ::std::async(::std::forward(args)...); hip::this_thread::sleep_for(ms(300)); // Check that deferred async's have not invoked the function. assert(invoked == !IsDeferred); // Time the call to f.get() and check that the returned value matches // what is expected. Clock::time_point t0 = Clock::now(); assert(getAndCheckFn(f)); Clock::time_point t1 = Clock::now(); // If the async is deferred it should take more than 100ms, otherwise // it should take less than 100ms. if (IsDeferred) { assert(t1 - t0 > ms(100)); } else { assert(t1 - t0 < ms(100)); } } int main(int, char**) { // The default launch policy is implementation defined. libc++ defines // it to be ::std::launch::async. bool DefaultPolicyIsDeferred = false; bool DPID = DefaultPolicyIsDeferred; ::std::launch AnyPolicy = ::std::launch::async | ::std::launch::deferred; LIBCPP_ASSERT(AnyPolicy == ::std::launch::any); { auto checkInt = [](::std::future& f) { return f.get() == 3; }; test(checkInt, DPID, f0); test(checkInt, false, ::std::launch::async, f0); test(checkInt, true, ::std::launch::deferred, f0); test(checkInt, DPID, AnyPolicy, f0); } { auto checkIntRef = [&](::std::future& f) { return &f.get() == &i; }; test(checkIntRef, DPID, f1); test(checkIntRef, false, ::std::launch::async, f1); test(checkIntRef, true, ::std::launch::deferred, f1); test(checkIntRef, DPID, AnyPolicy, f1); } { auto checkVoid = [](::std::future& f) { f.get(); return true; }; test(checkVoid, DPID, f2); test(checkVoid, false, ::std::launch::async, f2); test(checkVoid, true, ::std::launch::deferred, f2); test(checkVoid, DPID, AnyPolicy, f2); } { using Ret = ::std::unique_ptr; auto checkUPtr = [](::std::future& f) { return *f.get() == 3; }; test(checkUPtr, DPID, f3, 3); test(checkUPtr, DPID, f4, ::std::unique_ptr(new int(3))); } #ifndef TEST_HAS_NO_EXCEPTIONS { ::std::future f = ::std::async(f5, 3); hip::this_thread::sleep_for(ms(300)); try { f.get(); assert (false); } catch ( int ) {} } { ::std::future f = ::std::async(::std::launch::deferred, f5, 3); hip::this_thread::sleep_for(ms(300)); try { f.get(); assert (false); } catch ( int ) {} } #endif return 0; }