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 
p1()38 int p1()
39 {
40   return 123;
41 }
42 
thr()43 int thr()
44 {
45   throw std::logic_error("123");
46 }
p2()47 int p2()
48 {
49   return 321;
50 }
51 
main()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(boost::move(f1));
60     v.push_back(boost::make_ready_future(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(v.begin(), 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(123);
80     boost::future<int> f2 = boost::make_ready_future(321);
81     boost::csbl::vector<boost::future<int> > v;
82     v.push_back(boost::move(f1));
83     v.push_back(boost::move(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(v.begin(), 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(123).share();
104     boost::shared_future<int> f2 = boost::make_ready_future(321).share();
105     boost::csbl::vector<boost::shared_future<int> > v;
106     v.push_back(f1);
107     v.push_back(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(v.begin(), 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(boost::move(f1));
137     v.push_back(boost::move(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(v.begin(), 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(boost::move(f1));
163     v.push_back(boost::move(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(v.begin(), 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(f1);
196     v.push_back(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(v.begin(), 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(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(boost::launch::async, &p1);
221     BOOST_TEST(f1.valid());
222     boost::future<int> f2 = boost::async(boost::launch::async, &p2);
223     BOOST_TEST(f2.valid());
224     boost::csbl::vector<boost::future<int> > v;
225     v.push_back(boost::move(f1));
226     v.push_back(boost::move(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(v.begin(), 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(boost::launch::async, &p1).share();
243     BOOST_TEST(f1.valid());
244     boost::shared_future<int> f2 = boost::async(boost::launch::async, &p2).share();
245     BOOST_TEST(f2.valid());
246     boost::csbl::vector<boost::shared_future<int> > v;
247     v.push_back(f1);
248     v.push_back(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(v.begin(), 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(boost::launch::async, &p1);
267     BOOST_TEST(f1.valid());
268     boost::future<int> f2 = boost::make_ready_future(321);
269     BOOST_TEST(f2.valid());
270     BOOST_TEST(f2.is_ready());
271     boost::csbl::vector<boost::future<int> > v;
272     v.push_back(boost::move(f1));
273     v.push_back(boost::move(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(v.begin(), 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(boost::launch::deferred, &p1);
292     boost::future<int> f2 = boost::async(boost::launch::deferred, &p2);
293     boost::csbl::vector<boost::future<int> > v;
294     v.push_back(boost::move(f1));
295     v.push_back(boost::move(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(v.begin(), 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(boost::launch::deferred, &p1).share();
313     boost::shared_future<int> f2 = boost::async(boost::launch::deferred, &p2).share();
314     boost::csbl::vector<boost::shared_future<int> > v;
315     v.push_back(f1);
316     v.push_back(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(v.begin(), 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(boost::launch::async, &p1);
337       BOOST_TEST(f1.valid());
338       boost::future<int> f2 = boost::async(boost::launch::async, &p2);
339       BOOST_TEST(f2.valid());
340       boost::csbl::vector<boost::future<int> > v;
341       v.push_back(boost::move(f1));
342       v.push_back(boost::move(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(v.begin(), 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([](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