1 //===----------------------------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Copyright (C) 2014 Vicente J. Botet Escriba
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)
15 // <boost/thread/future.hpp>
17 // template <class T, class Ts>
18 // future<tuple<T, Ts...>> when_all(T&&, Ts&& ...);
20 #include <boost/config.hpp>
22 #if ! defined BOOST_NO_CXX11_DECLTYPE
23 #define BOOST_RESULT_OF_USE_DECLTYPE
27 #define BOOST_THREAD_VERSION 4
29 #include <boost/thread/future.hpp>
30 #include <boost/detail/lightweight_test.hpp>
35 boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
41 throw std::logic_error("123");
45 boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
51 #if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
52 if (0) // todo not yet implemented
53 { // invalid future copy-constructible
54 boost::future<int> f1;
55 boost::future<int> f2 = boost::make_ready_future(321);
56 BOOST_TEST(! f1.valid());
57 BOOST_TEST(f2.valid());
58 boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
59 BOOST_TEST(! f1.valid());
60 BOOST_TEST(! f2.valid());
61 BOOST_TEST(all.valid());
62 boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
63 BOOST_TEST(boost::csbl::get<0>(res).valid());
64 BOOST_TEST(boost::csbl::get<0>(res).is_ready());
66 //BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
67 BOOST_TEST(boost::csbl::get<1>(res).valid());
68 BOOST_TEST(boost::csbl::get<1>(res).is_ready());
69 BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
71 { // is_ready future copy-constructible
72 boost::future<int> f1 = boost::make_ready_future(123);
73 boost::future<int> f2 = boost::make_ready_future(321);
74 BOOST_TEST(f1.valid());
75 BOOST_TEST(f1.is_ready());
76 BOOST_TEST(f2.valid());
77 BOOST_TEST(f2.is_ready());
78 boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
79 BOOST_TEST(! f1.valid());
80 BOOST_TEST(! f2.valid());
81 BOOST_TEST(all.valid());
82 if (0) // todo FAILS not yet implemented
83 BOOST_TEST(all.is_ready());
84 boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
85 BOOST_TEST(boost::csbl::get<0>(res).valid());
86 BOOST_TEST(boost::csbl::get<0>(res).is_ready());
87 BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
88 BOOST_TEST(boost::csbl::get<1>(res).valid());
89 BOOST_TEST(boost::csbl::get<1>(res).is_ready());
90 BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
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_all(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<0>(res).is_ready());
108 BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
109 BOOST_TEST(boost::csbl::get<1>(res).valid());
110 BOOST_TEST(boost::csbl::get<1>(res).is_ready());
111 BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
113 { // packaged_task future copy-constructible
114 boost::packaged_task<int()> pt1(&p1);
115 boost::future<int> f1 = pt1.get_future();
116 BOOST_TEST(f1.valid());
117 boost::packaged_task<int()> pt2(&p2);
118 boost::future<int> f2 = pt2.get_future();
119 BOOST_TEST(f2.valid());
120 boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
121 BOOST_TEST(! f1.valid());
122 BOOST_TEST(! f2.valid());
123 BOOST_TEST(all.valid());
126 boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
127 BOOST_TEST(boost::csbl::get<0>(res).valid());
128 BOOST_TEST(boost::csbl::get<0>(res).is_ready());
129 BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
130 BOOST_TEST(boost::csbl::get<1>(res).valid());
131 BOOST_TEST(boost::csbl::get<1>(res).is_ready());
132 BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
134 { // packaged_task future copy-constructible
135 boost::packaged_task<int()> pt1(&thr);
136 boost::future<int> f1 = pt1.get_future();
137 BOOST_TEST(f1.valid());
138 boost::packaged_task<int()> pt2(&p2);
139 boost::future<int> f2 = pt2.get_future();
140 BOOST_TEST(f2.valid());
141 boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
142 BOOST_TEST(! f1.valid());
143 BOOST_TEST(! f2.valid());
144 BOOST_TEST(all.valid());
147 boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
148 BOOST_TEST(boost::csbl::get<0>(res).valid());
149 BOOST_TEST(boost::csbl::get<0>(res).is_ready());
151 boost::csbl::get<0>(res).get();
153 } catch (std::logic_error& ex) {
154 BOOST_TEST(ex.what() == std::string("123"));
158 BOOST_TEST(boost::csbl::get<1>(res).valid());
159 BOOST_TEST(boost::csbl::get<1>(res).is_ready());
160 BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
162 { // packaged_task shared_future copy-constructible
163 boost::packaged_task<int()> pt1(&p1);
164 boost::shared_future<int> f1 = pt1.get_future().share();
165 BOOST_TEST(f1.valid());
166 boost::packaged_task<int()> pt2(&p2);
167 boost::shared_future<int> f2 = pt2.get_future().share();
168 BOOST_TEST(f2.valid());
169 boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_all(f1, f2);
170 BOOST_TEST(f1.valid());
171 BOOST_TEST(f2.valid());
172 BOOST_TEST(all.valid());
173 BOOST_TEST(! all.is_ready());
175 BOOST_TEST(! all.is_ready());
177 boost::this_thread::sleep_for(boost::chrono::milliseconds(300));
178 BOOST_TEST(all.is_ready());
179 boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get();
180 BOOST_TEST(boost::csbl::get<0>(res).valid());
181 BOOST_TEST(boost::csbl::get<0>(res).is_ready());
182 BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
183 BOOST_TEST(boost::csbl::get<1>(res).valid());
184 BOOST_TEST(boost::csbl::get<1>(res).is_ready());
185 BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
187 { // async future copy-constructible
188 boost::future<int> f1 = boost::async(boost::launch::async, &p1);
189 BOOST_TEST(f1.valid());
190 boost::future<int> f2 = boost::async(boost::launch::async, &p2);
191 BOOST_TEST(f2.valid());
192 boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
193 BOOST_TEST(! f1.valid());
194 BOOST_TEST(! f2.valid());
195 BOOST_TEST(all.valid());
196 boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
197 BOOST_TEST(boost::csbl::get<0>(res).valid());
198 BOOST_TEST(boost::csbl::get<0>(res).is_ready());
199 BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
200 BOOST_TEST(boost::csbl::get<1>(res).valid());
201 BOOST_TEST(boost::csbl::get<1>(res).is_ready());
202 BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
204 { // async shared_future copy-constructible
205 boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
206 BOOST_TEST(f1.valid());
207 boost::shared_future<int> f2 = boost::async(boost::launch::async, &p2).share();
208 BOOST_TEST(f2.valid());
209 boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_all(f1, f2);
210 BOOST_TEST(f1.valid());
211 BOOST_TEST(f2.valid());
212 BOOST_TEST(all.valid());
213 boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get();
214 BOOST_TEST(boost::csbl::get<0>(res).valid());
215 BOOST_TEST(boost::csbl::get<0>(res).is_ready());
216 BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
217 BOOST_TEST(boost::csbl::get<1>(res).valid());
218 BOOST_TEST(boost::csbl::get<1>(res).is_ready());
219 BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
221 { // async future copy-constructible
222 boost::future<int> f1 = boost::async(boost::launch::async, &p1);
223 BOOST_TEST(f1.valid());
224 boost::future<int> f2 = boost::make_ready_future(321);
225 BOOST_TEST(f2.valid());
226 BOOST_TEST(f2.is_ready());
227 boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
228 BOOST_TEST(! f1.valid());
229 BOOST_TEST(! f2.valid());
230 BOOST_TEST(all.valid());
231 boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
232 BOOST_TEST(boost::csbl::get<0>(res).valid());
233 BOOST_TEST(boost::csbl::get<0>(res).is_ready());
234 BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
235 BOOST_TEST(boost::csbl::get<1>(res).valid());
236 BOOST_TEST(boost::csbl::get<1>(res).is_ready());
237 BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
239 #if ! defined BOOST_NO_CXX11_DECLTYPE_N3276
240 // fixme darwin-4.8.0_11 terminate called without an active exception
241 { // deferred future copy-constructible
242 boost::future<int> f1 = boost::async(boost::launch::deferred, &p1);
243 boost::future<int> f2 = boost::async(boost::launch::deferred, &p2);
244 boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
245 BOOST_TEST(! f1.valid());
246 BOOST_TEST(! f2.valid());
247 BOOST_TEST(all.valid());
248 boost::csbl::tuple<boost::future<int>,boost::future<int> > res = all.get();
249 BOOST_TEST(boost::csbl::get<0>(res).valid());
250 BOOST_TEST(boost::csbl::get<0>(res).is_ready());
251 BOOST_TEST(boost::csbl::get<1>(res).valid());
252 BOOST_TEST(boost::csbl::get<1>(res).is_ready());
253 BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
254 BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
256 // fixme darwin-4.8.0_11 terminate called without an active exception
257 { // deferred shared_future copy-constructible
258 boost::shared_future<int> f1 = boost::async(boost::launch::deferred, &p1).share();
259 boost::shared_future<int> f2 = boost::async(boost::launch::deferred, &p2).share();
260 boost::future<boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > > all = boost::when_all(f1, f2);
261 BOOST_TEST(f1.valid());
262 BOOST_TEST(f2.valid());
263 BOOST_TEST(all.valid());
264 boost::csbl::tuple<boost::shared_future<int>,boost::shared_future<int> > res = all.get();
265 BOOST_TEST(boost::csbl::get<0>(res).valid());
266 BOOST_TEST(boost::csbl::get<0>(res).is_ready());
267 BOOST_TEST(boost::csbl::get<1>(res).valid());
268 BOOST_TEST(boost::csbl::get<1>(res).is_ready());
269 BOOST_TEST(boost::csbl::get<0>(res).get() == 123);
270 BOOST_TEST(boost::csbl::get<1>(res).get() == 321);
273 #if ! defined BOOST_NO_CXX11_LAMBDAS
274 { // async futures copy-constructible then()
275 boost::future<int> f1 = boost::async(boost::launch::async, &p1);
276 BOOST_TEST(f1.valid());
277 boost::future<int> f2 = boost::async(boost::launch::async, &p2);
278 BOOST_TEST(f2.valid());
279 boost::future<boost::csbl::tuple<boost::future<int>,boost::future<int> > > all = boost::when_all(boost::move(f1), boost::move(f2));
280 BOOST_TEST(! f1.valid());
281 BOOST_TEST(! f2.valid());
282 BOOST_TEST(all.valid());
283 boost::future<int> sum = all.then([](boost::future<boost::csbl::tuple<boost::future<int>, boost::future<int> > > f)
285 boost::csbl::tuple<boost::future<int>,boost::future<int> > v = f.get();
286 return boost::csbl::get<0>(v).get()+boost::csbl::get<1>(v).get();
288 BOOST_TEST(sum.valid());
289 BOOST_TEST(sum.get() == 444);
294 return boost::report_errors();