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