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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // UNSUPPORTED: libcpp-has-no-threads 10 // UNSUPPORTED: c++98, c++03 11 12 // <future> 13 14 // template <class F, class... Args> 15 // future<typename result_of<F(Args...)>::type> 16 // async(F&& f, Args&&... args); 17 18 // template <class F, class... Args> 19 // future<typename result_of<F(Args...)>::type> 20 // async(launch policy, F&& f, Args&&... args); 21 22 23 #include <future> 24 #include <atomic> 25 #include <memory> 26 #include <cassert> 27 28 #include "test_macros.h" 29 30 typedef std::chrono::high_resolution_clock Clock; 31 typedef std::chrono::milliseconds ms; 32 33 std::atomic_bool invoked = ATOMIC_VAR_INIT(false); 34 35 int f0() 36 { 37 invoked = true; 38 std::this_thread::sleep_for(ms(200)); 39 return 3; 40 } 41 42 int i = 0; 43 44 int& f1() 45 { 46 invoked = true; 47 std::this_thread::sleep_for(ms(200)); 48 return i; 49 } 50 51 void f2() 52 { 53 invoked = true; 54 std::this_thread::sleep_for(ms(200)); 55 } 56 57 std::unique_ptr<int> f3(int j) 58 { 59 invoked = true; 60 std::this_thread::sleep_for(ms(200)); 61 return std::unique_ptr<int>(new int(j)); 62 } 63 64 std::unique_ptr<int> f4(std::unique_ptr<int>&& p) 65 { 66 invoked = true; 67 std::this_thread::sleep_for(ms(200)); 68 return std::move(p); 69 } 70 71 void f5(int j) 72 { 73 std::this_thread::sleep_for(ms(200)); 74 ((void)j); 75 TEST_THROW(j); 76 } 77 78 template <class Ret, class CheckLamdba, class ...Args> 79 void test(CheckLamdba&& getAndCheckFn, bool IsDeferred, Args&&... args) { 80 // Reset global state. 81 invoked = false; 82 83 // Create the future and wait 84 std::future<Ret> f = std::async(std::forward<Args>(args)...); 85 std::this_thread::sleep_for(ms(300)); 86 87 // Check that deferred async's have not invoked the function. 88 assert(invoked == !IsDeferred); 89 90 // Time the call to f.get() and check that the returned value matches 91 // what is expected. 92 Clock::time_point t0 = Clock::now(); 93 assert(getAndCheckFn(f)); 94 Clock::time_point t1 = Clock::now(); 95 96 // If the async is deferred it should take more than 100ms, otherwise 97 // it should take less than 100ms. 98 if (IsDeferred) { 99 assert(t1-t0 > ms(100)); 100 } else { 101 assert(t1-t0 < ms(100)); 102 } 103 } 104 105 int main() 106 { 107 // The default launch policy is implementation defined. libc++ defines 108 // it to be std::launch::async. 109 bool DefaultPolicyIsDeferred = false; 110 bool DPID = DefaultPolicyIsDeferred; 111 112 std::launch AnyPolicy = std::launch::async | std::launch::deferred; 113 LIBCPP_ASSERT(AnyPolicy == std::launch::any); 114 115 { 116 auto checkInt = [](std::future<int>& f) { return f.get() == 3; }; 117 test<int>(checkInt, DPID, f0); 118 test<int>(checkInt, false, std::launch::async, f0); 119 test<int>(checkInt, true, std::launch::deferred, f0); 120 test<int>(checkInt, DPID, AnyPolicy, f0); 121 } 122 { 123 auto checkIntRef = [&](std::future<int&>& f) { return &f.get() == &i; }; 124 test<int&>(checkIntRef, DPID, f1); 125 test<int&>(checkIntRef, false, std::launch::async, f1); 126 test<int&>(checkIntRef, true, std::launch::deferred, f1); 127 test<int&>(checkIntRef, DPID, AnyPolicy, f1); 128 } 129 { 130 auto checkVoid = [](std::future<void>& f) { f.get(); return true; }; 131 test<void>(checkVoid, DPID, f2); 132 test<void>(checkVoid, false, std::launch::async, f2); 133 test<void>(checkVoid, true, std::launch::deferred, f2); 134 test<void>(checkVoid, DPID, AnyPolicy, f2); 135 } 136 { 137 using Ret = std::unique_ptr<int>; 138 auto checkUPtr = [](std::future<Ret>& f) { return *f.get() == 3; }; 139 test<Ret>(checkUPtr, DPID, f3, 3); 140 test<Ret>(checkUPtr, DPID, f4, std::unique_ptr<int>(new int(3))); 141 } 142 #ifndef TEST_HAS_NO_EXCEPTIONS 143 { 144 std::future<void> f = std::async(f5, 3); 145 std::this_thread::sleep_for(ms(300)); 146 try { f.get(); assert (false); } catch ( int ) {} 147 } 148 { 149 std::future<void> f = std::async(std::launch::deferred, f5, 3); 150 std::this_thread::sleep_for(ms(300)); 151 try { f.get(); assert (false); } catch ( int ) {} 152 } 153 #endif 154 } 155