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