1 // (C) Copyright 2008-10 Anthony Williams
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)
12 #include <boost/test/unit_test.hpp>
14 #include <boost/fiber/all.hpp>
18 struct my_exception
: public std::runtime_error
{
20 std::runtime_error("my_exception") {
27 A( A
const&) = delete;
30 A
& operator=( A
const&) = delete;
31 A
& operator=( A
&&) = default;
57 B
& operator=( B
&& other
) {
58 if ( this == & other
) return * this;
64 B( B
const&) = delete;
65 B
& operator=( B
const&) = delete;
68 void fn1( boost::fibers::promise
< int > * p
, int i
) {
69 boost::this_fiber::yield();
74 boost::fibers::promise
< int > p
;
75 boost::fibers::future
< int > f( p
.get_future() );
76 boost::this_fiber::yield();
77 boost::fibers::fiber( boost::fibers::launch::dispatch
, fn1
, & p
, 7).detach();
78 boost::this_fiber::yield();
79 BOOST_CHECK( 7 == f
.get() );
90 boost::throw_exception( my_exception() );
95 boost::throw_exception( my_exception() );
113 boost::throw_exception( my_exception() );
123 void test_packaged_task_create() {
124 // default constructed packaged_task is not valid
125 boost::fibers::packaged_task
< int() > t1
;
126 BOOST_CHECK( ! t1
.valid() );
128 // packaged_task from function
129 boost::fibers::packaged_task
< int() > t2( fn3
);
130 BOOST_CHECK( t2
.valid() );
134 void test_packaged_task_create_move() {
135 // default constructed packaged_task is not valid
136 boost::fibers::packaged_task
< A() > t1
;
137 BOOST_CHECK( ! t1
.valid() );
139 // packaged_task from function
140 boost::fibers::packaged_task
< A() > t2( fn9
);
141 BOOST_CHECK( t2
.valid() );
144 void test_packaged_task_create_void() {
145 // default constructed packaged_task is not valid
146 boost::fibers::packaged_task
< void() > t1
;
147 BOOST_CHECK( ! t1
.valid() );
149 // packaged_task from function
150 boost::fibers::packaged_task
< void() > t2( fn4
);
151 BOOST_CHECK( t2
.valid() );
154 void test_packaged_task_move() {
155 boost::fibers::packaged_task
< int() > t1( fn3
);
156 BOOST_CHECK( t1
.valid() );
159 boost::fibers::packaged_task
< int() > t2( std::move( t1
) );
160 BOOST_CHECK( ! t1
.valid() );
161 BOOST_CHECK( t2
.valid() );
165 BOOST_CHECK( t1
.valid() );
166 BOOST_CHECK( ! t2
.valid() );
169 void test_packaged_task_move_move() {
170 boost::fibers::packaged_task
< A() > t1( fn9
);
171 BOOST_CHECK( t1
.valid() );
174 boost::fibers::packaged_task
< A() > t2( std::move( t1
) );
175 BOOST_CHECK( ! t1
.valid() );
176 BOOST_CHECK( t2
.valid() );
180 BOOST_CHECK( t1
.valid() );
181 BOOST_CHECK( ! t2
.valid() );
184 void test_packaged_task_move_void() {
185 boost::fibers::packaged_task
< void() > t1( fn4
);
186 BOOST_CHECK( t1
.valid() );
189 boost::fibers::packaged_task
< void() > t2( std::move( t1
) );
190 BOOST_CHECK( ! t1
.valid() );
191 BOOST_CHECK( t2
.valid() );
195 BOOST_CHECK( t1
.valid() );
196 BOOST_CHECK( ! t2
.valid() );
199 void test_packaged_task_swap() {
200 boost::fibers::packaged_task
< int() > t1( fn3
);
201 BOOST_CHECK( t1
.valid() );
203 boost::fibers::packaged_task
< int() > t2
;
204 BOOST_CHECK( ! t2
.valid() );
208 BOOST_CHECK( ! t1
.valid() );
209 BOOST_CHECK( t2
.valid() );
212 void test_packaged_task_swap_move() {
213 boost::fibers::packaged_task
< A() > t1( fn9
);
214 BOOST_CHECK( t1
.valid() );
216 boost::fibers::packaged_task
< A() > t2
;
217 BOOST_CHECK( ! t2
.valid() );
221 BOOST_CHECK( ! t1
.valid() );
222 BOOST_CHECK( t2
.valid() );
225 void test_packaged_task_swap_void() {
226 boost::fibers::packaged_task
< void() > t1( fn4
);
227 BOOST_CHECK( t1
.valid() );
229 boost::fibers::packaged_task
< void() > t2
;
230 BOOST_CHECK( ! t2
.valid() );
234 BOOST_CHECK( ! t1
.valid() );
235 BOOST_CHECK( t2
.valid() );
238 void test_packaged_task_reset() {
240 boost::fibers::packaged_task
< int() > p( fn3
);
241 boost::fibers::future
< int > f( p
.get_future() );
242 BOOST_CHECK( p
.valid() );
245 BOOST_CHECK( 3 == f
.get() );
251 BOOST_CHECK( 3 == f
.get() );
254 boost::fibers::packaged_task
< int() > p
;
259 } catch ( boost::fibers::packaged_task_uninitialized
const&) {
262 BOOST_CHECK( thrown
);
266 void test_packaged_task_reset_destruction() {
268 boost::fibers::packaged_task
< B( bool) > p( fn11
);
269 BOOST_CHECK( p
.valid() );
271 BOOST_CHECK( 0 == gi
);
273 BOOST_CHECK( 3 == gi
);
277 BOOST_CHECK( -1 == gi
);
279 BOOST_CHECK( 3 == gi
);
283 BOOST_CHECK( 3 == gi
);
286 void test_packaged_task_reset_move() {
288 boost::fibers::packaged_task
< A() > p( fn9
);
289 boost::fibers::future
< A
> f( p
.get_future() );
290 BOOST_CHECK( p
.valid() );
293 BOOST_CHECK( 3 == f
.get().value
);
299 BOOST_CHECK( 3 == f
.get().value
);
302 boost::fibers::packaged_task
< A() > p
;
307 } catch ( boost::fibers::packaged_task_uninitialized
const&) {
310 BOOST_CHECK( thrown
);
314 void test_packaged_task_reset_void() {
316 boost::fibers::packaged_task
< void() > p( fn4
);
317 boost::fibers::future
< void > f( p
.get_future() );
318 BOOST_CHECK( p
.valid() );
330 boost::fibers::packaged_task
< void() > p
;
335 } catch ( boost::fibers::packaged_task_uninitialized
const&) {
338 BOOST_CHECK( thrown
);
342 void test_packaged_task_get_future() {
343 boost::fibers::packaged_task
< int() > t1( fn3
);
344 BOOST_CHECK( t1
.valid() );
347 boost::fibers::future
< int > f1
= t1
.get_future();
348 BOOST_CHECK( f1
.valid() );
350 // retrieve future a second time
353 f1
= t1
.get_future();
354 } catch ( boost::fibers::future_already_retrieved
const&) {
357 BOOST_CHECK( thrown
);
360 boost::fibers::packaged_task
< int() > t2( std::move( t1
) );
361 BOOST_CHECK( ! t1
.valid() );
362 BOOST_CHECK( t2
.valid() );
364 // retrieve future from uninitialized
367 f1
= t1
.get_future();
368 } catch ( boost::fibers::packaged_task_uninitialized
const&) {
371 BOOST_CHECK( thrown
);
374 void test_packaged_task_get_future_move() {
375 boost::fibers::packaged_task
< A() > t1( fn9
);
376 BOOST_CHECK( t1
.valid() );
379 boost::fibers::future
< A
> f1
= t1
.get_future();
380 BOOST_CHECK( f1
.valid() );
382 // retrieve future a second time
385 f1
= t1
.get_future();
386 } catch ( boost::fibers::future_already_retrieved
const&) {
389 BOOST_CHECK( thrown
);
392 boost::fibers::packaged_task
< A() > t2( std::move( t1
) );
393 BOOST_CHECK( ! t1
.valid() );
394 BOOST_CHECK( t2
.valid() );
396 // retrieve future from uninitialized
399 f1
= t1
.get_future();
400 } catch ( boost::fibers::packaged_task_uninitialized
const&) {
403 BOOST_CHECK( thrown
);
406 void test_packaged_task_get_future_void() {
407 boost::fibers::packaged_task
< void() > t1( fn4
);
408 BOOST_CHECK( t1
.valid() );
411 boost::fibers::future
< void > f1
= t1
.get_future();
412 BOOST_CHECK( f1
.valid() );
414 // retrieve future a second time
417 f1
= t1
.get_future();
418 } catch ( boost::fibers::future_already_retrieved
const&) {
421 BOOST_CHECK( thrown
);
424 boost::fibers::packaged_task
< void() > t2( std::move( t1
) );
425 BOOST_CHECK( ! t1
.valid() );
426 BOOST_CHECK( t2
.valid() );
428 // retrieve future from uninitialized
431 f1
= t1
.get_future();
432 } catch ( boost::fibers::packaged_task_uninitialized
const&) {
435 BOOST_CHECK( thrown
);
438 void test_packaged_task_exec() {
439 // promise takes a copyable as return type
440 boost::fibers::packaged_task
< int() > t1( fn3
);
441 BOOST_CHECK( t1
.valid() );
442 boost::fibers::future
< int > f1
= t1
.get_future();
443 BOOST_CHECK( f1
.valid() );
447 BOOST_CHECK( 3 == f1
.get() );
449 // exec a second time
453 } catch ( boost::fibers::promise_already_satisfied
const&) {
456 BOOST_CHECK( thrown
);
459 void test_packaged_task_exec_move() {
460 // promise takes a copyable as return type
461 boost::fibers::packaged_task
< A() > t1( fn9
);
462 BOOST_CHECK( t1
.valid() );
463 boost::fibers::future
< A
> f1
= t1
.get_future();
464 BOOST_CHECK( f1
.valid() );
468 BOOST_CHECK( 3 == f1
.get().value
);
470 // exec a second time
474 } catch ( boost::fibers::promise_already_satisfied
const&) {
477 BOOST_CHECK( thrown
);
480 void test_packaged_task_exec_param() {
481 // promise takes a copyable as return type
482 boost::fibers::packaged_task
< int( int) > t1( fn8
);
483 BOOST_CHECK( t1
.valid() );
484 boost::fibers::future
< int > f1
= t1
.get_future();
485 BOOST_CHECK( f1
.valid() );
489 BOOST_CHECK( 3 == f1
.get() );
491 // exec a second time
495 } catch ( boost::fibers::promise_already_satisfied
const&) {
498 BOOST_CHECK( thrown
);
500 //TODO: packaged_task returns a moveable-only as return type
503 void test_packaged_task_exec_ref() {
504 // promise takes a copyable as return type
505 boost::fibers::packaged_task
< int&() > t1( fn7
);
506 BOOST_CHECK( t1
.valid() );
507 boost::fibers::future
< int& > f1
= t1
.get_future();
508 BOOST_CHECK( f1
.valid() );
513 BOOST_CHECK( &gi
== &i
);
515 // exec a second time
519 } catch ( boost::fibers::promise_already_satisfied
const&) {
522 BOOST_CHECK( thrown
);
524 //TODO: packaged_task returns a moveable-only as return type
527 void test_packaged_task_exec_void() {
528 // promise takes a copyable as return type
529 boost::fibers::packaged_task
< void() > t1( fn4
);
530 BOOST_CHECK( t1
.valid() );
531 boost::fibers::future
< void > f1
= t1
.get_future();
532 BOOST_CHECK( f1
.valid() );
538 // exec a second time
542 } catch ( boost::fibers::promise_already_satisfied
const&) {
545 BOOST_CHECK( thrown
);
548 void test_packaged_task_exception() {
549 // promise takes a copyable as return type
550 boost::fibers::packaged_task
< int() > t1( fn5
);
551 BOOST_CHECK( t1
.valid() );
552 boost::fibers::future
< int > f1
= t1
.get_future();
553 BOOST_CHECK( f1
.valid() );
560 } catch ( my_exception
const&) {
563 BOOST_CHECK( thrown
);
565 boost::fibers::packaged_task
< int() > t2( fn5
);
566 BOOST_CHECK( t2
.valid() );
567 boost::fibers::future
< int > f2
= t2
.get_future();
568 BOOST_CHECK( f2
.valid() );
572 BOOST_CHECK( f2
.get_exception_ptr() );
575 { std::rethrow_exception( f2
.get_exception_ptr() ); }
576 catch ( my_exception
const&)
578 BOOST_CHECK( thrown
);
581 void test_packaged_task_exception_move() {
582 // promise takes a moveable as return type
583 boost::fibers::packaged_task
< A() > t1( fn10
);
584 BOOST_CHECK( t1
.valid() );
585 boost::fibers::future
< A
> f1
= t1
.get_future();
586 BOOST_CHECK( f1
.valid() );
593 } catch ( my_exception
const&) {
596 BOOST_CHECK( thrown
);
598 boost::fibers::packaged_task
< A() > t2( fn10
);
599 BOOST_CHECK( t2
.valid() );
600 boost::fibers::future
< A
> f2
= t2
.get_future();
601 BOOST_CHECK( f2
.valid() );
605 BOOST_CHECK( f2
.get_exception_ptr() );
608 { std::rethrow_exception( f2
.get_exception_ptr() ); }
609 catch ( my_exception
const&)
611 BOOST_CHECK( thrown
);
614 void test_packaged_task_exception_void() {
615 // promise takes a copyable as return type
616 boost::fibers::packaged_task
< void() > t1( fn6
);
617 BOOST_CHECK( t1
.valid() );
618 boost::fibers::future
< void > f1
= t1
.get_future();
619 BOOST_CHECK( f1
.valid() );
626 } catch ( my_exception
const&) {
629 BOOST_CHECK( thrown
);
631 boost::fibers::packaged_task
< void() > t2( fn6
);
632 BOOST_CHECK( t2
.valid() );
633 boost::fibers::future
< void > f2
= t2
.get_future();
634 BOOST_CHECK( f2
.valid() );
638 BOOST_CHECK( f2
.get_exception_ptr() );
641 std::rethrow_exception( f2
.get_exception_ptr() );
642 } catch ( my_exception
const&) {
645 BOOST_CHECK( thrown
);
649 boost::unit_test_framework::test_suite
* init_unit_test_suite(int, char*[]) {
650 boost::unit_test_framework::test_suite
* test
=
651 BOOST_TEST_SUITE("Boost.Fiber: packaged_task test suite");
653 test
->add(BOOST_TEST_CASE(test_packaged_task_create
));
654 test
->add(BOOST_TEST_CASE(test_packaged_task_create_move
));
655 test
->add(BOOST_TEST_CASE(test_packaged_task_create_void
));
656 test
->add(BOOST_TEST_CASE(test_packaged_task_move
));
657 test
->add(BOOST_TEST_CASE(test_packaged_task_move_move
));
658 test
->add(BOOST_TEST_CASE(test_packaged_task_move_void
));
659 test
->add(BOOST_TEST_CASE(test_packaged_task_swap
));
660 test
->add(BOOST_TEST_CASE(test_packaged_task_swap_move
));
661 test
->add(BOOST_TEST_CASE(test_packaged_task_swap_void
));
662 test
->add(BOOST_TEST_CASE(test_packaged_task_reset
));
663 test
->add(BOOST_TEST_CASE(test_packaged_task_reset_destruction
));
664 test
->add(BOOST_TEST_CASE(test_packaged_task_reset_move
));
665 test
->add(BOOST_TEST_CASE(test_packaged_task_reset_void
));
666 test
->add(BOOST_TEST_CASE(test_packaged_task_get_future
));
667 test
->add(BOOST_TEST_CASE(test_packaged_task_get_future_move
));
668 test
->add(BOOST_TEST_CASE(test_packaged_task_get_future_void
));
669 test
->add(BOOST_TEST_CASE(test_packaged_task_exec
));
670 test
->add(BOOST_TEST_CASE(test_packaged_task_exec_move
));
671 test
->add(BOOST_TEST_CASE(test_packaged_task_exec_param
));
672 test
->add(BOOST_TEST_CASE(test_packaged_task_exec_ref
));
673 test
->add(BOOST_TEST_CASE(test_packaged_task_exec_void
));
674 test
->add(BOOST_TEST_CASE(test_packaged_task_exception
));
675 test
->add(BOOST_TEST_CASE(test_packaged_task_exception_move
));
676 test
->add(BOOST_TEST_CASE(test_packaged_task_exception_void
));