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

source code of libcxx/test/std/thread/futures/futures.async/async.pass.cpp