123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608 |
- // (C) Copyright 2008-10 Anthony Williams
- // 2015 Oliver Kowalke
- //
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #include <chrono>
- #include <memory>
- #include <stdexcept>
- #include <string>
- #include <utility>
- #include <boost/test/unit_test.hpp>
- #include <boost/fiber/all.hpp>
- typedef std::chrono::milliseconds ms;
- typedef std::chrono::high_resolution_clock Clock;
- int gi = 7;
- struct my_exception : public std::runtime_error {
- my_exception() :
- std::runtime_error("my_exception") {
- }
- };
- struct A {
- A() = default;
- A( A const&) = delete;
- A( A &&) = default;
- A & operator=( A const&) = delete;
- A & operator=( A &&) = default;
- int value;
- };
- void fn1( boost::fibers::promise< int > * p, int i) {
- boost::this_fiber::yield();
- p->set_value( i);
- }
- void fn2() {
- boost::fibers::promise< int > p;
- boost::fibers::shared_future< int > f( p.get_future().share() );
- boost::this_fiber::yield();
- boost::fibers::fiber( boost::fibers::launch::post, fn1, & p, 7).detach();
- boost::this_fiber::yield();
- BOOST_CHECK( 7 == f.get() );
- }
- int fn3() {
- return 3;
- }
- void fn4() {
- }
- int fn5() {
- boost::throw_exception( my_exception() );
- return 3;
- }
- void fn6() {
- boost::throw_exception( my_exception() );
- }
- int & fn7() {
- return gi;
- }
- int fn8( int i) {
- return i;
- }
- A fn9() {
- A a;
- a.value = 3;
- return a;
- }
- A fn10() {
- boost::throw_exception( my_exception() );
- return A();
- }
- void fn11( boost::fibers::promise< int > p) {
- boost::this_fiber::sleep_for( ms(500) );
- p.set_value(3);
- }
- void fn12( boost::fibers::promise< int& > p) {
- boost::this_fiber::sleep_for( ms(500) );
- gi = 5;
- p.set_value( gi);
- }
- void fn13( boost::fibers::promise< void > p) {
- boost::this_fiber::sleep_for( ms(500) );
- p.set_value();
- }
- // shared_future
- void test_shared_future_create() {
- {
- // default constructed and assigned shared_future is not valid
- boost::fibers::shared_future< int > f1;
- boost::fibers::shared_future< int > f2 = f1;
- BOOST_CHECK( ! f1.valid() );
- BOOST_CHECK( ! f2.valid() );
- }
- {
- // shared_future retrieved from promise is valid
- boost::fibers::promise< int > p;
- boost::fibers::shared_future< int > f1 = p.get_future();
- boost::fibers::shared_future< int > f2 = f1;
- BOOST_CHECK( f1.valid() );
- BOOST_CHECK( f2.valid() );
- }
- }
- void test_shared_future_create_ref() {
- {
- // default constructed and assigned shared_future is not valid
- boost::fibers::shared_future< int& > f1;
- boost::fibers::shared_future< int& > f2 = f1;
- BOOST_CHECK( ! f1.valid() );
- BOOST_CHECK( ! f2.valid() );
- }
- {
- // shared_future retrieved from promise is valid
- boost::fibers::promise< int& > p;
- boost::fibers::shared_future< int& > f1 = p.get_future();
- boost::fibers::shared_future< int& > f2 = f1;
- BOOST_CHECK( f1.valid() );
- BOOST_CHECK( f2.valid() );
- }
- }
- void test_shared_future_create_void() {
- {
- // default constructed and assigned shared_future is not valid
- boost::fibers::shared_future< void > f1;
- boost::fibers::shared_future< void > f2 = f1;
- BOOST_CHECK( ! f1.valid() );
- BOOST_CHECK( ! f2.valid() );
- }
- {
- // shared_future retrieved from promise is valid
- boost::fibers::promise< void > p;
- boost::fibers::shared_future< void > f1 = p.get_future();
- boost::fibers::shared_future< void > f2 = f1;
- BOOST_CHECK( f1.valid() );
- BOOST_CHECK( f2.valid() );
- }
- }
- void test_shared_future_get() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< int > p1;
- p1.set_value( 7);
- boost::fibers::shared_future< int > f1 = p1.get_future().share();
- BOOST_CHECK( f1.valid() );
- // get
- BOOST_CHECK( ! f1.get_exception_ptr() );
- BOOST_CHECK( 7 == f1.get() );
- BOOST_CHECK( f1.valid() );
- // throw broken_promise if promise is destroyed without set
- {
- boost::fibers::promise< int > p2;
- f1 = p2.get_future().share();
- }
- bool thrown = false;
- try {
- f1.get();
- } catch ( boost::fibers::broken_promise const&) {
- thrown = true;
- }
- BOOST_CHECK( f1.valid() );
- BOOST_CHECK( thrown);
- }
- void test_shared_future_get_move() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< A > p1;
- A a; a.value = 7;
- p1.set_value( std::move( a) );
- boost::fibers::shared_future< A > f1 = p1.get_future().share();
- BOOST_CHECK( f1.valid() );
- // get
- BOOST_CHECK( ! f1.get_exception_ptr() );
- BOOST_CHECK( 7 == f1.get().value);
- BOOST_CHECK( f1.valid() );
- // throw broken_promise if promise is destroyed without set
- {
- boost::fibers::promise< A > p2;
- f1 = p2.get_future().share();
- }
- bool thrown = false;
- try {
- f1.get();
- } catch ( boost::fibers::broken_promise const&) {
- thrown = true;
- }
- BOOST_CHECK( f1.valid() );
- BOOST_CHECK( thrown);
- }
- void test_shared_future_get_ref() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< int& > p1;
- int i = 7;
- p1.set_value( i);
- boost::fibers::shared_future< int& > f1 = p1.get_future().share();
- BOOST_CHECK( f1.valid() );
- // get
- BOOST_CHECK( ! f1.get_exception_ptr() );
- int & j = f1.get();
- BOOST_CHECK( &i == &j);
- BOOST_CHECK( f1.valid() );
- // throw broken_promise if promise is destroyed without set
- {
- boost::fibers::promise< int& > p2;
- f1 = p2.get_future().share();
- }
- bool thrown = false;
- try {
- f1.get();
- } catch ( boost::fibers::broken_promise const&) {
- thrown = true;
- }
- BOOST_CHECK( f1.valid() );
- BOOST_CHECK( thrown);
- }
- void test_shared_future_get_void() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< void > p1;
- p1.set_value();
- boost::fibers::shared_future< void > f1 = p1.get_future().share();
- BOOST_CHECK( f1.valid() );
- // get
- BOOST_CHECK( ! f1.get_exception_ptr() );
- f1.get();
- BOOST_CHECK( f1.valid() );
- // throw broken_promise if promise is destroyed without set
- {
- boost::fibers::promise< void > p2;
- f1 = p2.get_future().share();
- }
- bool thrown = false;
- try {
- f1.get();
- } catch ( boost::fibers::broken_promise const&) {
- thrown = true;
- }
- BOOST_CHECK( f1.valid() );
- BOOST_CHECK( thrown);
- }
- void test_future_share() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< int > p1;
- int i = 7;
- p1.set_value( i);
- boost::fibers::future< int > f1 = p1.get_future();
- BOOST_CHECK( f1.valid() );
- // share
- boost::fibers::shared_future< int > sf1 = f1.share();
- BOOST_CHECK( sf1.valid() );
- BOOST_CHECK( ! f1.valid() );
- // get
- BOOST_CHECK( ! sf1.get_exception_ptr() );
- int j = sf1.get();
- BOOST_CHECK_EQUAL( i, j);
- BOOST_CHECK( sf1.valid() );
- }
- void test_future_share_ref() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< int& > p1;
- int i = 7;
- p1.set_value( i);
- boost::fibers::future< int& > f1 = p1.get_future();
- BOOST_CHECK( f1.valid() );
- // share
- boost::fibers::shared_future< int& > sf1 = f1.share();
- BOOST_CHECK( sf1.valid() );
- BOOST_CHECK( ! f1.valid() );
- // get
- BOOST_CHECK( ! sf1.get_exception_ptr() );
- int & j = sf1.get();
- BOOST_CHECK( &i == &j);
- BOOST_CHECK( sf1.valid() );
- }
- void test_future_share_void() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< void > p1;
- p1.set_value();
- boost::fibers::future< void > f1 = p1.get_future();
- BOOST_CHECK( f1.valid() );
- // share
- boost::fibers::shared_future< void > sf1 = f1.share();
- BOOST_CHECK( sf1.valid() );
- BOOST_CHECK( ! f1.valid() );
- // get
- BOOST_CHECK( ! sf1.get_exception_ptr() );
- sf1.get();
- BOOST_CHECK( sf1.valid() );
- }
- void test_shared_future_wait() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< int > p1;
- boost::fibers::shared_future< int > f1 = p1.get_future().share();
- // wait on future
- p1.set_value( 7);
- f1.wait();
- BOOST_CHECK( 7 == f1.get() );
- }
- void test_shared_future_wait_ref() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< int& > p1;
- boost::fibers::shared_future< int& > f1 = p1.get_future().share();
- // wait on future
- int i = 7;
- p1.set_value( i);
- f1.wait();
- int & j = f1.get();
- BOOST_CHECK( &i == &j);
- }
- void test_shared_future_wait_void() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< void > p1;
- boost::fibers::shared_future< void > f1 = p1.get_future().share();
- // wait on future
- p1.set_value();
- f1.wait();
- f1.get();
- BOOST_CHECK( f1.valid() );
- }
- void test_shared_future_wait_for() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< int > p1;
- boost::fibers::shared_future< int > f1 = p1.get_future().share();
- boost::fibers::fiber( boost::fibers::launch::post, fn11, std::move( p1) ).detach();
- // wait on future
- BOOST_CHECK( f1.valid() );
- boost::fibers::future_status status = f1.wait_for( ms(300) );
- BOOST_CHECK( boost::fibers::future_status::timeout == status);
- BOOST_CHECK( f1.valid() );
- status = f1.wait_for( ms(300) );
- BOOST_CHECK( boost::fibers::future_status::ready == status);
- BOOST_CHECK( f1.valid() );
- f1.wait();
- }
- void test_shared_future_wait_for_ref() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< int& > p1;
- boost::fibers::shared_future< int& > f1 = p1.get_future().share();
- boost::fibers::fiber( boost::fibers::launch::post, fn12, std::move( p1) ).detach();
- // wait on future
- BOOST_CHECK( f1.valid() );
- boost::fibers::future_status status = f1.wait_for( ms(300) );
- BOOST_CHECK( boost::fibers::future_status::timeout == status);
- BOOST_CHECK( f1.valid() );
- status = f1.wait_for( ms(300) );
- BOOST_CHECK( boost::fibers::future_status::ready == status);
- BOOST_CHECK( f1.valid() );
- f1.wait();
- }
- void test_shared_future_wait_for_void() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< void > p1;
- boost::fibers::shared_future< void > f1 = p1.get_future().share();
- boost::fibers::fiber( boost::fibers::launch::post, fn13, std::move( p1) ).detach();
- // wait on future
- BOOST_CHECK( f1.valid() );
- boost::fibers::future_status status = f1.wait_for( ms(300) );
- BOOST_CHECK( boost::fibers::future_status::timeout == status);
- BOOST_CHECK( f1.valid() );
- status = f1.wait_for( ms(300) );
- BOOST_CHECK( boost::fibers::future_status::ready == status);
- BOOST_CHECK( f1.valid() );
- f1.wait();
- }
- void test_shared_future_wait_until() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< int > p1;
- boost::fibers::shared_future< int > f1 = p1.get_future().share();
- boost::fibers::fiber( boost::fibers::launch::post, fn11, std::move( p1) ).detach();
- // wait on future
- BOOST_CHECK( f1.valid() );
- boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
- BOOST_CHECK( boost::fibers::future_status::timeout == status);
- BOOST_CHECK( f1.valid() );
- status = f1.wait_until( Clock::now() + ms(300) );
- BOOST_CHECK( boost::fibers::future_status::ready == status);
- BOOST_CHECK( f1.valid() );
- f1.wait();
- }
- void test_shared_future_wait_until_ref() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< int& > p1;
- boost::fibers::shared_future< int& > f1 = p1.get_future().share();
- boost::fibers::fiber( boost::fibers::launch::post, fn12, std::move( p1) ).detach();
- // wait on future
- BOOST_CHECK( f1.valid() );
- boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
- BOOST_CHECK( boost::fibers::future_status::timeout == status);
- BOOST_CHECK( f1.valid() );
- status = f1.wait_until( Clock::now() + ms(300) );
- BOOST_CHECK( boost::fibers::future_status::ready == status);
- BOOST_CHECK( f1.valid() );
- f1.wait();
- }
- void test_shared_future_wait_until_void() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< void > p1;
- boost::fibers::shared_future< void > f1 = p1.get_future().share();
- boost::fibers::fiber( boost::fibers::launch::post, fn13, std::move( p1) ).detach();
- // wait on future
- BOOST_CHECK( f1.valid() );
- boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
- BOOST_CHECK( boost::fibers::future_status::timeout == status);
- BOOST_CHECK( f1.valid() );
- status = f1.wait_until( Clock::now() + ms(300) );
- BOOST_CHECK( boost::fibers::future_status::ready == status);
- BOOST_CHECK( f1.valid() );
- f1.wait();
- }
- void test_shared_future_wait_with_fiber_1() {
- boost::fibers::promise< int > p1;
- boost::fibers::fiber( boost::fibers::launch::post, fn1, & p1, 7).detach();
- boost::fibers::shared_future< int > f1 = p1.get_future().share();
- // wait on future
- BOOST_CHECK( 7 == f1.get() );
- }
- void test_shared_future_wait_with_fiber_2() {
- boost::fibers::fiber( boost::fibers::launch::post, fn2).join();
- }
- void test_shared_future_move() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< int > p1;
- boost::fibers::shared_future< int > f1 = p1.get_future().share();
- BOOST_CHECK( f1.valid() );
- // move construction
- boost::fibers::shared_future< int > f2( std::move( f1) );
- BOOST_CHECK( ! f1.valid() );
- BOOST_CHECK( f2.valid() );
- // move assignment
- f1 = std::move( f2);
- BOOST_CHECK( f1.valid() );
- BOOST_CHECK( ! f2.valid() );
- }
- void test_shared_future_move_move() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< A > p1;
- boost::fibers::shared_future< A > f1 = p1.get_future().share();
- BOOST_CHECK( f1.valid() );
- // move construction
- boost::fibers::shared_future< A > f2( std::move( f1) );
- BOOST_CHECK( ! f1.valid() );
- BOOST_CHECK( f2.valid() );
- // move assignment
- f1 = std::move( f2);
- BOOST_CHECK( f1.valid() );
- BOOST_CHECK( ! f2.valid() );
- }
- void test_shared_future_move_ref() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< int& > p1;
- boost::fibers::shared_future< int& > f1 = p1.get_future().share();
- BOOST_CHECK( f1.valid() );
- // move construction
- boost::fibers::shared_future< int& > f2( std::move( f1) );
- BOOST_CHECK( ! f1.valid() );
- BOOST_CHECK( f2.valid() );
- // move assignment
- f1 = std::move( f2);
- BOOST_CHECK( f1.valid() );
- BOOST_CHECK( ! f2.valid() );
- }
- void test_shared_future_move_void() {
- // future retrieved from promise is valid (if it is the first)
- boost::fibers::promise< void > p1;
- boost::fibers::shared_future< void > f1 = p1.get_future().share();
- BOOST_CHECK( f1.valid() );
- // move construction
- boost::fibers::shared_future< void > f2( std::move( f1) );
- BOOST_CHECK( ! f1.valid() );
- BOOST_CHECK( f2.valid() );
- // move assignment
- f1 = std::move( f2);
- BOOST_CHECK( f1.valid() );
- BOOST_CHECK( ! f2.valid() );
- }
- boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
- boost::unit_test_framework::test_suite* test =
- BOOST_TEST_SUITE("Boost.Fiber: shared_future test suite");
- test->add(BOOST_TEST_CASE(test_shared_future_create));
- test->add(BOOST_TEST_CASE(test_shared_future_create_ref));
- test->add(BOOST_TEST_CASE(test_shared_future_create_void));
- test->add(BOOST_TEST_CASE(test_shared_future_move));
- test->add(BOOST_TEST_CASE(test_shared_future_move_move));
- test->add(BOOST_TEST_CASE(test_shared_future_move_ref));
- test->add(BOOST_TEST_CASE(test_shared_future_move_void));
- test->add(BOOST_TEST_CASE(test_shared_future_get));
- test->add(BOOST_TEST_CASE(test_shared_future_get_move));
- test->add(BOOST_TEST_CASE(test_shared_future_get_ref));
- test->add(BOOST_TEST_CASE(test_shared_future_get_void));
- test->add(BOOST_TEST_CASE(test_shared_future_wait));
- test->add(BOOST_TEST_CASE(test_shared_future_wait_ref));
- test->add(BOOST_TEST_CASE(test_shared_future_wait_void));
- test->add(BOOST_TEST_CASE(test_shared_future_wait_for));
- test->add(BOOST_TEST_CASE(test_shared_future_wait_for_ref));
- test->add(BOOST_TEST_CASE(test_shared_future_wait_for_void));
- test->add(BOOST_TEST_CASE(test_shared_future_wait_until));
- test->add(BOOST_TEST_CASE(test_shared_future_wait_until_ref));
- test->add(BOOST_TEST_CASE(test_shared_future_wait_until_void));
- test->add(BOOST_TEST_CASE(test_shared_future_wait_with_fiber_1));
- test->add(BOOST_TEST_CASE(test_shared_future_wait_with_fiber_2));
- return test;
- }
|