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_any(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   boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
50   return 321;
51 }
52 
main()53 int main()
54 {
55 #if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
56   if (0) // todo not yet implemented
57   { // invalid future copy-constructible
58     boost::csbl::vector<boost::future<int> > v;
59     boost::future<int> f1;
60     v.push_back(boost::move(f1));
61     v.push_back(boost::make_ready_future(321));
62     BOOST_TEST(! v[0].valid());
63     BOOST_TEST(v[1].valid());
64 
65     boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
66     BOOST_TEST(! v[0].valid());
67     BOOST_TEST(! v[1].valid());
68     BOOST_TEST(all.valid());
69     boost::csbl::vector<boost::future<int> > res = all.get();
70     BOOST_TEST(res.size() == 2);
71     BOOST_TEST(res[1].valid());
72     BOOST_TEST(res[1].is_ready());
73     // has exception
74     //BOOST_TEST(res[0].get() == 123);
75     BOOST_TEST(res[1].valid());
76     BOOST_TEST(res[1].is_ready());
77     BOOST_TEST(res[1].get() == 321);
78   }
79   { // is_ready future copy-constructible
80     boost::future<int> f1 = boost::make_ready_future(123);
81     boost::future<int> f2 = boost::make_ready_future(321);
82     boost::csbl::vector<boost::future<int> > v;
83     v.push_back(boost::move(f1));
84     v.push_back(boost::move(f2));
85     BOOST_TEST(v[0].valid());
86     BOOST_TEST(v[0].is_ready());
87     BOOST_TEST(v[1].valid());
88     BOOST_TEST(v[1].is_ready());
89     boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
90     BOOST_TEST(! v[0].valid());
91     BOOST_TEST(! v[1].valid());
92     BOOST_TEST(all.valid());
93     if (0) // todo FAILS not yet implemented
94     BOOST_TEST(all.is_ready());
95     boost::csbl::vector<boost::future<int> > res = all.get();
96     BOOST_TEST(res[0].valid());
97     BOOST_TEST(res[0].is_ready());
98     BOOST_TEST(res[0].get() == 123);
99     BOOST_TEST(res[1].valid());
100     BOOST_TEST(res[1].is_ready());
101     BOOST_TEST(res[1].get() == 321);
102   }
103   { // is_ready shared_future copy-constructible
104     boost::shared_future<int> f1 = boost::make_ready_future(123).share();
105     boost::shared_future<int> f2 = boost::make_ready_future(321).share();
106     boost::csbl::vector<boost::shared_future<int> > v;
107     v.push_back(f1);
108     v.push_back(f2);
109     BOOST_TEST(v[0].valid());
110     BOOST_TEST(v[0].is_ready());
111     BOOST_TEST(v[1].valid());
112     BOOST_TEST(v[1].is_ready());
113     boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_any(v.begin(), v.end());
114     if (0) // fixme
115     BOOST_TEST(v[0].valid());
116     if (0) // fixme
117     BOOST_TEST(v[1].valid());
118     BOOST_TEST(all.valid());
119     if (0) // todo FAILS not yet implemented
120     BOOST_TEST(all.is_ready());
121     boost::csbl::vector<boost::shared_future<int> > res = all.get();
122     BOOST_TEST(res[0].valid());
123     BOOST_TEST(res[0].is_ready());
124     BOOST_TEST(res[0].get() == 123);
125     BOOST_TEST(res[1].valid());
126     BOOST_TEST(res[1].is_ready());
127     BOOST_TEST(res[1].get() == 321);
128   }
129   { // packaged_task future copy-constructible
130     boost::packaged_task<int()> pt1(&p1);
131     boost::future<int> f1 = pt1.get_future();
132     BOOST_TEST(f1.valid());
133     boost::packaged_task<int()> pt2(&p2);
134     boost::future<int> f2 = pt2.get_future();
135     BOOST_TEST(f2.valid());
136     boost::csbl::vector<boost::future<int> > v;
137     v.push_back(boost::move(f1));
138     v.push_back(boost::move(f2));
139     BOOST_TEST(v[0].valid());
140     BOOST_TEST(v[1].valid());
141     boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
142     BOOST_TEST(! v[0].valid());
143     BOOST_TEST(! v[1].valid());
144     BOOST_TEST(all.valid());
145     pt1();
146     pt2();
147     boost::csbl::vector<boost::future<int> > res = all.get();
148     BOOST_TEST(res[0].valid());
149     BOOST_TEST(res[0].is_ready());
150     BOOST_TEST(res[0].get() == 123);
151     BOOST_TEST(res[1].valid());
152     BOOST_TEST(res[1].is_ready());
153     BOOST_TEST(res[1].get() == 321);
154   }
155   { // packaged_task future copy-constructible
156     boost::packaged_task<int()> pt1(&thr);
157     boost::future<int> f1 = pt1.get_future();
158     BOOST_TEST(f1.valid());
159     boost::packaged_task<int()> pt2(&p2);
160     boost::future<int> f2 = pt2.get_future();
161     BOOST_TEST(f2.valid());
162     boost::csbl::vector<boost::future<int> > v;
163     v.push_back(boost::move(f1));
164     v.push_back(boost::move(f2));
165     BOOST_TEST(v[0].valid());
166     BOOST_TEST(v[1].valid());
167     boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
168     BOOST_TEST(! v[0].valid());
169     BOOST_TEST(! v[1].valid());
170     BOOST_TEST(all.valid());
171     pt1();
172     pt2();
173     boost::csbl::vector<boost::future<int> > res = all.get();
174     BOOST_TEST(res[0].valid());
175     BOOST_TEST(res[0].is_ready());
176     try {
177       res[0].get();
178       BOOST_TEST(false);
179     } catch (std::logic_error& ex) {
180       BOOST_TEST(ex.what() == std::string("123"));
181     } catch (...) {
182       BOOST_TEST(false);
183     }
184     BOOST_TEST(res[1].valid());
185     BOOST_TEST(res[1].is_ready());
186     BOOST_TEST(res[1].get() == 321);
187   }
188   { // packaged_task shared_future copy-constructible
189     boost::packaged_task<int()> pt1(&p1);
190     boost::shared_future<int> f1 = pt1.get_future().share();
191     BOOST_TEST(f1.valid());
192     boost::packaged_task<int()> pt2(&p2);
193     boost::shared_future<int> f2 = pt2.get_future().share();
194     BOOST_TEST(f2.valid());
195     boost::csbl::vector<boost::shared_future<int> > v;
196     v.push_back(f1);
197     v.push_back(f2);
198     BOOST_TEST(v[0].valid());
199     BOOST_TEST(v[1].valid());
200     boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_any(v.begin(), v.end());
201     if (0) // fixme
202     BOOST_TEST(v[0].valid());
203     if (0) // fixme
204     BOOST_TEST(v[1].valid());
205     BOOST_TEST(all.valid());
206     BOOST_TEST(! all.is_ready());
207     pt1();
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_any(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_any(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_any(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     if (0) // fixme
283     BOOST_TEST(! res[0].is_ready());
284     BOOST_TEST(res[0].get() == 123);
285     BOOST_TEST(res[1].valid());
286     BOOST_TEST(res[1].is_ready());
287     BOOST_TEST(res[1].get() == 321);
288   }
289 #if defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD
290   // fixme darwin-4.8.0_11 terminate called without an active exception
291   { // deferred future copy-constructible
292     boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
293     boost::future<int> f2 = boost::async(boost::launch::deferred, &p2);
294     boost::csbl::vector<boost::future<int> > v;
295     v.push_back(boost::move(f1));
296     v.push_back(boost::move(f2));
297     BOOST_TEST(v[0].valid());
298     BOOST_TEST(v[1].valid());
299     boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
300     BOOST_TEST(! v[0].valid());
301     BOOST_TEST(! v[1].valid());
302     BOOST_TEST(all.valid());
303     boost::csbl::vector<boost::future<int> > res = all.get();
304     BOOST_TEST(res[0].valid());
305     BOOST_TEST(res[0].is_ready());
306     BOOST_TEST(res[0].get() == 123);
307     BOOST_TEST(res[1].valid());
308     BOOST_TEST(! res[1].is_ready());
309     BOOST_TEST(res[1].get() == 321);
310   }
311   // fixme darwin-4.8.0_11 terminate called without an active exception
312   { // deferred shared_future copy-constructible
313     boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share();
314     boost::shared_future<int> f2 = boost::async(boost::launch::deferred, &p2).share();
315     boost::csbl::vector<boost::shared_future<int> > v;
316     v.push_back(f1);
317     v.push_back(f2);
318     BOOST_TEST(v[0].valid());
319     BOOST_TEST(v[1].valid());
320     boost::future<boost::csbl::vector<boost::shared_future<int> > > all = boost::when_any(v.begin(), v.end());
321     if (0) // fixme
322     BOOST_TEST(v[0].valid());
323     if (0) // fixme
324     BOOST_TEST(v[1].valid());
325     BOOST_TEST(all.valid());
326     boost::csbl::vector<boost::shared_future<int> > res = all.get();
327     BOOST_TEST(res[0].valid());
328     BOOST_TEST(res[0].is_ready());
329     BOOST_TEST(res[0].get() == 123);
330     BOOST_TEST(res[1].valid());
331     BOOST_TEST(! res[1].is_ready());
332     BOOST_TEST(res[1].get() == 321);
333   }
334 #endif
335 #if ! defined BOOST_NO_CXX11_LAMBDAS
336     { // async futures copy-constructible then()
337       boost::future<int> f1 = boost::async(boost::launch::async, &p1);
338       BOOST_TEST(f1.valid());
339       boost::future<int> f2 = boost::async(boost::launch::async, &p2);
340       BOOST_TEST(f2.valid());
341       boost::csbl::vector<boost::future<int> > v;
342       v.push_back(boost::move(f1));
343       v.push_back(boost::move(f2));
344       BOOST_TEST(v[0].valid());
345       BOOST_TEST(v[1].valid());
346       boost::future<boost::csbl::vector<boost::future<int> > > all = boost::when_any(v.begin(), v.end());
347       BOOST_TEST(! v[0].valid());
348       BOOST_TEST(! v[1].valid());
349       BOOST_TEST(all.valid());
350       boost::future<int> sum = all.then([](boost::future<boost::csbl::vector<boost::future<int> > > f)
351       {
352         boost::csbl::vector<boost::future<int> > v = f.get();
353         return v[0].get() + v[1].get();
354       });
355       BOOST_TEST(sum.valid());
356       BOOST_TEST(sum.get() == 444);
357     }
358 #endif
359 #endif
360 
361   return boost::report_errors();
362 }
363 
364