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::future
< int > f( p
.get_future() );
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_future_create() {
108 // default constructed future is not valid
109 boost::fibers::future
< int > f1
;
110 BOOST_CHECK( ! f1
.valid() );
112 // future retrieved from promise is valid (if it is the first)
113 boost::fibers::promise
< int > p2
;
114 boost::fibers::future
< int > f2
= p2
.get_future();
115 BOOST_CHECK( f2
.valid() );
118 void test_future_create_ref() {
119 // default constructed future is not valid
120 boost::fibers::future
< int& > f1
;
121 BOOST_CHECK( ! f1
.valid() );
123 // future retrieved from promise is valid (if it is the first)
124 boost::fibers::promise
< int& > p2
;
125 boost::fibers::future
< int& > f2
= p2
.get_future();
126 BOOST_CHECK( f2
.valid() );
129 void test_future_create_void() {
130 // default constructed future is not valid
131 boost::fibers::future
< void > f1
;
132 BOOST_CHECK( ! f1
.valid() );
134 // future retrieved from promise is valid (if it is the first)
135 boost::fibers::promise
< void > p2
;
136 boost::fibers::future
< void > f2
= p2
.get_future();
137 BOOST_CHECK( f2
.valid() );
140 void test_future_move() {
141 // future retrieved from promise is valid (if it is the first)
142 boost::fibers::promise
< int > p1
;
143 boost::fibers::future
< int > f1
= p1
.get_future();
144 BOOST_CHECK( f1
.valid() );
147 boost::fibers::future
< int > f2( std::move( f1
) );
148 BOOST_CHECK( ! f1
.valid() );
149 BOOST_CHECK( f2
.valid() );
153 BOOST_CHECK( f1
.valid() );
154 BOOST_CHECK( ! f2
.valid() );
157 void test_future_move_ref() {
158 // future retrieved from promise is valid (if it is the first)
159 boost::fibers::promise
< int& > p1
;
160 boost::fibers::future
< int& > f1
= p1
.get_future();
161 BOOST_CHECK( f1
.valid() );
164 boost::fibers::future
< int& > f2( std::move( f1
) );
165 BOOST_CHECK( ! f1
.valid() );
166 BOOST_CHECK( f2
.valid() );
170 BOOST_CHECK( f1
.valid() );
171 BOOST_CHECK( ! f2
.valid() );
174 void test_future_move_void() {
175 // future retrieved from promise is valid (if it is the first)
176 boost::fibers::promise
< void > p1
;
177 boost::fibers::future
< void > f1
= p1
.get_future();
178 BOOST_CHECK( f1
.valid() );
181 boost::fibers::future
< void > f2( std::move( f1
) );
182 BOOST_CHECK( ! f1
.valid() );
183 BOOST_CHECK( f2
.valid() );
187 BOOST_CHECK( f1
.valid() );
188 BOOST_CHECK( ! f2
.valid() );
191 void test_future_get() {
192 // future retrieved from promise is valid (if it is the first)
193 boost::fibers::promise
< int > p1
;
196 boost::fibers::future
< int > f1
= p1
.get_future();
197 BOOST_CHECK( f1
.valid() );
200 BOOST_CHECK( ! f1
.get_exception_ptr() );
201 BOOST_CHECK( 7 == f1
.get() );
202 BOOST_CHECK( ! f1
.valid() );
204 // throw broken_promise if promise is destroyed without set
206 boost::fibers::promise
< int > p2
;
207 f1
= p2
.get_future();
212 } catch ( boost::fibers::broken_promise
const&) {
215 BOOST_CHECK( ! f1
.valid() );
216 BOOST_CHECK( thrown
);
219 void test_future_get_move() {
220 // future retrieved from promise is valid (if it is the first)
221 boost::fibers::promise
< A
> p1
;
223 p1
.set_value( std::move( a
) );
225 boost::fibers::future
< A
> f1
= p1
.get_future();
226 BOOST_CHECK( f1
.valid() );
229 BOOST_CHECK( ! f1
.get_exception_ptr() );
230 BOOST_CHECK( 7 == f1
.get().value
);
231 BOOST_CHECK( ! f1
.valid() );
233 // throw broken_promise if promise is destroyed without set
235 boost::fibers::promise
< A
> p2
;
236 f1
= p2
.get_future();
241 } catch ( boost::fibers::broken_promise
const&) {
244 BOOST_CHECK( ! f1
.valid() );
245 BOOST_CHECK( thrown
);
248 void test_future_get_ref() {
249 // future retrieved from promise is valid (if it is the first)
250 boost::fibers::promise
< int& > p1
;
254 boost::fibers::future
< int& > f1
= p1
.get_future();
255 BOOST_CHECK( f1
.valid() );
258 BOOST_CHECK( ! f1
.get_exception_ptr() );
260 BOOST_CHECK( &i
== &j
);
261 BOOST_CHECK( ! f1
.valid() );
263 // throw broken_promise if promise is destroyed without set
265 boost::fibers::promise
< int& > p2
;
266 f1
= p2
.get_future();
271 } catch ( boost::fibers::broken_promise
const&) {
274 BOOST_CHECK( ! f1
.valid() );
275 BOOST_CHECK( thrown
);
279 void test_future_get_void() {
280 // future retrieved from promise is valid (if it is the first)
281 boost::fibers::promise
< void > p1
;
284 boost::fibers::future
< void > f1
= p1
.get_future();
285 BOOST_CHECK( f1
.valid() );
288 BOOST_CHECK( ! f1
.get_exception_ptr() );
290 BOOST_CHECK( ! f1
.valid() );
292 // throw broken_promise if promise is destroyed without set
294 boost::fibers::promise
< void > p2
;
295 f1
= p2
.get_future();
300 } catch ( boost::fibers::broken_promise
const&) {
303 BOOST_CHECK( ! f1
.valid() );
304 BOOST_CHECK( thrown
);
307 void test_future_share() {
308 // future retrieved from promise is valid (if it is the first)
309 boost::fibers::promise
< int > p1
;
313 boost::fibers::future
< int > f1
= p1
.get_future();
314 BOOST_CHECK( f1
.valid() );
317 boost::fibers::shared_future
< int > sf1
= f1
.share();
318 BOOST_CHECK( sf1
.valid() );
319 BOOST_CHECK( ! f1
.valid() );
322 BOOST_CHECK( ! sf1
.get_exception_ptr() );
324 BOOST_CHECK_EQUAL( i
, j
);
325 BOOST_CHECK( sf1
.valid() );
328 void test_future_share_ref() {
329 // future retrieved from promise is valid (if it is the first)
330 boost::fibers::promise
< int& > p1
;
334 boost::fibers::future
< int& > f1
= p1
.get_future();
335 BOOST_CHECK( f1
.valid() );
338 boost::fibers::shared_future
< int& > sf1
= f1
.share();
339 BOOST_CHECK( sf1
.valid() );
340 BOOST_CHECK( ! f1
.valid() );
343 BOOST_CHECK( ! sf1
.get_exception_ptr() );
345 BOOST_CHECK( &i
== &j
);
346 BOOST_CHECK( sf1
.valid() );
349 void test_future_share_void() {
350 // future retrieved from promise is valid (if it is the first)
351 boost::fibers::promise
< void > p1
;
354 boost::fibers::future
< void > f1
= p1
.get_future();
355 BOOST_CHECK( f1
.valid() );
358 boost::fibers::shared_future
< void > sf1
= f1
.share();
359 BOOST_CHECK( sf1
.valid() );
360 BOOST_CHECK( ! f1
.valid() );
363 BOOST_CHECK( ! sf1
.get_exception_ptr() );
365 BOOST_CHECK( sf1
.valid() );
368 void test_future_wait() {
369 // future retrieved from promise is valid (if it is the first)
370 boost::fibers::promise
< int > p1
;
371 boost::fibers::future
< int > f1
= p1
.get_future();
376 BOOST_CHECK( 7 == f1
.get() );
379 void test_future_wait_ref() {
380 // future retrieved from promise is valid (if it is the first)
381 boost::fibers::promise
< int& > p1
;
382 boost::fibers::future
< int& > f1
= p1
.get_future();
389 BOOST_CHECK( &i
== &j
);
392 void test_future_wait_void() {
393 // future retrieved from promise is valid (if it is the first)
394 boost::fibers::promise
< void > p1
;
395 boost::fibers::future
< void > f1
= p1
.get_future();
401 BOOST_CHECK( ! f1
.valid() );
404 void test_future_wait_for() {
405 // future retrieved from promise is valid (if it is the first)
406 boost::fibers::promise
< int > p1
;
407 boost::fibers::future
< int > f1
= p1
.get_future();
409 boost::fibers::fiber( boost::fibers::launch::post
, fn11
, std::move( p1
) ).detach();
412 BOOST_CHECK( f1
.valid() );
413 boost::fibers::future_status status
= f1
.wait_for( ms(300) );
414 BOOST_CHECK( boost::fibers::future_status::timeout
== status
);
416 BOOST_CHECK( f1
.valid() );
417 status
= f1
.wait_for( ms(300) );
418 BOOST_CHECK( boost::fibers::future_status::ready
== status
);
420 BOOST_CHECK( f1
.valid() );
424 void test_future_wait_for_ref() {
425 // future retrieved from promise is valid (if it is the first)
426 boost::fibers::promise
< int& > p1
;
427 boost::fibers::future
< int& > f1
= p1
.get_future();
429 boost::fibers::fiber( boost::fibers::launch::post
, fn12
, std::move( p1
) ).detach();
432 BOOST_CHECK( f1
.valid() );
433 boost::fibers::future_status status
= f1
.wait_for( ms(300) );
434 BOOST_CHECK( boost::fibers::future_status::timeout
== status
);
436 BOOST_CHECK( f1
.valid() );
437 status
= f1
.wait_for( ms(300) );
438 BOOST_CHECK( boost::fibers::future_status::ready
== status
);
440 BOOST_CHECK( f1
.valid() );
444 void test_future_wait_for_void() {
445 // future retrieved from promise is valid (if it is the first)
446 boost::fibers::promise
< void > p1
;
447 boost::fibers::future
< void > f1
= p1
.get_future();
449 boost::fibers::fiber( boost::fibers::launch::post
, fn13
, std::move( p1
) ).detach();
452 BOOST_CHECK( f1
.valid() );
453 boost::fibers::future_status status
= f1
.wait_for( ms(300) );
454 BOOST_CHECK( boost::fibers::future_status::timeout
== status
);
456 BOOST_CHECK( f1
.valid() );
457 status
= f1
.wait_for( ms(300) );
458 BOOST_CHECK( boost::fibers::future_status::ready
== status
);
460 BOOST_CHECK( f1
.valid() );
464 void test_future_wait_until() {
465 // future retrieved from promise is valid (if it is the first)
466 boost::fibers::promise
< int > p1
;
467 boost::fibers::future
< int > f1
= p1
.get_future();
469 boost::fibers::fiber( boost::fibers::launch::post
, fn11
, std::move( p1
) ).detach();
472 BOOST_CHECK( f1
.valid() );
473 boost::fibers::future_status status
= f1
.wait_until( Clock::now() + ms(300) );
474 BOOST_CHECK( boost::fibers::future_status::timeout
== status
);
476 BOOST_CHECK( f1
.valid() );
477 status
= f1
.wait_until( Clock::now() + ms(300) );
478 BOOST_CHECK( boost::fibers::future_status::ready
== status
);
480 BOOST_CHECK( f1
.valid() );
484 void test_future_wait_until_ref() {
485 // future retrieved from promise is valid (if it is the first)
486 boost::fibers::promise
< int& > p1
;
487 boost::fibers::future
< int& > f1
= p1
.get_future();
489 boost::fibers::fiber( boost::fibers::launch::post
, fn12
, std::move( p1
) ).detach();
492 BOOST_CHECK( f1
.valid() );
493 boost::fibers::future_status status
= f1
.wait_until( Clock::now() + ms(300) );
494 BOOST_CHECK( boost::fibers::future_status::timeout
== status
);
496 BOOST_CHECK( f1
.valid() );
497 status
= f1
.wait_until( Clock::now() + ms(300) );
498 BOOST_CHECK( boost::fibers::future_status::ready
== status
);
500 BOOST_CHECK( f1
.valid() );
504 void test_future_wait_until_void() {
505 // future retrieved from promise is valid (if it is the first)
506 boost::fibers::promise
< void > p1
;
507 boost::fibers::future
< void > f1
= p1
.get_future();
509 boost::fibers::fiber( boost::fibers::launch::post
, fn13
, std::move( p1
) ).detach();
512 BOOST_CHECK( f1
.valid() );
513 boost::fibers::future_status status
= f1
.wait_until( Clock::now() + ms(300) );
514 BOOST_CHECK( boost::fibers::future_status::timeout
== status
);
516 BOOST_CHECK( f1
.valid() );
517 status
= f1
.wait_until( Clock::now() + ms(300) );
518 BOOST_CHECK( boost::fibers::future_status::ready
== status
);
520 BOOST_CHECK( f1
.valid() );
524 void test_future_wait_with_fiber_1() {
525 boost::fibers::promise
< int > p1
;
526 boost::fibers::fiber( boost::fibers::launch::post
, fn1
, & p1
, 7).detach();
528 boost::fibers::future
< int > f1
= p1
.get_future();
531 BOOST_CHECK( 7 == f1
.get() );
534 void test_future_wait_with_fiber_2() {
535 boost::fibers::fiber( boost::fibers::launch::post
, fn2
).join();
539 boost::unit_test_framework::test_suite
* init_unit_test_suite(int, char*[]) {
540 boost::unit_test_framework::test_suite
* test
=
541 BOOST_TEST_SUITE("Boost.Fiber: future test suite");
543 test
->add(BOOST_TEST_CASE(test_future_create
));
544 test
->add(BOOST_TEST_CASE(test_future_create_ref
));
545 test
->add(BOOST_TEST_CASE(test_future_create_void
));
546 test
->add(BOOST_TEST_CASE(test_future_move
));
547 test
->add(BOOST_TEST_CASE(test_future_move_ref
));
548 test
->add(BOOST_TEST_CASE(test_future_move_void
));
549 test
->add(BOOST_TEST_CASE(test_future_get
));
550 test
->add(BOOST_TEST_CASE(test_future_get_move
));
551 test
->add(BOOST_TEST_CASE(test_future_get_ref
));
552 test
->add(BOOST_TEST_CASE(test_future_get_void
));
553 test
->add(BOOST_TEST_CASE(test_future_share
));
554 test
->add(BOOST_TEST_CASE(test_future_share_ref
));
555 test
->add(BOOST_TEST_CASE(test_future_share_void
));
556 test
->add(BOOST_TEST_CASE(test_future_wait
));
557 test
->add(BOOST_TEST_CASE(test_future_wait_ref
));
558 test
->add(BOOST_TEST_CASE(test_future_wait_void
));
559 test
->add(BOOST_TEST_CASE(test_future_wait_for
));
560 test
->add(BOOST_TEST_CASE(test_future_wait_for_ref
));
561 test
->add(BOOST_TEST_CASE(test_future_wait_for_void
));
562 test
->add(BOOST_TEST_CASE(test_future_wait_until
));
563 test
->add(BOOST_TEST_CASE(test_future_wait_until_ref
));
564 test
->add(BOOST_TEST_CASE(test_future_wait_until_void
));
565 test
->add(BOOST_TEST_CASE(test_future_wait_with_fiber_1
));
566 test
->add(BOOST_TEST_CASE(test_future_wait_with_fiber_2
));