1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // UNSUPPORTED: libcpp-has-no-threads 11 // UNSUPPORTED: c++98, c++03 12 13 // <future> 14 15 // template <class F, class... Args> 16 // future<typename result_of<F(Args...)>::type> 17 // async(F&& f, Args&&... args); 18 19 // template <class F, class... Args> 20 // future<typename result_of<F(Args...)>::type> 21 // async(launch policy, F&& f, Args&&... args); 22 23 24 #include <future> 25 #include <atomic> 26 #include <memory> 27 #include <cassert> 28 29 #include "test_macros.h" 30 31 typedef std::chrono::high_resolution_clock Clock; 32 typedef std::chrono::milliseconds ms; 33 34 std::atomic_bool invoked = ATOMIC_VAR_INIT(false); 35 36 int f0() 37 { 38 invoked = true; 39 std::this_thread::sleep_for(ms(200)); 40 return 3; 41 } 42 43 int i = 0; 44 45 int& f1() 46 { 47 invoked = true; 48 std::this_thread::sleep_for(ms(200)); 49 return i; 50 } 51 52 void f2() 53 { 54 invoked = true; 55 std::this_thread::sleep_for(ms(200)); 56 } 57 58 std::unique_ptr<int> f3(int j) 59 { 60 invoked = true; 61 std::this_thread::sleep_for(ms(200)); 62 return std::unique_ptr<int>(new int(j)); 63 } 64 65 std::unique_ptr<int> f4(std::unique_ptr<int>&& p) 66 { 67 invoked = true; 68 std::this_thread::sleep_for(ms(200)); 69 return std::move(p); 70 } 71 72 void f5(int j) 73 { 74 std::this_thread::sleep_for(ms(200)); 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