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 | // Copyright (C) 2014 Vicente J. Botet Escriba |
11 | // |
12 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
13 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
14 | |
15 | // <boost/thread/future.hpp> |
16 | |
17 | // template< typename InputIterator> |
18 | // future<vector<typename InputIterator::value_type> > |
19 | // when_all(InputIterator first, InputIterator last) |
20 | |
21 | #include <boost/config.hpp> |
22 | |
23 | #if ! defined BOOST_NO_CXX11_DECLTYPE |
24 | #define BOOST_RESULT_OF_USE_DECLTYPE |
25 | #endif |
26 | |
27 | |
28 | #define BOOST_THREAD_VERSION 4 |
29 | |
30 | #include <boost/thread/future.hpp> |
31 | #include <boost/detail/lightweight_test.hpp> |
32 | #include <stdexcept> |
33 | |
34 | #ifdef BOOST_MSVC |
35 | #pragma warning(disable: 4127) // conditional expression is constant |
36 | #endif |
37 | |
38 | int p1() |
39 | { |
40 | return 123; |
41 | } |
42 | |
43 | int thr() |
44 | { |
45 | throw std::logic_error("123" ); |
46 | } |
47 | int p2() |
48 | { |
49 | return 321; |
50 | } |
51 | |
52 | int main() |
53 | { |
54 | #if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY |
55 | if (0) // todo not yet implemented |
56 | { // invalid future copy-constructible |
57 | boost::csbl::vector<boost::future<int> > v; |
58 | boost::future<int> f1; |
59 | v.push_back(x: boost::move(t&: f1)); |
60 | v.push_back(x: boost::make_ready_future(value: 321)); |
61 | BOOST_TEST(! v[0].valid()); |
62 | BOOST_TEST(v[1].valid()); |
63 | |
64 | boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(first: v.begin(), last: v.end()); |
65 | BOOST_TEST(! v[0].valid()); |
66 | BOOST_TEST(! v[1].valid()); |
67 | BOOST_TEST(all.valid()); |
68 | boost::csbl::vector<boost::future<int> > res = all.get(); |
69 | BOOST_TEST(res.size() == 2); |
70 | BOOST_TEST(res[1].valid()); |
71 | BOOST_TEST(res[1].is_ready()); |
72 | // has exception |
73 | //BOOST_TEST(res[0].get() == 123); |
74 | BOOST_TEST(res[1].valid()); |
75 | BOOST_TEST(res[1].is_ready()); |
76 | BOOST_TEST(res[1].get() == 321); |
77 | } |
78 | { // is_ready future copy-constructible |
79 | boost::future<int> f1 = boost::make_ready_future(value: 123); |
80 | boost::future<int> f2 = boost::make_ready_future(value: 321); |
81 | boost::csbl::vector<boost::future<int> > v; |
82 | v.push_back(x: boost::move(t&: f1)); |
83 | v.push_back(x: boost::move(t&: f2)); |
84 | BOOST_TEST(v[0].valid()); |
85 | BOOST_TEST(v[0].is_ready()); |
86 | BOOST_TEST(v[1].valid()); |
87 | BOOST_TEST(v[1].is_ready()); |
88 | boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(first: v.begin(), last: v.end()); |
89 | BOOST_TEST(! v[0].valid()); |
90 | BOOST_TEST(! v[1].valid()); |
91 | BOOST_TEST(all.valid()); |
92 | if (0) // todo FAILS not yet implemented |
93 | BOOST_TEST(all.is_ready()); |
94 | boost::csbl::vector<boost::future<int> > res = all.get(); |
95 | BOOST_TEST(res[0].valid()); |
96 | BOOST_TEST(res[0].is_ready()); |
97 | BOOST_TEST(res[0].get() == 123); |
98 | BOOST_TEST(res[1].valid()); |
99 | BOOST_TEST(res[1].is_ready()); |
100 | BOOST_TEST(res[1].get() == 321); |
101 | } |
102 | { // is_ready shared_future copy-constructible |
103 | boost::shared_future<int> f1 = boost::make_ready_future(value: 123).share(); |
104 | boost::shared_future<int> f2 = boost::make_ready_future(value: 321).share(); |
105 | boost::csbl::vector<boost::shared_future<int> > v; |
106 | v.push_back(x: f1); |
107 | v.push_back(x: f2); |
108 | BOOST_TEST(v[0].valid()); |
109 | BOOST_TEST(v[0].is_ready()); |
110 | BOOST_TEST(v[1].valid()); |
111 | BOOST_TEST(v[1].is_ready()); |
112 | boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(first: v.begin(), last: v.end()); |
113 | if (0) // fixme |
114 | BOOST_TEST(v[0].valid()); |
115 | if (0) // fixme |
116 | BOOST_TEST(v[1].valid()); |
117 | BOOST_TEST(all.valid()); |
118 | if (0) // todo FAILS not yet implemented |
119 | BOOST_TEST(all.is_ready()); |
120 | boost::csbl::vector<boost::shared_future<int> > res = all.get(); |
121 | BOOST_TEST(res[0].valid()); |
122 | BOOST_TEST(res[0].is_ready()); |
123 | BOOST_TEST(res[0].get() == 123); |
124 | BOOST_TEST(res[1].valid()); |
125 | BOOST_TEST(res[1].is_ready()); |
126 | BOOST_TEST(res[1].get() == 321); |
127 | } |
128 | { // packaged_task future copy-constructible |
129 | boost::packaged_task<int()> pt1(&p1); |
130 | boost::future<int> f1 = pt1.get_future(); |
131 | BOOST_TEST(f1.valid()); |
132 | boost::packaged_task<int()> pt2(&p2); |
133 | boost::future<int> f2 = pt2.get_future(); |
134 | BOOST_TEST(f2.valid()); |
135 | boost::csbl::vector<boost::future<int> > v; |
136 | v.push_back(x: boost::move(t&: f1)); |
137 | v.push_back(x: boost::move(t&: f2)); |
138 | BOOST_TEST(v[0].valid()); |
139 | BOOST_TEST(v[1].valid()); |
140 | boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(first: v.begin(), last: v.end()); |
141 | BOOST_TEST(! v[0].valid()); |
142 | BOOST_TEST(! v[1].valid()); |
143 | BOOST_TEST(all.valid()); |
144 | pt1(); |
145 | pt2(); |
146 | boost::csbl::vector<boost::future<int> > res = all.get(); |
147 | BOOST_TEST(res[0].valid()); |
148 | BOOST_TEST(res[0].is_ready()); |
149 | BOOST_TEST(res[0].get() == 123); |
150 | BOOST_TEST(res[1].valid()); |
151 | BOOST_TEST(res[1].is_ready()); |
152 | BOOST_TEST(res[1].get() == 321); |
153 | } |
154 | { // packaged_task future copy-constructible |
155 | boost::packaged_task<int()> pt1(&thr); |
156 | boost::future<int> f1 = pt1.get_future(); |
157 | BOOST_TEST(f1.valid()); |
158 | boost::packaged_task<int()> pt2(&p2); |
159 | boost::future<int> f2 = pt2.get_future(); |
160 | BOOST_TEST(f2.valid()); |
161 | boost::csbl::vector<boost::future<int> > v; |
162 | v.push_back(x: boost::move(t&: f1)); |
163 | v.push_back(x: boost::move(t&: f2)); |
164 | BOOST_TEST(v[0].valid()); |
165 | BOOST_TEST(v[1].valid()); |
166 | boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(first: v.begin(), last: v.end()); |
167 | BOOST_TEST(! v[0].valid()); |
168 | BOOST_TEST(! v[1].valid()); |
169 | BOOST_TEST(all.valid()); |
170 | pt1(); |
171 | pt2(); |
172 | boost::csbl::vector<boost::future<int> > res = all.get(); |
173 | BOOST_TEST(res[0].valid()); |
174 | BOOST_TEST(res[0].is_ready()); |
175 | try { |
176 | res[0].get(); |
177 | BOOST_TEST(false); |
178 | } catch (std::logic_error& ex) { |
179 | BOOST_TEST(ex.what() == std::string("123" )); |
180 | } catch (...) { |
181 | BOOST_TEST(false); |
182 | } |
183 | BOOST_TEST(res[1].valid()); |
184 | BOOST_TEST(res[1].is_ready()); |
185 | BOOST_TEST(res[1].get() == 321); |
186 | } |
187 | { // packaged_task shared_future copy-constructible |
188 | boost::packaged_task<int()> pt1(&p1); |
189 | boost::shared_future<int> f1 = pt1.get_future().share(); |
190 | BOOST_TEST(f1.valid()); |
191 | boost::packaged_task<int()> pt2(&p2); |
192 | boost::shared_future<int> f2 = pt2.get_future().share(); |
193 | BOOST_TEST(f2.valid()); |
194 | boost::csbl::vector<boost::shared_future<int> > v; |
195 | v.push_back(x: f1); |
196 | v.push_back(x: f2); |
197 | BOOST_TEST(v[0].valid()); |
198 | BOOST_TEST(v[1].valid()); |
199 | boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(first: v.begin(), last: v.end()); |
200 | if (0) // fixme |
201 | BOOST_TEST(v[0].valid()); |
202 | if (0) // fixme |
203 | BOOST_TEST(v[1].valid()); |
204 | BOOST_TEST(all.valid()); |
205 | BOOST_TEST(! all.is_ready()); |
206 | pt1(); |
207 | BOOST_TEST(! all.is_ready()); |
208 | pt2(); |
209 | boost::this_thread::sleep_for(d: boost::chrono::milliseconds(300)); |
210 | BOOST_TEST(all.is_ready()); |
211 | boost::csbl::vector<boost::shared_future<int> > res = all.get(); |
212 | BOOST_TEST(res[0].valid()); |
213 | BOOST_TEST(res[0].is_ready()); |
214 | BOOST_TEST(res[0].get() == 123); |
215 | BOOST_TEST(res[1].valid()); |
216 | BOOST_TEST(res[1].is_ready()); |
217 | BOOST_TEST(res[1].get() == 321); |
218 | } |
219 | { // async future copy-constructible |
220 | boost::future<int> f1 = boost::async(policy: boost::launch::async, f: &p1); |
221 | BOOST_TEST(f1.valid()); |
222 | boost::future<int> f2 = boost::async(policy: boost::launch::async, f: &p2); |
223 | BOOST_TEST(f2.valid()); |
224 | boost::csbl::vector<boost::future<int> > v; |
225 | v.push_back(x: boost::move(t&: f1)); |
226 | v.push_back(x: boost::move(t&: f2)); |
227 | BOOST_TEST(v[0].valid()); |
228 | BOOST_TEST(v[1].valid()); |
229 | boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(first: v.begin(), last: v.end()); |
230 | BOOST_TEST(! v[0].valid()); |
231 | BOOST_TEST(! v[1].valid()); |
232 | BOOST_TEST(all.valid()); |
233 | boost::csbl::vector<boost::future<int> > res = all.get(); |
234 | BOOST_TEST(res[0].valid()); |
235 | BOOST_TEST(res[0].is_ready()); |
236 | BOOST_TEST(res[0].get() == 123); |
237 | BOOST_TEST(res[1].valid()); |
238 | BOOST_TEST(res[1].is_ready()); |
239 | BOOST_TEST(res[1].get() == 321); |
240 | } |
241 | { // async shared_future copy-constructible |
242 | boost::shared_future<int> f1 = boost::async(policy: boost::launch::async, f: &p1).share(); |
243 | BOOST_TEST(f1.valid()); |
244 | boost::shared_future<int> f2 = boost::async(policy: boost::launch::async, f: &p2).share(); |
245 | BOOST_TEST(f2.valid()); |
246 | boost::csbl::vector<boost::shared_future<int> > v; |
247 | v.push_back(x: f1); |
248 | v.push_back(x: f2); |
249 | BOOST_TEST(v[0].valid()); |
250 | BOOST_TEST(v[1].valid()); |
251 | boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(first: v.begin(), last: v.end()); |
252 | if (0) // fixme |
253 | BOOST_TEST(v[0].valid()); |
254 | if (0) // fixme |
255 | BOOST_TEST(v[1].valid()); |
256 | BOOST_TEST(all.valid()); |
257 | boost::csbl::vector<boost::shared_future<int> > res = all.get(); |
258 | BOOST_TEST(res[0].valid()); |
259 | BOOST_TEST(res[0].is_ready()); |
260 | BOOST_TEST(res[0].get() == 123); |
261 | BOOST_TEST(res[1].valid()); |
262 | BOOST_TEST(res[1].is_ready()); |
263 | BOOST_TEST(res[1].get() == 321); |
264 | } |
265 | { // async future copy-constructible |
266 | boost::future<int> f1 = boost::async(policy: boost::launch::async, f: &p1); |
267 | BOOST_TEST(f1.valid()); |
268 | boost::future<int> f2 = boost::make_ready_future(value: 321); |
269 | BOOST_TEST(f2.valid()); |
270 | BOOST_TEST(f2.is_ready()); |
271 | boost::csbl::vector<boost::future<int> > v; |
272 | v.push_back(x: boost::move(t&: f1)); |
273 | v.push_back(x: boost::move(t&: f2)); |
274 | BOOST_TEST(v[0].valid()); |
275 | BOOST_TEST(v[1].valid()); |
276 | boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(first: v.begin(), last: v.end()); |
277 | BOOST_TEST(! v[0].valid()); |
278 | BOOST_TEST(! v[1].valid()); |
279 | BOOST_TEST(all.valid()); |
280 | boost::csbl::vector<boost::future<int> > res = all.get(); |
281 | BOOST_TEST(res[0].valid()); |
282 | BOOST_TEST(res[0].is_ready()); |
283 | BOOST_TEST(res[0].get() == 123); |
284 | BOOST_TEST(res[1].valid()); |
285 | BOOST_TEST(res[1].is_ready()); |
286 | BOOST_TEST(res[1].get() == 321); |
287 | } |
288 | #if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD |
289 | // fixme darwin-4.8.0_11 terminate called without an active exception |
290 | { // deferred future copy-constructible |
291 | boost::future<int> f1 = boost::async(policy: boost::launch::deferred, f: &p1); |
292 | boost::future<int> f2 = boost::async(policy: boost::launch::deferred, f: &p2); |
293 | boost::csbl::vector<boost::future<int> > v; |
294 | v.push_back(x: boost::move(t&: f1)); |
295 | v.push_back(x: boost::move(t&: f2)); |
296 | BOOST_TEST(v[0].valid()); |
297 | BOOST_TEST(v[1].valid()); |
298 | boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(first: v.begin(), last: v.end()); |
299 | BOOST_TEST(! v[0].valid()); |
300 | BOOST_TEST(! v[1].valid()); |
301 | BOOST_TEST(all.valid()); |
302 | boost::csbl::vector<boost::future<int> > res = all.get(); |
303 | BOOST_TEST(res[0].valid()); |
304 | BOOST_TEST(res[0].is_ready()); |
305 | BOOST_TEST(res[0].get() == 123); |
306 | BOOST_TEST(res[1].valid()); |
307 | BOOST_TEST(res[1].is_ready()); |
308 | BOOST_TEST(res[1].get() == 321); |
309 | } |
310 | // fixme darwin-4.8.0_11 terminate called without an active exception |
311 | { // deferred shared_future copy-constructible |
312 | boost::shared_future<int> f1 = boost::async(policy: boost::launch::deferred, f: &p1).share(); |
313 | boost::shared_future<int> f2 = boost::async(policy: boost::launch::deferred, f: &p2).share(); |
314 | boost::csbl::vector<boost::shared_future<int> > v; |
315 | v.push_back(x: f1); |
316 | v.push_back(x: f2); |
317 | BOOST_TEST(v[0].valid()); |
318 | BOOST_TEST(v[1].valid()); |
319 | boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_all(first: v.begin(), last: v.end()); |
320 | if (0) // fixme |
321 | BOOST_TEST(v[0].valid()); |
322 | if (0) // fixme |
323 | BOOST_TEST(v[1].valid()); |
324 | BOOST_TEST(all.valid()); |
325 | boost::csbl::vector<boost::shared_future<int> > res = all.get(); |
326 | BOOST_TEST(res[0].valid()); |
327 | BOOST_TEST(res[0].is_ready()); |
328 | BOOST_TEST(res[0].get() == 123); |
329 | BOOST_TEST(res[1].valid()); |
330 | BOOST_TEST(res[1].is_ready()); |
331 | BOOST_TEST(res[1].get() == 321); |
332 | } |
333 | #endif |
334 | #if ! defined BOOST_NO_CXX11_LAMBDAS |
335 | { // async futures copy-constructible then() |
336 | boost::future<int> f1 = boost::async(policy: boost::launch::async, f: &p1); |
337 | BOOST_TEST(f1.valid()); |
338 | boost::future<int> f2 = boost::async(policy: boost::launch::async, f: &p2); |
339 | BOOST_TEST(f2.valid()); |
340 | boost::csbl::vector<boost::future<int> > v; |
341 | v.push_back(x: boost::move(t&: f1)); |
342 | v.push_back(x: boost::move(t&: f2)); |
343 | BOOST_TEST(v[0].valid()); |
344 | BOOST_TEST(v[1].valid()); |
345 | boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_all(first: v.begin(), last: v.end()); |
346 | BOOST_TEST(! v[0].valid()); |
347 | BOOST_TEST(! v[1].valid()); |
348 | BOOST_TEST(all.valid()); |
349 | boost::future<int> sum = all.then(func: [](boost::future<boost::csbl::vector<boost::future<int> > > f) |
350 | { |
351 | boost::csbl::vector<boost::future<int> > v = f.get(); |
352 | return v[0].get() + v[1].get(); |
353 | }); |
354 | BOOST_TEST(sum.valid()); |
355 | BOOST_TEST(sum.get() == 444); |
356 | } |
357 | #endif |
358 | #endif |
359 | |
360 | return boost::report_errors(); |
361 | } |
362 | |
363 | |