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