1 // (C) Copyright 2008-10 Anthony Williams
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
14 #include <boost/test/unit_test.hpp>
16 #include <boost/fiber/all.hpp>
18 typedef std::chrono::milliseconds ms
;
19 typedef std::chrono::high_resolution_clock Clock
;
23 struct my_exception
: public std::runtime_error
{
25 std::runtime_error("my_exception") {
32 A( A
const&) = delete;
35 A
& operator=( A
const&) = delete;
36 A
& operator=( A
&&) = default;
41 void fn1( boost::fibers::promise
< int > * p
, int i
) {
42 boost::this_fiber::yield();
47 boost::fibers::promise
< int > p
;
48 boost::fibers::shared_future
< int > f( p
.get_future().share() );
49 boost::this_fiber::yield();
50 boost::fibers::fiber( boost::fibers::launch::post
, fn1
, & p
, 7).detach();
51 boost::this_fiber::yield();
52 BOOST_CHECK( 7 == f
.get() );
63 boost::throw_exception( my_exception() );
68 boost::throw_exception( my_exception() );
86 boost::throw_exception( my_exception() );
90 void fn11( boost::fibers::promise
< int > p
) {
91 boost::this_fiber::sleep_for( ms(500) );
95 void fn12( boost::fibers::promise
< int& > p
) {
96 boost::this_fiber::sleep_for( ms(500) );
101 void fn13( boost::fibers::promise
< void > p
) {
102 boost::this_fiber::sleep_for( ms(500) );
107 void test_shared_future_create() {
109 // default constructed and assigned shared_future is not valid
110 boost::fibers::shared_future
< int > f1
;
111 boost::fibers::shared_future
< int > f2
= f1
;
112 BOOST_CHECK( ! f1
.valid() );
113 BOOST_CHECK( ! f2
.valid() );
117 // shared_future retrieved from promise is valid
118 boost::fibers::promise
< int > p
;
119 boost::fibers::shared_future
< int > f1
= p
.get_future();
120 boost::fibers::shared_future
< int > f2
= f1
;
121 BOOST_CHECK( f1
.valid() );
122 BOOST_CHECK( f2
.valid() );
126 void test_shared_future_create_ref() {
128 // default constructed and assigned shared_future is not valid
129 boost::fibers::shared_future
< int& > f1
;
130 boost::fibers::shared_future
< int& > f2
= f1
;
131 BOOST_CHECK( ! f1
.valid() );
132 BOOST_CHECK( ! f2
.valid() );
136 // shared_future retrieved from promise is valid
137 boost::fibers::promise
< int& > p
;
138 boost::fibers::shared_future
< int& > f1
= p
.get_future();
139 boost::fibers::shared_future
< int& > f2
= f1
;
140 BOOST_CHECK( f1
.valid() );
141 BOOST_CHECK( f2
.valid() );
145 void test_shared_future_create_void() {
147 // default constructed and assigned shared_future is not valid
148 boost::fibers::shared_future
< void > f1
;
149 boost::fibers::shared_future
< void > f2
= f1
;
150 BOOST_CHECK( ! f1
.valid() );
151 BOOST_CHECK( ! f2
.valid() );
155 // shared_future retrieved from promise is valid
156 boost::fibers::promise
< void > p
;
157 boost::fibers::shared_future
< void > f1
= p
.get_future();
158 boost::fibers::shared_future
< void > f2
= f1
;
159 BOOST_CHECK( f1
.valid() );
160 BOOST_CHECK( f2
.valid() );
164 void test_shared_future_get() {
165 // future retrieved from promise is valid (if it is the first)
166 boost::fibers::promise
< int > p1
;
169 boost::fibers::shared_future
< int > f1
= p1
.get_future().share();
170 BOOST_CHECK( f1
.valid() );
173 BOOST_CHECK( ! f1
.get_exception_ptr() );
174 BOOST_CHECK( 7 == f1
.get() );
175 BOOST_CHECK( f1
.valid() );
177 // throw broken_promise if promise is destroyed without set
179 boost::fibers::promise
< int > p2
;
180 f1
= p2
.get_future().share();
185 } catch ( boost::fibers::broken_promise
const&) {
188 BOOST_CHECK( f1
.valid() );
189 BOOST_CHECK( thrown
);
192 void test_shared_future_get_move() {
193 // future retrieved from promise is valid (if it is the first)
194 boost::fibers::promise
< A
> p1
;
196 p1
.set_value( std::move( a
) );
198 boost::fibers::shared_future
< A
> f1
= p1
.get_future().share();
199 BOOST_CHECK( f1
.valid() );
202 BOOST_CHECK( ! f1
.get_exception_ptr() );
203 BOOST_CHECK( 7 == f1
.get().value
);
204 BOOST_CHECK( f1
.valid() );
206 // throw broken_promise if promise is destroyed without set
208 boost::fibers::promise
< A
> p2
;
209 f1
= p2
.get_future().share();
214 } catch ( boost::fibers::broken_promise
const&) {
217 BOOST_CHECK( f1
.valid() );
218 BOOST_CHECK( thrown
);
221 void test_shared_future_get_ref() {
222 // future retrieved from promise is valid (if it is the first)
223 boost::fibers::promise
< int& > p1
;
227 boost::fibers::shared_future
< int& > f1
= p1
.get_future().share();
228 BOOST_CHECK( f1
.valid() );
231 BOOST_CHECK( ! f1
.get_exception_ptr() );
233 BOOST_CHECK( &i
== &j
);
234 BOOST_CHECK( f1
.valid() );
236 // throw broken_promise if promise is destroyed without set
238 boost::fibers::promise
< int& > p2
;
239 f1
= p2
.get_future().share();
244 } catch ( boost::fibers::broken_promise
const&) {
247 BOOST_CHECK( f1
.valid() );
248 BOOST_CHECK( thrown
);
252 void test_shared_future_get_void() {
253 // future retrieved from promise is valid (if it is the first)
254 boost::fibers::promise
< void > p1
;
257 boost::fibers::shared_future
< void > f1
= p1
.get_future().share();
258 BOOST_CHECK( f1
.valid() );
261 BOOST_CHECK( ! f1
.get_exception_ptr() );
263 BOOST_CHECK( f1
.valid() );
265 // throw broken_promise if promise is destroyed without set
267 boost::fibers::promise
< void > p2
;
268 f1
= p2
.get_future().share();
273 } catch ( boost::fibers::broken_promise
const&) {
276 BOOST_CHECK( f1
.valid() );
277 BOOST_CHECK( thrown
);
280 void test_future_share() {
281 // future retrieved from promise is valid (if it is the first)
282 boost::fibers::promise
< int > p1
;
286 boost::fibers::future
< int > f1
= p1
.get_future();
287 BOOST_CHECK( f1
.valid() );
290 boost::fibers::shared_future
< int > sf1
= f1
.share();
291 BOOST_CHECK( sf1
.valid() );
292 BOOST_CHECK( ! f1
.valid() );
295 BOOST_CHECK( ! sf1
.get_exception_ptr() );
297 BOOST_CHECK_EQUAL( i
, j
);
298 BOOST_CHECK( sf1
.valid() );
301 void test_future_share_ref() {
302 // future retrieved from promise is valid (if it is the first)
303 boost::fibers::promise
< int& > p1
;
307 boost::fibers::future
< int& > f1
= p1
.get_future();
308 BOOST_CHECK( f1
.valid() );
311 boost::fibers::shared_future
< int& > sf1
= f1
.share();
312 BOOST_CHECK( sf1
.valid() );
313 BOOST_CHECK( ! f1
.valid() );
316 BOOST_CHECK( ! sf1
.get_exception_ptr() );
318 BOOST_CHECK( &i
== &j
);
319 BOOST_CHECK( sf1
.valid() );
322 void test_future_share_void() {
323 // future retrieved from promise is valid (if it is the first)
324 boost::fibers::promise
< void > p1
;
327 boost::fibers::future
< void > f1
= p1
.get_future();
328 BOOST_CHECK( f1
.valid() );
331 boost::fibers::shared_future
< void > sf1
= f1
.share();
332 BOOST_CHECK( sf1
.valid() );
333 BOOST_CHECK( ! f1
.valid() );
336 BOOST_CHECK( ! sf1
.get_exception_ptr() );
338 BOOST_CHECK( sf1
.valid() );
341 void test_shared_future_wait() {
342 // future retrieved from promise is valid (if it is the first)
343 boost::fibers::promise
< int > p1
;
344 boost::fibers::shared_future
< int > f1
= p1
.get_future().share();
349 BOOST_CHECK( 7 == f1
.get() );
352 void test_shared_future_wait_ref() {
353 // future retrieved from promise is valid (if it is the first)
354 boost::fibers::promise
< int& > p1
;
355 boost::fibers::shared_future
< int& > f1
= p1
.get_future().share();
362 BOOST_CHECK( &i
== &j
);
365 void test_shared_future_wait_void() {
366 // future retrieved from promise is valid (if it is the first)
367 boost::fibers::promise
< void > p1
;
368 boost::fibers::shared_future
< void > f1
= p1
.get_future().share();
374 BOOST_CHECK( f1
.valid() );
377 void test_shared_future_wait_for() {
378 // future retrieved from promise is valid (if it is the first)
379 boost::fibers::promise
< int > p1
;
380 boost::fibers::shared_future
< int > f1
= p1
.get_future().share();
382 boost::fibers::fiber( boost::fibers::launch::post
, fn11
, std::move( p1
) ).detach();
385 BOOST_CHECK( f1
.valid() );
386 boost::fibers::future_status status
= f1
.wait_for( ms(300) );
387 BOOST_CHECK( boost::fibers::future_status::timeout
== status
);
389 BOOST_CHECK( f1
.valid() );
390 status
= f1
.wait_for( ms(300) );
391 BOOST_CHECK( boost::fibers::future_status::ready
== status
);
393 BOOST_CHECK( f1
.valid() );
397 void test_shared_future_wait_for_ref() {
398 // future retrieved from promise is valid (if it is the first)
399 boost::fibers::promise
< int& > p1
;
400 boost::fibers::shared_future
< int& > f1
= p1
.get_future().share();
402 boost::fibers::fiber( boost::fibers::launch::post
, fn12
, std::move( p1
) ).detach();
405 BOOST_CHECK( f1
.valid() );
406 boost::fibers::future_status status
= f1
.wait_for( ms(300) );
407 BOOST_CHECK( boost::fibers::future_status::timeout
== status
);
409 BOOST_CHECK( f1
.valid() );
410 status
= f1
.wait_for( ms(300) );
411 BOOST_CHECK( boost::fibers::future_status::ready
== status
);
413 BOOST_CHECK( f1
.valid() );
417 void test_shared_future_wait_for_void() {
418 // future retrieved from promise is valid (if it is the first)
419 boost::fibers::promise
< void > p1
;
420 boost::fibers::shared_future
< void > f1
= p1
.get_future().share();
422 boost::fibers::fiber( boost::fibers::launch::post
, fn13
, std::move( p1
) ).detach();
425 BOOST_CHECK( f1
.valid() );
426 boost::fibers::future_status status
= f1
.wait_for( ms(300) );
427 BOOST_CHECK( boost::fibers::future_status::timeout
== status
);
429 BOOST_CHECK( f1
.valid() );
430 status
= f1
.wait_for( ms(300) );
431 BOOST_CHECK( boost::fibers::future_status::ready
== status
);
433 BOOST_CHECK( f1
.valid() );
437 void test_shared_future_wait_until() {
438 // future retrieved from promise is valid (if it is the first)
439 boost::fibers::promise
< int > p1
;
440 boost::fibers::shared_future
< int > f1
= p1
.get_future().share();
442 boost::fibers::fiber( boost::fibers::launch::post
, fn11
, std::move( p1
) ).detach();
445 BOOST_CHECK( f1
.valid() );
446 boost::fibers::future_status status
= f1
.wait_until( Clock::now() + ms(300) );
447 BOOST_CHECK( boost::fibers::future_status::timeout
== status
);
449 BOOST_CHECK( f1
.valid() );
450 status
= f1
.wait_until( Clock::now() + ms(300) );
451 BOOST_CHECK( boost::fibers::future_status::ready
== status
);
453 BOOST_CHECK( f1
.valid() );
457 void test_shared_future_wait_until_ref() {
458 // future retrieved from promise is valid (if it is the first)
459 boost::fibers::promise
< int& > p1
;
460 boost::fibers::shared_future
< int& > f1
= p1
.get_future().share();
462 boost::fibers::fiber( boost::fibers::launch::post
, fn12
, std::move( p1
) ).detach();
465 BOOST_CHECK( f1
.valid() );
466 boost::fibers::future_status status
= f1
.wait_until( Clock::now() + ms(300) );
467 BOOST_CHECK( boost::fibers::future_status::timeout
== status
);
469 BOOST_CHECK( f1
.valid() );
470 status
= f1
.wait_until( Clock::now() + ms(300) );
471 BOOST_CHECK( boost::fibers::future_status::ready
== status
);
473 BOOST_CHECK( f1
.valid() );
477 void test_shared_future_wait_until_void() {
478 // future retrieved from promise is valid (if it is the first)
479 boost::fibers::promise
< void > p1
;
480 boost::fibers::shared_future
< void > f1
= p1
.get_future().share();
482 boost::fibers::fiber( boost::fibers::launch::post
, fn13
, std::move( p1
) ).detach();
485 BOOST_CHECK( f1
.valid() );
486 boost::fibers::future_status status
= f1
.wait_until( Clock::now() + ms(300) );
487 BOOST_CHECK( boost::fibers::future_status::timeout
== status
);
489 BOOST_CHECK( f1
.valid() );
490 status
= f1
.wait_until( Clock::now() + ms(300) );
491 BOOST_CHECK( boost::fibers::future_status::ready
== status
);
493 BOOST_CHECK( f1
.valid() );
497 void test_shared_future_wait_with_fiber_1() {
498 boost::fibers::promise
< int > p1
;
499 boost::fibers::fiber( boost::fibers::launch::post
, fn1
, & p1
, 7).detach();
501 boost::fibers::shared_future
< int > f1
= p1
.get_future().share();
504 BOOST_CHECK( 7 == f1
.get() );
507 void test_shared_future_wait_with_fiber_2() {
508 boost::fibers::fiber( boost::fibers::launch::post
, fn2
).join();
511 void test_shared_future_move() {
512 // future retrieved from promise is valid (if it is the first)
513 boost::fibers::promise
< int > p1
;
514 boost::fibers::shared_future
< int > f1
= p1
.get_future().share();
515 BOOST_CHECK( f1
.valid() );
518 boost::fibers::shared_future
< int > f2( std::move( f1
) );
519 BOOST_CHECK( ! f1
.valid() );
520 BOOST_CHECK( f2
.valid() );
524 BOOST_CHECK( f1
.valid() );
525 BOOST_CHECK( ! f2
.valid() );
528 void test_shared_future_move_move() {
529 // future retrieved from promise is valid (if it is the first)
530 boost::fibers::promise
< A
> p1
;
531 boost::fibers::shared_future
< A
> f1
= p1
.get_future().share();
532 BOOST_CHECK( f1
.valid() );
535 boost::fibers::shared_future
< A
> f2( std::move( f1
) );
536 BOOST_CHECK( ! f1
.valid() );
537 BOOST_CHECK( f2
.valid() );
541 BOOST_CHECK( f1
.valid() );
542 BOOST_CHECK( ! f2
.valid() );
545 void test_shared_future_move_ref() {
546 // future retrieved from promise is valid (if it is the first)
547 boost::fibers::promise
< int& > p1
;
548 boost::fibers::shared_future
< int& > f1
= p1
.get_future().share();
549 BOOST_CHECK( f1
.valid() );
552 boost::fibers::shared_future
< int& > f2( std::move( f1
) );
553 BOOST_CHECK( ! f1
.valid() );
554 BOOST_CHECK( f2
.valid() );
558 BOOST_CHECK( f1
.valid() );
559 BOOST_CHECK( ! f2
.valid() );
562 void test_shared_future_move_void() {
563 // future retrieved from promise is valid (if it is the first)
564 boost::fibers::promise
< void > p1
;
565 boost::fibers::shared_future
< void > f1
= p1
.get_future().share();
566 BOOST_CHECK( f1
.valid() );
569 boost::fibers::shared_future
< void > f2( std::move( f1
) );
570 BOOST_CHECK( ! f1
.valid() );
571 BOOST_CHECK( f2
.valid() );
575 BOOST_CHECK( f1
.valid() );
576 BOOST_CHECK( ! f2
.valid() );
580 boost::unit_test_framework::test_suite
* init_unit_test_suite(int, char*[]) {
581 boost::unit_test_framework::test_suite
* test
=
582 BOOST_TEST_SUITE("Boost.Fiber: shared_future test suite");
584 test
->add(BOOST_TEST_CASE(test_shared_future_create
));
585 test
->add(BOOST_TEST_CASE(test_shared_future_create_ref
));
586 test
->add(BOOST_TEST_CASE(test_shared_future_create_void
));
587 test
->add(BOOST_TEST_CASE(test_shared_future_move
));
588 test
->add(BOOST_TEST_CASE(test_shared_future_move_move
));
589 test
->add(BOOST_TEST_CASE(test_shared_future_move_ref
));
590 test
->add(BOOST_TEST_CASE(test_shared_future_move_void
));
591 test
->add(BOOST_TEST_CASE(test_shared_future_get
));
592 test
->add(BOOST_TEST_CASE(test_shared_future_get_move
));
593 test
->add(BOOST_TEST_CASE(test_shared_future_get_ref
));
594 test
->add(BOOST_TEST_CASE(test_shared_future_get_void
));
595 test
->add(BOOST_TEST_CASE(test_shared_future_wait
));
596 test
->add(BOOST_TEST_CASE(test_shared_future_wait_ref
));
597 test
->add(BOOST_TEST_CASE(test_shared_future_wait_void
));
598 test
->add(BOOST_TEST_CASE(test_shared_future_wait_for
));
599 test
->add(BOOST_TEST_CASE(test_shared_future_wait_for_ref
));
600 test
->add(BOOST_TEST_CASE(test_shared_future_wait_for_void
));
601 test
->add(BOOST_TEST_CASE(test_shared_future_wait_until
));
602 test
->add(BOOST_TEST_CASE(test_shared_future_wait_until_ref
));
603 test
->add(BOOST_TEST_CASE(test_shared_future_wait_until_void
));
604 test
->add(BOOST_TEST_CASE(test_shared_future_wait_with_fiber_1
));
605 test
->add(BOOST_TEST_CASE(test_shared_future_wait_with_fiber_2
));