1 | // (C) Copyright 2008-10 Anthony Williams |
2 | // |
3 | // Distributed under the Boost Software License, Version 1.0. (See |
4 | // accompanying file LICENSE_1_0.txt or copy at |
5 | // http://www.boost.org/LICENSE_1_0.txt) |
6 | |
7 | #define BOOST_THREAD_VERSION 2 |
8 | #define BOOST_TEST_MODULE Boost.Threads: futures test suite |
9 | |
10 | #include <boost/thread/thread_only.hpp> |
11 | #include <boost/thread/mutex.hpp> |
12 | #include <boost/thread/condition.hpp> |
13 | #include <boost/thread/future.hpp> |
14 | #include <utility> |
15 | #include <memory> |
16 | #include <string> |
17 | #include <iostream> |
18 | #include <boost/thread/detail/log.hpp> |
19 | |
20 | #include <boost/test/unit_test.hpp> |
21 | |
22 | #ifdef BOOST_MSVC |
23 | # pragma warning(disable: 4267) // conversion from ... to ..., possible loss of data |
24 | #endif |
25 | |
26 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
27 | template<typename T> |
28 | typename boost::remove_reference<T>::type&& cast_to_rval(T&& t) |
29 | { |
30 | return static_cast<typename boost::remove_reference<T>::type&&>(t); |
31 | } |
32 | #else |
33 | #if defined BOOST_THREAD_USES_MOVE |
34 | template<typename T> |
35 | boost::rv<T>& cast_to_rval(T& t) |
36 | { |
37 | return boost::move(t); |
38 | } |
39 | #else |
40 | template<typename T> |
41 | boost::detail::thread_move_t<T> cast_to_rval(T& t) |
42 | { |
43 | return boost::move(t); |
44 | } |
45 | #endif |
46 | #endif |
47 | |
48 | struct X |
49 | { |
50 | public: |
51 | int i; |
52 | |
53 | BOOST_THREAD_MOVABLE_ONLY(X) |
54 | X(): |
55 | i(42) |
56 | {} |
57 | X(BOOST_THREAD_RV_REF(X) other): |
58 | i(BOOST_THREAD_RV(other).i) |
59 | { |
60 | BOOST_THREAD_RV(other).i=0; |
61 | } |
62 | X& operator=(BOOST_THREAD_RV_REF(X) other) |
63 | { |
64 | i=BOOST_THREAD_RV(other).i; |
65 | BOOST_THREAD_RV(other).i=0; |
66 | return *this; |
67 | } |
68 | ~X() |
69 | {} |
70 | }; |
71 | namespace boost { |
72 | BOOST_THREAD_DCL_MOVABLE(X) |
73 | } |
74 | |
75 | int make_int() |
76 | { |
77 | return 42; |
78 | } |
79 | |
80 | int throw_runtime_error() |
81 | { |
82 | throw std::runtime_error("42" ); |
83 | } |
84 | |
85 | void set_promise_thread(boost::promise<int>* p) |
86 | { |
87 | p->set_value(42); |
88 | } |
89 | |
90 | struct my_exception |
91 | {}; |
92 | |
93 | void set_promise_exception_thread(boost::promise<int>* p) |
94 | { |
95 | p->set_exception(boost::copy_exception(e: my_exception())); |
96 | } |
97 | |
98 | |
99 | BOOST_AUTO_TEST_CASE(test_store_value_from_thread) |
100 | { |
101 | BOOST_DETAIL_THREAD_LOG; |
102 | try { |
103 | boost::promise<int> pi2; |
104 | BOOST_DETAIL_THREAD_LOG; |
105 | boost::unique_future<int> fi2(BOOST_THREAD_MAKE_RV_REF(pi2.get_future())); |
106 | BOOST_DETAIL_THREAD_LOG; |
107 | boost::thread(set_promise_thread,&pi2); |
108 | BOOST_DETAIL_THREAD_LOG; |
109 | int j=fi2.get(); |
110 | BOOST_DETAIL_THREAD_LOG; |
111 | BOOST_CHECK(j==42); |
112 | BOOST_DETAIL_THREAD_LOG; |
113 | BOOST_CHECK(fi2.is_ready()); |
114 | BOOST_DETAIL_THREAD_LOG; |
115 | BOOST_CHECK(fi2.has_value()); |
116 | BOOST_DETAIL_THREAD_LOG; |
117 | BOOST_CHECK(!fi2.has_exception()); |
118 | BOOST_DETAIL_THREAD_LOG; |
119 | BOOST_CHECK(fi2.get_state()==boost::future_state::ready); |
120 | BOOST_DETAIL_THREAD_LOG; |
121 | } |
122 | catch (...) |
123 | { |
124 | BOOST_CHECK(false&&"Exception thrown" ); |
125 | } |
126 | } |
127 | |
128 | BOOST_AUTO_TEST_CASE(test_store_exception) |
129 | { |
130 | BOOST_DETAIL_THREAD_LOG; |
131 | boost::promise<int> pi3; |
132 | boost::unique_future<int> fi3(BOOST_THREAD_MAKE_RV_REF(pi3.get_future())); |
133 | boost::thread(set_promise_exception_thread,&pi3); |
134 | try |
135 | { |
136 | fi3.get(); |
137 | BOOST_CHECK(false); |
138 | } |
139 | catch(my_exception) |
140 | { |
141 | BOOST_CHECK(true); |
142 | } |
143 | |
144 | BOOST_CHECK(fi3.is_ready()); |
145 | BOOST_CHECK(!fi3.has_value()); |
146 | BOOST_CHECK(fi3.has_exception()); |
147 | BOOST_CHECK(fi3.get_state()==boost::future_state::ready); |
148 | } |
149 | |
150 | BOOST_AUTO_TEST_CASE(test_initial_state) |
151 | { |
152 | BOOST_DETAIL_THREAD_LOG; |
153 | boost::unique_future<int> fi; |
154 | BOOST_CHECK(!fi.is_ready()); |
155 | BOOST_CHECK(!fi.has_value()); |
156 | BOOST_CHECK(!fi.has_exception()); |
157 | BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); |
158 | int i; |
159 | try |
160 | { |
161 | i=fi.get(); |
162 | (void)i; |
163 | BOOST_CHECK(false); |
164 | } |
165 | catch(boost::future_uninitialized) |
166 | { |
167 | BOOST_CHECK(true); |
168 | } |
169 | } |
170 | |
171 | BOOST_AUTO_TEST_CASE(test_waiting_future) |
172 | { |
173 | BOOST_DETAIL_THREAD_LOG; |
174 | boost::promise<int> pi; |
175 | boost::unique_future<int> fi; |
176 | fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); |
177 | |
178 | int i=0; |
179 | BOOST_CHECK(!fi.is_ready()); |
180 | BOOST_CHECK(!fi.has_value()); |
181 | BOOST_CHECK(!fi.has_exception()); |
182 | BOOST_CHECK(fi.get_state()==boost::future_state::waiting); |
183 | BOOST_CHECK(i==0); |
184 | } |
185 | |
186 | BOOST_AUTO_TEST_CASE(test_cannot_get_future_twice) |
187 | { |
188 | BOOST_DETAIL_THREAD_LOG; |
189 | boost::promise<int> pi; |
190 | BOOST_THREAD_MAKE_RV_REF(pi.get_future()); |
191 | |
192 | try |
193 | { |
194 | pi.get_future(); |
195 | BOOST_CHECK(false); |
196 | } |
197 | catch(boost::future_already_retrieved&) |
198 | { |
199 | BOOST_CHECK(true); |
200 | } |
201 | } |
202 | |
203 | BOOST_AUTO_TEST_CASE(test_set_value_updates_future_state) |
204 | { |
205 | BOOST_DETAIL_THREAD_LOG; |
206 | boost::promise<int> pi; |
207 | boost::unique_future<int> fi; |
208 | fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); |
209 | |
210 | pi.set_value(42); |
211 | |
212 | BOOST_CHECK(fi.is_ready()); |
213 | BOOST_CHECK(fi.has_value()); |
214 | BOOST_CHECK(!fi.has_exception()); |
215 | BOOST_CHECK(fi.get_state()==boost::future_state::ready); |
216 | } |
217 | |
218 | BOOST_AUTO_TEST_CASE(test_set_value_can_be_retrieved) |
219 | { |
220 | BOOST_DETAIL_THREAD_LOG; |
221 | boost::promise<int> pi; |
222 | boost::unique_future<int> fi; |
223 | fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); |
224 | |
225 | pi.set_value(42); |
226 | |
227 | int i=0; |
228 | BOOST_CHECK(i=fi.get()); |
229 | BOOST_CHECK(i==42); |
230 | BOOST_CHECK(fi.is_ready()); |
231 | BOOST_CHECK(fi.has_value()); |
232 | BOOST_CHECK(!fi.has_exception()); |
233 | BOOST_CHECK(fi.get_state()==boost::future_state::ready); |
234 | } |
235 | |
236 | BOOST_AUTO_TEST_CASE(test_set_value_can_be_moved) |
237 | { |
238 | BOOST_DETAIL_THREAD_LOG; |
239 | // boost::promise<int> pi; |
240 | // boost::unique_future<int> fi; |
241 | // fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); |
242 | |
243 | // pi.set_value(42); |
244 | |
245 | // int i=0; |
246 | // BOOST_CHECK(i=fi.get()); |
247 | // BOOST_CHECK(i==42); |
248 | // BOOST_CHECK(fi.is_ready()); |
249 | // BOOST_CHECK(fi.has_value()); |
250 | // BOOST_CHECK(!fi.has_exception()); |
251 | // BOOST_CHECK(fi.get_state()==boost::future_state::ready); |
252 | } |
253 | |
254 | BOOST_AUTO_TEST_CASE(test_future_from_packaged_task_is_waiting) |
255 | { |
256 | BOOST_DETAIL_THREAD_LOG; |
257 | boost::packaged_task<int> pt(make_int); |
258 | boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
259 | int i=0; |
260 | BOOST_CHECK(!fi.is_ready()); |
261 | BOOST_CHECK(!fi.has_value()); |
262 | BOOST_CHECK(!fi.has_exception()); |
263 | BOOST_CHECK(fi.get_state()==boost::future_state::waiting); |
264 | BOOST_CHECK(i==0); |
265 | } |
266 | |
267 | BOOST_AUTO_TEST_CASE(test_invoking_a_packaged_task_populates_future) |
268 | { |
269 | BOOST_DETAIL_THREAD_LOG; |
270 | boost::packaged_task<int> pt(make_int); |
271 | boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
272 | |
273 | pt(); |
274 | |
275 | int i=0; |
276 | BOOST_CHECK(fi.is_ready()); |
277 | BOOST_CHECK(fi.has_value()); |
278 | BOOST_CHECK(!fi.has_exception()); |
279 | BOOST_CHECK(fi.get_state()==boost::future_state::ready); |
280 | BOOST_CHECK(i=fi.get()); |
281 | BOOST_CHECK(i==42); |
282 | } |
283 | |
284 | BOOST_AUTO_TEST_CASE(test_invoking_a_packaged_task_twice_throws) |
285 | { |
286 | BOOST_DETAIL_THREAD_LOG; |
287 | boost::packaged_task<int> pt(make_int); |
288 | |
289 | pt(); |
290 | try |
291 | { |
292 | pt(); |
293 | BOOST_CHECK(false); |
294 | } |
295 | catch(boost::task_already_started) |
296 | { |
297 | BOOST_CHECK(true); |
298 | } |
299 | } |
300 | |
301 | |
302 | BOOST_AUTO_TEST_CASE(test_cannot_get_future_twice_from_task) |
303 | { |
304 | BOOST_DETAIL_THREAD_LOG; |
305 | boost::packaged_task<int> pt(make_int); |
306 | pt.get_future(); |
307 | try |
308 | { |
309 | pt.get_future(); |
310 | BOOST_CHECK(false); |
311 | } |
312 | catch(boost::future_already_retrieved) |
313 | { |
314 | BOOST_CHECK(true); |
315 | } |
316 | } |
317 | |
318 | BOOST_AUTO_TEST_CASE(test_task_stores_exception_if_function_throws) |
319 | { |
320 | BOOST_DETAIL_THREAD_LOG; |
321 | boost::packaged_task<int> pt(throw_runtime_error); |
322 | boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
323 | |
324 | pt(); |
325 | |
326 | BOOST_CHECK(fi.is_ready()); |
327 | BOOST_CHECK(!fi.has_value()); |
328 | BOOST_CHECK(fi.has_exception()); |
329 | BOOST_CHECK(fi.get_state()==boost::future_state::ready); |
330 | try |
331 | { |
332 | fi.get(); |
333 | BOOST_CHECK(false); |
334 | } |
335 | catch(std::exception&) |
336 | { |
337 | BOOST_CHECK(true); |
338 | } |
339 | catch(...) |
340 | { |
341 | BOOST_CHECK(!"Unknown exception thrown" ); |
342 | } |
343 | |
344 | } |
345 | |
346 | BOOST_AUTO_TEST_CASE(test_void_promise) |
347 | { |
348 | BOOST_DETAIL_THREAD_LOG; |
349 | boost::promise<void> p; |
350 | boost::unique_future<void> f(BOOST_THREAD_MAKE_RV_REF(p.get_future())); |
351 | p.set_value(); |
352 | BOOST_CHECK(f.is_ready()); |
353 | BOOST_CHECK(f.has_value()); |
354 | BOOST_CHECK(!f.has_exception()); |
355 | BOOST_CHECK(f.get_state()==boost::future_state::ready); |
356 | f.get(); |
357 | } |
358 | |
359 | BOOST_AUTO_TEST_CASE(test_reference_promise) |
360 | { |
361 | BOOST_DETAIL_THREAD_LOG; |
362 | boost::promise<int&> p; |
363 | boost::unique_future<int&> f(BOOST_THREAD_MAKE_RV_REF(p.get_future())); |
364 | int i=42; |
365 | p.set_value(i); |
366 | BOOST_CHECK(f.is_ready()); |
367 | BOOST_CHECK(f.has_value()); |
368 | BOOST_CHECK(!f.has_exception()); |
369 | BOOST_CHECK(f.get_state()==boost::future_state::ready); |
370 | BOOST_CHECK(&f.get()==&i); |
371 | } |
372 | |
373 | void do_nothing() |
374 | {} |
375 | |
376 | BOOST_AUTO_TEST_CASE(test_task_returning_void) |
377 | { |
378 | BOOST_DETAIL_THREAD_LOG; |
379 | boost::packaged_task<void> pt(do_nothing); |
380 | boost::unique_future<void> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
381 | |
382 | pt(); |
383 | |
384 | BOOST_CHECK(fi.is_ready()); |
385 | BOOST_CHECK(fi.has_value()); |
386 | BOOST_CHECK(!fi.has_exception()); |
387 | BOOST_CHECK(fi.get_state()==boost::future_state::ready); |
388 | } |
389 | |
390 | int global_ref_target=0; |
391 | |
392 | int& return_ref() |
393 | { |
394 | return global_ref_target; |
395 | } |
396 | |
397 | BOOST_AUTO_TEST_CASE(test_task_returning_reference) |
398 | { |
399 | BOOST_DETAIL_THREAD_LOG; |
400 | boost::packaged_task<int&> pt(return_ref); |
401 | boost::unique_future<int&> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
402 | |
403 | pt(); |
404 | |
405 | BOOST_CHECK(fi.is_ready()); |
406 | BOOST_CHECK(fi.has_value()); |
407 | BOOST_CHECK(!fi.has_exception()); |
408 | BOOST_CHECK(fi.get_state()==boost::future_state::ready); |
409 | int& i=fi.get(); |
410 | BOOST_CHECK(&i==&global_ref_target); |
411 | } |
412 | |
413 | BOOST_AUTO_TEST_CASE(test_shared_future) |
414 | { |
415 | BOOST_DETAIL_THREAD_LOG; |
416 | boost::packaged_task<int> pt(make_int); |
417 | boost::unique_future<int> fi=pt.get_future(); |
418 | |
419 | boost::shared_future<int> sf(::cast_to_rval(t&: fi)); |
420 | BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); |
421 | |
422 | pt(); |
423 | |
424 | int i=0; |
425 | BOOST_CHECK(sf.is_ready()); |
426 | BOOST_CHECK(sf.has_value()); |
427 | BOOST_CHECK(!sf.has_exception()); |
428 | BOOST_CHECK(sf.get_state()==boost::future_state::ready); |
429 | BOOST_CHECK(i=sf.get()); |
430 | BOOST_CHECK(i==42); |
431 | } |
432 | |
433 | BOOST_AUTO_TEST_CASE(test_copies_of_shared_future_become_ready_together) |
434 | { |
435 | BOOST_DETAIL_THREAD_LOG; |
436 | boost::packaged_task<int> pt(make_int); |
437 | boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
438 | |
439 | boost::shared_future<int> sf(::cast_to_rval(t&: fi)); |
440 | boost::shared_future<int> sf2(sf); |
441 | boost::shared_future<int> sf3; |
442 | sf3=sf; |
443 | BOOST_CHECK(sf.get_state()==boost::future_state::waiting); |
444 | BOOST_CHECK(sf2.get_state()==boost::future_state::waiting); |
445 | BOOST_CHECK(sf3.get_state()==boost::future_state::waiting); |
446 | |
447 | pt(); |
448 | |
449 | int i=0; |
450 | BOOST_CHECK(sf.is_ready()); |
451 | BOOST_CHECK(sf.has_value()); |
452 | BOOST_CHECK(!sf.has_exception()); |
453 | BOOST_CHECK(sf.get_state()==boost::future_state::ready); |
454 | BOOST_CHECK(i=sf.get()); |
455 | BOOST_CHECK(i==42); |
456 | i=0; |
457 | BOOST_CHECK(sf2.is_ready()); |
458 | BOOST_CHECK(sf2.has_value()); |
459 | BOOST_CHECK(!sf2.has_exception()); |
460 | BOOST_CHECK(sf2.get_state()==boost::future_state::ready); |
461 | BOOST_CHECK(i=sf2.get()); |
462 | BOOST_CHECK(i==42); |
463 | i=0; |
464 | BOOST_CHECK(sf3.is_ready()); |
465 | BOOST_CHECK(sf3.has_value()); |
466 | BOOST_CHECK(!sf3.has_exception()); |
467 | BOOST_CHECK(sf3.get_state()==boost::future_state::ready); |
468 | BOOST_CHECK(i=sf3.get()); |
469 | BOOST_CHECK(i==42); |
470 | } |
471 | |
472 | BOOST_AUTO_TEST_CASE(test_shared_future_can_be_move_assigned_from_unique_future) |
473 | { |
474 | BOOST_DETAIL_THREAD_LOG; |
475 | boost::packaged_task<int> pt(make_int); |
476 | boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
477 | |
478 | boost::shared_future<int> sf; |
479 | sf=::cast_to_rval(t&: fi); |
480 | BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); |
481 | |
482 | BOOST_CHECK(!sf.is_ready()); |
483 | BOOST_CHECK(!sf.has_value()); |
484 | BOOST_CHECK(!sf.has_exception()); |
485 | BOOST_CHECK(sf.get_state()==boost::future_state::waiting); |
486 | } |
487 | |
488 | BOOST_AUTO_TEST_CASE(test_shared_future_void) |
489 | { |
490 | BOOST_DETAIL_THREAD_LOG; |
491 | boost::packaged_task<void> pt(do_nothing); |
492 | boost::unique_future<void> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
493 | |
494 | boost::shared_future<void> sf(::cast_to_rval(t&: fi)); |
495 | BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); |
496 | |
497 | pt(); |
498 | |
499 | BOOST_CHECK(sf.is_ready()); |
500 | BOOST_CHECK(sf.has_value()); |
501 | BOOST_CHECK(!sf.has_exception()); |
502 | BOOST_CHECK(sf.get_state()==boost::future_state::ready); |
503 | sf.get(); |
504 | } |
505 | |
506 | BOOST_AUTO_TEST_CASE(test_shared_future_ref) |
507 | { |
508 | BOOST_DETAIL_THREAD_LOG; |
509 | boost::promise<int&> p; |
510 | boost::shared_future<int&> f(BOOST_THREAD_MAKE_RV_REF(p.get_future())); |
511 | int i=42; |
512 | p.set_value(i); |
513 | BOOST_CHECK(f.is_ready()); |
514 | BOOST_CHECK(f.has_value()); |
515 | BOOST_CHECK(!f.has_exception()); |
516 | BOOST_CHECK(f.get_state()==boost::future_state::ready); |
517 | BOOST_CHECK(&f.get()==&i); |
518 | } |
519 | |
520 | BOOST_AUTO_TEST_CASE(test_can_get_a_second_future_from_a_moved_promise) |
521 | { |
522 | BOOST_DETAIL_THREAD_LOG; |
523 | boost::promise<int> pi; |
524 | boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); |
525 | |
526 | boost::promise<int> pi2(::cast_to_rval(t&: pi)); |
527 | boost::unique_future<int> fi2(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); |
528 | |
529 | pi2.set_value(3); |
530 | BOOST_CHECK(fi.is_ready()); |
531 | BOOST_CHECK(!fi2.is_ready()); |
532 | BOOST_CHECK(fi.get()==3); |
533 | pi.set_value(42); |
534 | BOOST_CHECK(fi2.is_ready()); |
535 | BOOST_CHECK(fi2.get()==42); |
536 | } |
537 | |
538 | BOOST_AUTO_TEST_CASE(test_can_get_a_second_future_from_a_moved_void_promise) |
539 | { |
540 | BOOST_DETAIL_THREAD_LOG; |
541 | boost::promise<void> pi; |
542 | boost::unique_future<void> fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); |
543 | |
544 | boost::promise<void> pi2(::cast_to_rval(t&: pi)); |
545 | boost::unique_future<void> fi2(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); |
546 | |
547 | pi2.set_value(); |
548 | BOOST_CHECK(fi.is_ready()); |
549 | BOOST_CHECK(!fi2.is_ready()); |
550 | pi.set_value(); |
551 | BOOST_CHECK(fi2.is_ready()); |
552 | } |
553 | |
554 | BOOST_AUTO_TEST_CASE(test_unique_future_for_move_only_udt) |
555 | { |
556 | BOOST_DETAIL_THREAD_LOG; |
557 | boost::promise<X> pt; |
558 | boost::unique_future<X> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
559 | |
560 | pt.set_value(X()); |
561 | X res(fi.get()); |
562 | BOOST_CHECK(res.i==42); |
563 | } |
564 | |
565 | BOOST_AUTO_TEST_CASE(test_unique_future_for_string) |
566 | { |
567 | BOOST_DETAIL_THREAD_LOG; |
568 | boost::promise<std::string> pt; |
569 | boost::unique_future<std::string> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
570 | |
571 | pt.set_value(std::string("hello" )); |
572 | std::string res(fi.get()); |
573 | BOOST_CHECK(res=="hello" ); |
574 | |
575 | boost::promise<std::string> pt2; |
576 | fi=BOOST_THREAD_MAKE_RV_REF(pt2.get_future()); |
577 | |
578 | std::string const s="goodbye" ; |
579 | |
580 | pt2.set_value(s); |
581 | res=fi.get(); |
582 | BOOST_CHECK(res=="goodbye" ); |
583 | |
584 | boost::promise<std::string> pt3; |
585 | fi=BOOST_THREAD_MAKE_RV_REF(pt3.get_future()); |
586 | |
587 | std::string s2="foo" ; |
588 | |
589 | pt3.set_value(s2); |
590 | res=fi.get(); |
591 | BOOST_CHECK(res=="foo" ); |
592 | } |
593 | |
594 | boost::mutex callback_mutex; |
595 | unsigned callback_called=0; |
596 | |
597 | void wait_callback(boost::promise<int>& pi) |
598 | { |
599 | boost::lock_guard<boost::mutex> lk(callback_mutex); |
600 | ++callback_called; |
601 | try |
602 | { |
603 | pi.set_value(42); |
604 | } |
605 | catch(...) |
606 | { |
607 | } |
608 | } |
609 | |
610 | void do_nothing_callback(boost::promise<int>& /*pi*/) |
611 | { |
612 | boost::lock_guard<boost::mutex> lk(callback_mutex); |
613 | ++callback_called; |
614 | } |
615 | |
616 | BOOST_AUTO_TEST_CASE(test_wait_callback) |
617 | { |
618 | BOOST_DETAIL_THREAD_LOG; |
619 | callback_called=0; |
620 | boost::promise<int> pi; |
621 | boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); |
622 | pi.set_wait_callback(wait_callback); |
623 | fi.wait(); |
624 | BOOST_CHECK(callback_called); |
625 | BOOST_CHECK(fi.get()==42); |
626 | fi.wait(); |
627 | fi.wait(); |
628 | BOOST_CHECK(callback_called==1); |
629 | } |
630 | |
631 | BOOST_AUTO_TEST_CASE(test_wait_callback_with_timed_wait) |
632 | { |
633 | BOOST_DETAIL_THREAD_LOG; |
634 | callback_called=0; |
635 | boost::promise<int> pi; |
636 | boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); |
637 | pi.set_wait_callback(do_nothing_callback); |
638 | bool success=fi.timed_wait(rel_time: boost::posix_time::milliseconds(10)); |
639 | BOOST_CHECK(callback_called); |
640 | BOOST_CHECK(!success); |
641 | success=fi.timed_wait(rel_time: boost::posix_time::milliseconds(10)); |
642 | BOOST_CHECK(!success); |
643 | success=fi.timed_wait(rel_time: boost::posix_time::milliseconds(10)); |
644 | BOOST_CHECK(!success); |
645 | BOOST_CHECK(callback_called==3); |
646 | pi.set_value(42); |
647 | success=fi.timed_wait(rel_time: boost::posix_time::milliseconds(10)); |
648 | BOOST_CHECK(success); |
649 | BOOST_CHECK(callback_called==3); |
650 | BOOST_CHECK(fi.get()==42); |
651 | BOOST_CHECK(callback_called==3); |
652 | } |
653 | |
654 | |
655 | void wait_callback_for_task(boost::packaged_task<int>& pt) |
656 | { |
657 | BOOST_DETAIL_THREAD_LOG; |
658 | boost::lock_guard<boost::mutex> lk(callback_mutex); |
659 | ++callback_called; |
660 | try |
661 | { |
662 | pt(); |
663 | } |
664 | catch(...) |
665 | { |
666 | } |
667 | } |
668 | |
669 | |
670 | BOOST_AUTO_TEST_CASE(test_wait_callback_for_packaged_task) |
671 | { |
672 | BOOST_DETAIL_THREAD_LOG; |
673 | callback_called=0; |
674 | boost::packaged_task<int> pt(make_int); |
675 | boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
676 | pt.set_wait_callback(wait_callback_for_task); |
677 | fi.wait(); |
678 | BOOST_CHECK(callback_called); |
679 | BOOST_CHECK(fi.get()==42); |
680 | fi.wait(); |
681 | fi.wait(); |
682 | BOOST_CHECK(callback_called==1); |
683 | } |
684 | |
685 | BOOST_AUTO_TEST_CASE(test_packaged_task_can_be_moved) |
686 | { |
687 | BOOST_DETAIL_THREAD_LOG; |
688 | boost::packaged_task<int> pt(make_int); |
689 | |
690 | boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
691 | |
692 | BOOST_CHECK(!fi.is_ready()); |
693 | |
694 | boost::packaged_task<int> pt2(::cast_to_rval(t&: pt)); |
695 | |
696 | BOOST_CHECK(!fi.is_ready()); |
697 | try |
698 | { |
699 | pt(); |
700 | BOOST_CHECK(!"Can invoke moved task!" ); |
701 | } |
702 | catch(boost::task_moved&) |
703 | { |
704 | } |
705 | |
706 | BOOST_CHECK(!fi.is_ready()); |
707 | |
708 | pt2(); |
709 | |
710 | BOOST_CHECK(fi.is_ready()); |
711 | } |
712 | |
713 | BOOST_AUTO_TEST_CASE(test_destroying_a_promise_stores_broken_promise) |
714 | { |
715 | BOOST_DETAIL_THREAD_LOG; |
716 | boost::unique_future<int> f; |
717 | |
718 | { |
719 | boost::promise<int> p; |
720 | f=BOOST_THREAD_MAKE_RV_REF(p.get_future()); |
721 | } |
722 | BOOST_CHECK(f.is_ready()); |
723 | BOOST_CHECK(f.has_exception()); |
724 | try |
725 | { |
726 | f.get(); |
727 | } |
728 | catch(boost::broken_promise&) |
729 | { |
730 | } |
731 | } |
732 | |
733 | BOOST_AUTO_TEST_CASE(test_destroying_a_packaged_task_stores_broken_promise) |
734 | { |
735 | BOOST_DETAIL_THREAD_LOG; |
736 | boost::unique_future<int> f; |
737 | |
738 | { |
739 | boost::packaged_task<int> p(make_int); |
740 | f=BOOST_THREAD_MAKE_RV_REF(p.get_future()); |
741 | } |
742 | BOOST_CHECK(f.is_ready()); |
743 | BOOST_CHECK(f.has_exception()); |
744 | try |
745 | { |
746 | f.get(); |
747 | } |
748 | catch(boost::broken_promise&) |
749 | { |
750 | } |
751 | } |
752 | |
753 | int make_int_slowly() |
754 | { |
755 | boost::this_thread::sleep(rel_time: boost::posix_time::seconds(1)); |
756 | return 42; |
757 | } |
758 | |
759 | BOOST_AUTO_TEST_CASE(test_wait_for_either_of_two_futures_1) |
760 | { |
761 | BOOST_DETAIL_THREAD_LOG; |
762 | boost::packaged_task<int> pt(make_int_slowly); |
763 | boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
764 | boost::packaged_task<int> pt2(make_int_slowly); |
765 | boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
766 | |
767 | boost::thread(::cast_to_rval(t&: pt)); |
768 | |
769 | unsigned const future=boost::wait_for_any(f1,fs&: f2); |
770 | |
771 | BOOST_CHECK(future==0); |
772 | BOOST_CHECK(f1.is_ready()); |
773 | BOOST_CHECK(!f2.is_ready()); |
774 | BOOST_CHECK(f1.get()==42); |
775 | } |
776 | |
777 | BOOST_AUTO_TEST_CASE(test_wait_for_either_of_two_futures_2) |
778 | { |
779 | BOOST_DETAIL_THREAD_LOG; |
780 | boost::packaged_task<int> pt(make_int_slowly); |
781 | boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
782 | boost::packaged_task<int> pt2(make_int_slowly); |
783 | boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
784 | |
785 | boost::thread(::cast_to_rval(t&: pt2)); |
786 | |
787 | unsigned const future=boost::wait_for_any(f1,fs&: f2); |
788 | |
789 | BOOST_CHECK(future==1); |
790 | BOOST_CHECK(!f1.is_ready()); |
791 | BOOST_CHECK(f2.is_ready()); |
792 | BOOST_CHECK(f2.get()==42); |
793 | } |
794 | |
795 | BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_1) |
796 | { |
797 | BOOST_DETAIL_THREAD_LOG; |
798 | boost::packaged_task<int> pt(make_int_slowly); |
799 | boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
800 | boost::packaged_task<int> pt2(make_int_slowly); |
801 | boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
802 | boost::packaged_task<int> pt3(make_int_slowly); |
803 | boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
804 | |
805 | boost::thread(::cast_to_rval(t&: pt)); |
806 | |
807 | unsigned const future=boost::wait_for_any(f1,fs&: f2,fs&: f3); |
808 | |
809 | BOOST_CHECK(future==0); |
810 | BOOST_CHECK(f1.is_ready()); |
811 | BOOST_CHECK(!f2.is_ready()); |
812 | BOOST_CHECK(!f3.is_ready()); |
813 | BOOST_CHECK(f1.get()==42); |
814 | } |
815 | |
816 | BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_2) |
817 | { |
818 | BOOST_DETAIL_THREAD_LOG; |
819 | boost::packaged_task<int> pt(make_int_slowly); |
820 | boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
821 | boost::packaged_task<int> pt2(make_int_slowly); |
822 | boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
823 | boost::packaged_task<int> pt3(make_int_slowly); |
824 | boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
825 | |
826 | boost::thread(::cast_to_rval(t&: pt2)); |
827 | |
828 | unsigned const future=boost::wait_for_any(f1,fs&: f2,fs&: f3); |
829 | |
830 | BOOST_CHECK(future==1); |
831 | BOOST_CHECK(!f1.is_ready()); |
832 | BOOST_CHECK(f2.is_ready()); |
833 | BOOST_CHECK(!f3.is_ready()); |
834 | BOOST_CHECK(f2.get()==42); |
835 | } |
836 | |
837 | BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_3) |
838 | { |
839 | BOOST_DETAIL_THREAD_LOG; |
840 | boost::packaged_task<int> pt(make_int_slowly); |
841 | boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
842 | boost::packaged_task<int> pt2(make_int_slowly); |
843 | boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
844 | boost::packaged_task<int> pt3(make_int_slowly); |
845 | boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
846 | |
847 | boost::thread(::cast_to_rval(t&: pt3)); |
848 | |
849 | unsigned const future=boost::wait_for_any(f1,fs&: f2,fs&: f3); |
850 | |
851 | BOOST_CHECK(future==2); |
852 | BOOST_CHECK(!f1.is_ready()); |
853 | BOOST_CHECK(!f2.is_ready()); |
854 | BOOST_CHECK(f3.is_ready()); |
855 | BOOST_CHECK(f3.get()==42); |
856 | } |
857 | |
858 | BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_1) |
859 | { |
860 | BOOST_DETAIL_THREAD_LOG; |
861 | boost::packaged_task<int> pt(make_int_slowly); |
862 | boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
863 | boost::packaged_task<int> pt2(make_int_slowly); |
864 | boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
865 | boost::packaged_task<int> pt3(make_int_slowly); |
866 | boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
867 | boost::packaged_task<int> pt4(make_int_slowly); |
868 | boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); |
869 | |
870 | boost::thread(::cast_to_rval(t&: pt)); |
871 | |
872 | unsigned const future=boost::wait_for_any(f1,fs&: f2,fs&: f3,fs&: f4); |
873 | |
874 | BOOST_CHECK(future==0); |
875 | BOOST_CHECK(f1.is_ready()); |
876 | BOOST_CHECK(!f2.is_ready()); |
877 | BOOST_CHECK(!f3.is_ready()); |
878 | BOOST_CHECK(!f4.is_ready()); |
879 | BOOST_CHECK(f1.get()==42); |
880 | } |
881 | |
882 | BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_2) |
883 | { |
884 | BOOST_DETAIL_THREAD_LOG; |
885 | boost::packaged_task<int> pt(make_int_slowly); |
886 | boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
887 | boost::packaged_task<int> pt2(make_int_slowly); |
888 | boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
889 | boost::packaged_task<int> pt3(make_int_slowly); |
890 | boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
891 | boost::packaged_task<int> pt4(make_int_slowly); |
892 | boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); |
893 | |
894 | boost::thread(::cast_to_rval(t&: pt2)); |
895 | |
896 | unsigned const future=boost::wait_for_any(f1,fs&: f2,fs&: f3,fs&: f4); |
897 | |
898 | BOOST_CHECK(future==1); |
899 | BOOST_CHECK(!f1.is_ready()); |
900 | BOOST_CHECK(f2.is_ready()); |
901 | BOOST_CHECK(!f3.is_ready()); |
902 | BOOST_CHECK(!f4.is_ready()); |
903 | BOOST_CHECK(f2.get()==42); |
904 | } |
905 | |
906 | BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_3) |
907 | { |
908 | BOOST_DETAIL_THREAD_LOG; |
909 | boost::packaged_task<int> pt(make_int_slowly); |
910 | boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
911 | boost::packaged_task<int> pt2(make_int_slowly); |
912 | boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
913 | boost::packaged_task<int> pt3(make_int_slowly); |
914 | boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
915 | boost::packaged_task<int> pt4(make_int_slowly); |
916 | boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); |
917 | |
918 | boost::thread(::cast_to_rval(t&: pt3)); |
919 | |
920 | unsigned const future=boost::wait_for_any(f1,fs&: f2,fs&: f3,fs&: f4); |
921 | |
922 | BOOST_CHECK(future==2); |
923 | BOOST_CHECK(!f1.is_ready()); |
924 | BOOST_CHECK(!f2.is_ready()); |
925 | BOOST_CHECK(f3.is_ready()); |
926 | BOOST_CHECK(!f4.is_ready()); |
927 | BOOST_CHECK(f3.get()==42); |
928 | } |
929 | |
930 | BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_4) |
931 | { |
932 | BOOST_DETAIL_THREAD_LOG; |
933 | boost::packaged_task<int> pt(make_int_slowly); |
934 | boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
935 | boost::packaged_task<int> pt2(make_int_slowly); |
936 | boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
937 | boost::packaged_task<int> pt3(make_int_slowly); |
938 | boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
939 | boost::packaged_task<int> pt4(make_int_slowly); |
940 | boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); |
941 | |
942 | boost::thread(::cast_to_rval(t&: pt4)); |
943 | |
944 | unsigned const future=boost::wait_for_any(f1,fs&: f2,fs&: f3,fs&: f4); |
945 | |
946 | BOOST_CHECK(future==3); |
947 | BOOST_CHECK(!f1.is_ready()); |
948 | BOOST_CHECK(!f2.is_ready()); |
949 | BOOST_CHECK(!f3.is_ready()); |
950 | BOOST_CHECK(f4.is_ready()); |
951 | BOOST_CHECK(f4.get()==42); |
952 | } |
953 | |
954 | BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_1) |
955 | { |
956 | BOOST_DETAIL_THREAD_LOG; |
957 | boost::packaged_task<int> pt(make_int_slowly); |
958 | boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
959 | boost::packaged_task<int> pt2(make_int_slowly); |
960 | boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
961 | boost::packaged_task<int> pt3(make_int_slowly); |
962 | boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
963 | boost::packaged_task<int> pt4(make_int_slowly); |
964 | boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); |
965 | boost::packaged_task<int> pt5(make_int_slowly); |
966 | boost::unique_future<int> f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); |
967 | |
968 | boost::thread(::cast_to_rval(t&: pt)); |
969 | |
970 | unsigned const future=boost::wait_for_any(f1,fs&: f2,fs&: f3,fs&: f4,fs&: f5); |
971 | |
972 | BOOST_CHECK(future==0); |
973 | BOOST_CHECK(f1.is_ready()); |
974 | BOOST_CHECK(!f2.is_ready()); |
975 | BOOST_CHECK(!f3.is_ready()); |
976 | BOOST_CHECK(!f4.is_ready()); |
977 | BOOST_CHECK(!f5.is_ready()); |
978 | BOOST_CHECK(f1.get()==42); |
979 | } |
980 | |
981 | BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_2) |
982 | { |
983 | BOOST_DETAIL_THREAD_LOG; |
984 | boost::packaged_task<int> pt(make_int_slowly); |
985 | boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
986 | boost::packaged_task<int> pt2(make_int_slowly); |
987 | boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
988 | boost::packaged_task<int> pt3(make_int_slowly); |
989 | boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
990 | boost::packaged_task<int> pt4(make_int_slowly); |
991 | boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); |
992 | boost::packaged_task<int> pt5(make_int_slowly); |
993 | boost::unique_future<int> f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); |
994 | |
995 | boost::thread(::cast_to_rval(t&: pt2)); |
996 | |
997 | unsigned const future=boost::wait_for_any(f1,fs&: f2,fs&: f3,fs&: f4,fs&: f5); |
998 | |
999 | BOOST_CHECK(future==1); |
1000 | BOOST_CHECK(!f1.is_ready()); |
1001 | BOOST_CHECK(f2.is_ready()); |
1002 | BOOST_CHECK(!f3.is_ready()); |
1003 | BOOST_CHECK(!f4.is_ready()); |
1004 | BOOST_CHECK(!f5.is_ready()); |
1005 | BOOST_CHECK(f2.get()==42); |
1006 | } |
1007 | BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_3) |
1008 | { |
1009 | BOOST_DETAIL_THREAD_LOG; |
1010 | boost::packaged_task<int> pt(make_int_slowly); |
1011 | boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
1012 | boost::packaged_task<int> pt2(make_int_slowly); |
1013 | boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
1014 | boost::packaged_task<int> pt3(make_int_slowly); |
1015 | boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
1016 | boost::packaged_task<int> pt4(make_int_slowly); |
1017 | boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); |
1018 | boost::packaged_task<int> pt5(make_int_slowly); |
1019 | boost::unique_future<int> f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); |
1020 | |
1021 | boost::thread(::cast_to_rval(t&: pt3)); |
1022 | |
1023 | unsigned const future=boost::wait_for_any(f1,fs&: f2,fs&: f3,fs&: f4,fs&: f5); |
1024 | |
1025 | BOOST_CHECK(future==2); |
1026 | BOOST_CHECK(!f1.is_ready()); |
1027 | BOOST_CHECK(!f2.is_ready()); |
1028 | BOOST_CHECK(f3.is_ready()); |
1029 | BOOST_CHECK(!f4.is_ready()); |
1030 | BOOST_CHECK(!f5.is_ready()); |
1031 | BOOST_CHECK(f3.get()==42); |
1032 | } |
1033 | BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_4) |
1034 | { |
1035 | BOOST_DETAIL_THREAD_LOG; |
1036 | boost::packaged_task<int> pt(make_int_slowly); |
1037 | boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
1038 | boost::packaged_task<int> pt2(make_int_slowly); |
1039 | boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
1040 | boost::packaged_task<int> pt3(make_int_slowly); |
1041 | boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
1042 | boost::packaged_task<int> pt4(make_int_slowly); |
1043 | boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); |
1044 | boost::packaged_task<int> pt5(make_int_slowly); |
1045 | boost::unique_future<int> f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); |
1046 | |
1047 | boost::thread(::cast_to_rval(t&: pt4)); |
1048 | |
1049 | unsigned const future=boost::wait_for_any(f1,fs&: f2,fs&: f3,fs&: f4,fs&: f5); |
1050 | |
1051 | BOOST_CHECK(future==3); |
1052 | BOOST_CHECK(!f1.is_ready()); |
1053 | BOOST_CHECK(!f2.is_ready()); |
1054 | BOOST_CHECK(!f3.is_ready()); |
1055 | BOOST_CHECK(f4.is_ready()); |
1056 | BOOST_CHECK(!f5.is_ready()); |
1057 | BOOST_CHECK(f4.get()==42); |
1058 | } |
1059 | BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_5) |
1060 | { |
1061 | BOOST_DETAIL_THREAD_LOG; |
1062 | boost::packaged_task<int> pt(make_int_slowly); |
1063 | boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
1064 | boost::packaged_task<int> pt2(make_int_slowly); |
1065 | boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
1066 | boost::packaged_task<int> pt3(make_int_slowly); |
1067 | boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
1068 | boost::packaged_task<int> pt4(make_int_slowly); |
1069 | boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); |
1070 | boost::packaged_task<int> pt5(make_int_slowly); |
1071 | boost::unique_future<int> f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); |
1072 | |
1073 | boost::thread(::cast_to_rval(t&: pt5)); |
1074 | |
1075 | unsigned const future=boost::wait_for_any(f1,fs&: f2,fs&: f3,fs&: f4,fs&: f5); |
1076 | |
1077 | BOOST_CHECK(future==4); |
1078 | BOOST_CHECK(!f1.is_ready()); |
1079 | BOOST_CHECK(!f2.is_ready()); |
1080 | BOOST_CHECK(!f3.is_ready()); |
1081 | BOOST_CHECK(!f4.is_ready()); |
1082 | BOOST_CHECK(f5.is_ready()); |
1083 | BOOST_CHECK(f5.get()==42); |
1084 | } |
1085 | |
1086 | BOOST_AUTO_TEST_CASE(test_wait_for_either_invokes_callbacks) |
1087 | { |
1088 | BOOST_DETAIL_THREAD_LOG; |
1089 | callback_called=0; |
1090 | boost::packaged_task<int> pt(make_int_slowly); |
1091 | boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
1092 | boost::packaged_task<int> pt2(make_int_slowly); |
1093 | boost::unique_future<int> fi2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
1094 | pt.set_wait_callback(wait_callback_for_task); |
1095 | |
1096 | boost::thread(::cast_to_rval(t&: pt)); |
1097 | |
1098 | boost::wait_for_any(f1&: fi,fs&: fi2); |
1099 | BOOST_CHECK(callback_called==1); |
1100 | BOOST_CHECK(fi.get()==42); |
1101 | } |
1102 | |
1103 | BOOST_AUTO_TEST_CASE(test_wait_for_any_from_range) |
1104 | { |
1105 | BOOST_DETAIL_THREAD_LOG; |
1106 | unsigned const count=10; |
1107 | for(unsigned i=0;i<count;++i) |
1108 | { |
1109 | boost::packaged_task<int> tasks[count]; |
1110 | boost::unique_future<int> futures[count]; |
1111 | for(unsigned j=0;j<count;++j) |
1112 | { |
1113 | tasks[j]=boost::packaged_task<int>(make_int_slowly); |
1114 | futures[j]=BOOST_THREAD_MAKE_RV_REF(tasks[j].get_future()); |
1115 | } |
1116 | boost::thread(::cast_to_rval(t&: tasks[i])); |
1117 | |
1118 | BOOST_CHECK(boost::wait_for_any(futures,futures)==futures); |
1119 | |
1120 | boost::unique_future<int>* const future=boost::wait_for_any(begin: futures,end: futures+count); |
1121 | |
1122 | BOOST_CHECK(future==(futures+i)); |
1123 | for(unsigned j=0;j<count;++j) |
1124 | { |
1125 | if(j!=i) |
1126 | { |
1127 | BOOST_CHECK(!futures[j].is_ready()); |
1128 | } |
1129 | else |
1130 | { |
1131 | BOOST_CHECK(futures[j].is_ready()); |
1132 | } |
1133 | } |
1134 | BOOST_CHECK(futures[i].get()==42); |
1135 | } |
1136 | } |
1137 | |
1138 | BOOST_AUTO_TEST_CASE(test_wait_for_all_from_range) |
1139 | { |
1140 | BOOST_DETAIL_THREAD_LOG; |
1141 | unsigned const count=10; |
1142 | boost::unique_future<int> futures[count]; |
1143 | for(unsigned j=0;j<count;++j) |
1144 | { |
1145 | boost::packaged_task<int> task(make_int_slowly); |
1146 | futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); |
1147 | boost::thread(::cast_to_rval(t&: task)); |
1148 | } |
1149 | |
1150 | boost::wait_for_all(begin: futures,end: futures+count); |
1151 | |
1152 | for(unsigned j=0;j<count;++j) |
1153 | { |
1154 | BOOST_CHECK(futures[j].is_ready()); |
1155 | } |
1156 | } |
1157 | |
1158 | BOOST_AUTO_TEST_CASE(test_wait_for_all_two_futures) |
1159 | { |
1160 | BOOST_DETAIL_THREAD_LOG; |
1161 | unsigned const count=2; |
1162 | boost::unique_future<int> futures[count]; |
1163 | for(unsigned j=0;j<count;++j) |
1164 | { |
1165 | boost::packaged_task<int> task(make_int_slowly); |
1166 | futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); |
1167 | boost::thread(::cast_to_rval(t&: task)); |
1168 | } |
1169 | |
1170 | boost::wait_for_all(f1&: futures[0],fs&: futures[1]); |
1171 | |
1172 | for(unsigned j=0;j<count;++j) |
1173 | { |
1174 | BOOST_CHECK(futures[j].is_ready()); |
1175 | } |
1176 | } |
1177 | |
1178 | BOOST_AUTO_TEST_CASE(test_wait_for_all_three_futures) |
1179 | { |
1180 | BOOST_DETAIL_THREAD_LOG; |
1181 | unsigned const count=3; |
1182 | boost::unique_future<int> futures[count]; |
1183 | for(unsigned j=0;j<count;++j) |
1184 | { |
1185 | boost::packaged_task<int> task(make_int_slowly); |
1186 | futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); |
1187 | boost::thread(::cast_to_rval(t&: task)); |
1188 | } |
1189 | |
1190 | boost::wait_for_all(f1&: futures[0],fs&: futures[1],fs&: futures[2]); |
1191 | |
1192 | for(unsigned j=0;j<count;++j) |
1193 | { |
1194 | BOOST_CHECK(futures[j].is_ready()); |
1195 | } |
1196 | } |
1197 | |
1198 | BOOST_AUTO_TEST_CASE(test_wait_for_all_four_futures) |
1199 | { |
1200 | BOOST_DETAIL_THREAD_LOG; |
1201 | unsigned const count=4; |
1202 | boost::unique_future<int> futures[count]; |
1203 | for(unsigned j=0;j<count;++j) |
1204 | { |
1205 | boost::packaged_task<int> task(make_int_slowly); |
1206 | futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); |
1207 | boost::thread(::cast_to_rval(t&: task)); |
1208 | } |
1209 | |
1210 | boost::wait_for_all(f1&: futures[0],fs&: futures[1],fs&: futures[2],fs&: futures[3]); |
1211 | |
1212 | for(unsigned j=0;j<count;++j) |
1213 | { |
1214 | BOOST_CHECK(futures[j].is_ready()); |
1215 | } |
1216 | } |
1217 | |
1218 | BOOST_AUTO_TEST_CASE(test_wait_for_all_five_futures) |
1219 | { |
1220 | BOOST_DETAIL_THREAD_LOG; |
1221 | unsigned const count=5; |
1222 | boost::unique_future<int> futures[count]; |
1223 | for(unsigned j=0;j<count;++j) |
1224 | { |
1225 | boost::packaged_task<int> task(make_int_slowly); |
1226 | futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); |
1227 | boost::thread(::cast_to_rval(t&: task)); |
1228 | } |
1229 | |
1230 | boost::wait_for_all(f1&: futures[0],fs&: futures[1],fs&: futures[2],fs&: futures[3],fs&: futures[4]); |
1231 | |
1232 | for(unsigned j=0;j<count;++j) |
1233 | { |
1234 | BOOST_CHECK(futures[j].is_ready()); |
1235 | } |
1236 | } |
1237 | |