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