// (C) Copyright 2008-10 Anthony Williams // // 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) #define BOOST_THREAD_VERSION 2 #define BOOST_TEST_MODULE Boost.Threads: futures test suite #include #include #include #include #include #include #include #include #include #include #ifdef BOOST_MSVC # pragma warning(disable: 4267) // conversion from ... to ..., possible loss of data #endif #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template typename boost::remove_reference::type&& cast_to_rval(T&& t) { return static_cast::type&&>(t); } #else #if defined BOOST_THREAD_USES_MOVE template boost::rv& cast_to_rval(T& t) { return boost::move(t); } #else template boost::detail::thread_move_t cast_to_rval(T& t) { return boost::move(t); } #endif #endif struct X { public: int i; BOOST_THREAD_MOVABLE_ONLY(X) X(): i(42) {} X(BOOST_THREAD_RV_REF(X) other): i(BOOST_THREAD_RV(other).i) { BOOST_THREAD_RV(other).i=0; } X& operator=(BOOST_THREAD_RV_REF(X) other) { i=BOOST_THREAD_RV(other).i; BOOST_THREAD_RV(other).i=0; return *this; } ~X() {} }; namespace boost { BOOST_THREAD_DCL_MOVABLE(X) } int make_int() { return 42; } int throw_runtime_error() { throw std::runtime_error("42"); } void set_promise_thread(boost::promise* p) { p->set_value(42); } struct my_exception {}; void set_promise_exception_thread(boost::promise* p) { p->set_exception(boost::copy_exception(my_exception())); } BOOST_AUTO_TEST_CASE(test_store_value_from_thread) { BOOST_DETAIL_THREAD_LOG; try { boost::promise pi2; BOOST_DETAIL_THREAD_LOG; boost::unique_future fi2(BOOST_THREAD_MAKE_RV_REF(pi2.get_future())); BOOST_DETAIL_THREAD_LOG; boost::thread(set_promise_thread,&pi2); BOOST_DETAIL_THREAD_LOG; int j=fi2.get(); BOOST_DETAIL_THREAD_LOG; BOOST_CHECK(j==42); BOOST_DETAIL_THREAD_LOG; BOOST_CHECK(fi2.is_ready()); BOOST_DETAIL_THREAD_LOG; BOOST_CHECK(fi2.has_value()); BOOST_DETAIL_THREAD_LOG; BOOST_CHECK(!fi2.has_exception()); BOOST_DETAIL_THREAD_LOG; BOOST_CHECK(fi2.get_state()==boost::future_state::ready); BOOST_DETAIL_THREAD_LOG; } catch (...) { BOOST_CHECK(false&&"Exception thrown"); } } BOOST_AUTO_TEST_CASE(test_store_exception) { BOOST_DETAIL_THREAD_LOG; boost::promise pi3; boost::unique_future fi3(BOOST_THREAD_MAKE_RV_REF(pi3.get_future())); boost::thread(set_promise_exception_thread,&pi3); try { fi3.get(); BOOST_CHECK(false); } catch(my_exception) { BOOST_CHECK(true); } BOOST_CHECK(fi3.is_ready()); BOOST_CHECK(!fi3.has_value()); BOOST_CHECK(fi3.has_exception()); BOOST_CHECK(fi3.get_state()==boost::future_state::ready); } BOOST_AUTO_TEST_CASE(test_initial_state) { BOOST_DETAIL_THREAD_LOG; boost::unique_future fi; BOOST_CHECK(!fi.is_ready()); BOOST_CHECK(!fi.has_value()); BOOST_CHECK(!fi.has_exception()); BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); int i; try { i=fi.get(); (void)i; BOOST_CHECK(false); } catch(boost::future_uninitialized) { BOOST_CHECK(true); } } BOOST_AUTO_TEST_CASE(test_waiting_future) { BOOST_DETAIL_THREAD_LOG; boost::promise pi; boost::unique_future fi; fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); int i=0; BOOST_CHECK(!fi.is_ready()); BOOST_CHECK(!fi.has_value()); BOOST_CHECK(!fi.has_exception()); BOOST_CHECK(fi.get_state()==boost::future_state::waiting); BOOST_CHECK(i==0); } BOOST_AUTO_TEST_CASE(test_cannot_get_future_twice) { BOOST_DETAIL_THREAD_LOG; boost::promise pi; BOOST_THREAD_MAKE_RV_REF(pi.get_future()); try { pi.get_future(); BOOST_CHECK(false); } catch(boost::future_already_retrieved&) { BOOST_CHECK(true); } } BOOST_AUTO_TEST_CASE(test_set_value_updates_future_state) { BOOST_DETAIL_THREAD_LOG; boost::promise pi; boost::unique_future fi; fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); pi.set_value(42); BOOST_CHECK(fi.is_ready()); BOOST_CHECK(fi.has_value()); BOOST_CHECK(!fi.has_exception()); BOOST_CHECK(fi.get_state()==boost::future_state::ready); } BOOST_AUTO_TEST_CASE(test_set_value_can_be_retrieved) { BOOST_DETAIL_THREAD_LOG; boost::promise pi; boost::unique_future fi; fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); pi.set_value(42); int i=0; BOOST_CHECK(i=fi.get()); BOOST_CHECK(i==42); BOOST_CHECK(fi.is_ready()); BOOST_CHECK(fi.has_value()); BOOST_CHECK(!fi.has_exception()); BOOST_CHECK(fi.get_state()==boost::future_state::ready); } BOOST_AUTO_TEST_CASE(test_set_value_can_be_moved) { BOOST_DETAIL_THREAD_LOG; // boost::promise pi; // boost::unique_future fi; // fi=BOOST_THREAD_MAKE_RV_REF(pi.get_future()); // pi.set_value(42); // int i=0; // BOOST_CHECK(i=fi.get()); // BOOST_CHECK(i==42); // BOOST_CHECK(fi.is_ready()); // BOOST_CHECK(fi.has_value()); // BOOST_CHECK(!fi.has_exception()); // BOOST_CHECK(fi.get_state()==boost::future_state::ready); } BOOST_AUTO_TEST_CASE(test_future_from_packaged_task_is_waiting) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int); boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); int i=0; BOOST_CHECK(!fi.is_ready()); BOOST_CHECK(!fi.has_value()); BOOST_CHECK(!fi.has_exception()); BOOST_CHECK(fi.get_state()==boost::future_state::waiting); BOOST_CHECK(i==0); } BOOST_AUTO_TEST_CASE(test_invoking_a_packaged_task_populates_future) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int); boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); pt(); int i=0; BOOST_CHECK(fi.is_ready()); BOOST_CHECK(fi.has_value()); BOOST_CHECK(!fi.has_exception()); BOOST_CHECK(fi.get_state()==boost::future_state::ready); BOOST_CHECK(i=fi.get()); BOOST_CHECK(i==42); } BOOST_AUTO_TEST_CASE(test_invoking_a_packaged_task_twice_throws) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int); pt(); try { pt(); BOOST_CHECK(false); } catch(boost::task_already_started) { BOOST_CHECK(true); } } BOOST_AUTO_TEST_CASE(test_cannot_get_future_twice_from_task) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int); pt.get_future(); try { pt.get_future(); BOOST_CHECK(false); } catch(boost::future_already_retrieved) { BOOST_CHECK(true); } } BOOST_AUTO_TEST_CASE(test_task_stores_exception_if_function_throws) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(throw_runtime_error); boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); pt(); BOOST_CHECK(fi.is_ready()); BOOST_CHECK(!fi.has_value()); BOOST_CHECK(fi.has_exception()); BOOST_CHECK(fi.get_state()==boost::future_state::ready); try { fi.get(); BOOST_CHECK(false); } catch(std::exception&) { BOOST_CHECK(true); } catch(...) { BOOST_CHECK(!"Unknown exception thrown"); } } BOOST_AUTO_TEST_CASE(test_void_promise) { BOOST_DETAIL_THREAD_LOG; boost::promise p; boost::unique_future f(BOOST_THREAD_MAKE_RV_REF(p.get_future())); p.set_value(); BOOST_CHECK(f.is_ready()); BOOST_CHECK(f.has_value()); BOOST_CHECK(!f.has_exception()); BOOST_CHECK(f.get_state()==boost::future_state::ready); f.get(); } BOOST_AUTO_TEST_CASE(test_reference_promise) { BOOST_DETAIL_THREAD_LOG; boost::promise p; boost::unique_future f(BOOST_THREAD_MAKE_RV_REF(p.get_future())); int i=42; p.set_value(i); BOOST_CHECK(f.is_ready()); BOOST_CHECK(f.has_value()); BOOST_CHECK(!f.has_exception()); BOOST_CHECK(f.get_state()==boost::future_state::ready); BOOST_CHECK(&f.get()==&i); } void do_nothing() {} BOOST_AUTO_TEST_CASE(test_task_returning_void) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(do_nothing); boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); pt(); BOOST_CHECK(fi.is_ready()); BOOST_CHECK(fi.has_value()); BOOST_CHECK(!fi.has_exception()); BOOST_CHECK(fi.get_state()==boost::future_state::ready); } int global_ref_target=0; int& return_ref() { return global_ref_target; } BOOST_AUTO_TEST_CASE(test_task_returning_reference) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(return_ref); boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); pt(); BOOST_CHECK(fi.is_ready()); BOOST_CHECK(fi.has_value()); BOOST_CHECK(!fi.has_exception()); BOOST_CHECK(fi.get_state()==boost::future_state::ready); int& i=fi.get(); BOOST_CHECK(&i==&global_ref_target); } BOOST_AUTO_TEST_CASE(test_shared_future) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int); boost::unique_future fi=pt.get_future(); boost::shared_future sf(::cast_to_rval(fi)); BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); pt(); int i=0; BOOST_CHECK(sf.is_ready()); BOOST_CHECK(sf.has_value()); BOOST_CHECK(!sf.has_exception()); BOOST_CHECK(sf.get_state()==boost::future_state::ready); BOOST_CHECK(i=sf.get()); BOOST_CHECK(i==42); } BOOST_AUTO_TEST_CASE(test_copies_of_shared_future_become_ready_together) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int); boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::shared_future sf(::cast_to_rval(fi)); boost::shared_future sf2(sf); boost::shared_future sf3; sf3=sf; BOOST_CHECK(sf.get_state()==boost::future_state::waiting); BOOST_CHECK(sf2.get_state()==boost::future_state::waiting); BOOST_CHECK(sf3.get_state()==boost::future_state::waiting); pt(); int i=0; BOOST_CHECK(sf.is_ready()); BOOST_CHECK(sf.has_value()); BOOST_CHECK(!sf.has_exception()); BOOST_CHECK(sf.get_state()==boost::future_state::ready); BOOST_CHECK(i=sf.get()); BOOST_CHECK(i==42); i=0; BOOST_CHECK(sf2.is_ready()); BOOST_CHECK(sf2.has_value()); BOOST_CHECK(!sf2.has_exception()); BOOST_CHECK(sf2.get_state()==boost::future_state::ready); BOOST_CHECK(i=sf2.get()); BOOST_CHECK(i==42); i=0; BOOST_CHECK(sf3.is_ready()); BOOST_CHECK(sf3.has_value()); BOOST_CHECK(!sf3.has_exception()); BOOST_CHECK(sf3.get_state()==boost::future_state::ready); BOOST_CHECK(i=sf3.get()); BOOST_CHECK(i==42); } BOOST_AUTO_TEST_CASE(test_shared_future_can_be_move_assigned_from_unique_future) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int); boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::shared_future sf; sf=::cast_to_rval(fi); BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); BOOST_CHECK(!sf.is_ready()); BOOST_CHECK(!sf.has_value()); BOOST_CHECK(!sf.has_exception()); BOOST_CHECK(sf.get_state()==boost::future_state::waiting); } BOOST_AUTO_TEST_CASE(test_shared_future_void) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(do_nothing); boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::shared_future sf(::cast_to_rval(fi)); BOOST_CHECK(fi.get_state()==boost::future_state::uninitialized); pt(); BOOST_CHECK(sf.is_ready()); BOOST_CHECK(sf.has_value()); BOOST_CHECK(!sf.has_exception()); BOOST_CHECK(sf.get_state()==boost::future_state::ready); sf.get(); } BOOST_AUTO_TEST_CASE(test_shared_future_ref) { BOOST_DETAIL_THREAD_LOG; boost::promise p; boost::shared_future f(BOOST_THREAD_MAKE_RV_REF(p.get_future())); int i=42; p.set_value(i); BOOST_CHECK(f.is_ready()); BOOST_CHECK(f.has_value()); BOOST_CHECK(!f.has_exception()); BOOST_CHECK(f.get_state()==boost::future_state::ready); BOOST_CHECK(&f.get()==&i); } BOOST_AUTO_TEST_CASE(test_can_get_a_second_future_from_a_moved_promise) { BOOST_DETAIL_THREAD_LOG; boost::promise pi; boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); boost::promise pi2(::cast_to_rval(pi)); boost::unique_future fi2(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); pi2.set_value(3); BOOST_CHECK(fi.is_ready()); BOOST_CHECK(!fi2.is_ready()); BOOST_CHECK(fi.get()==3); pi.set_value(42); BOOST_CHECK(fi2.is_ready()); BOOST_CHECK(fi2.get()==42); } BOOST_AUTO_TEST_CASE(test_can_get_a_second_future_from_a_moved_void_promise) { BOOST_DETAIL_THREAD_LOG; boost::promise pi; boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); boost::promise pi2(::cast_to_rval(pi)); boost::unique_future fi2(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); pi2.set_value(); BOOST_CHECK(fi.is_ready()); BOOST_CHECK(!fi2.is_ready()); pi.set_value(); BOOST_CHECK(fi2.is_ready()); } BOOST_AUTO_TEST_CASE(test_unique_future_for_move_only_udt) { BOOST_DETAIL_THREAD_LOG; boost::promise pt; boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); pt.set_value(X()); X res(fi.get()); BOOST_CHECK(res.i==42); } BOOST_AUTO_TEST_CASE(test_unique_future_for_string) { BOOST_DETAIL_THREAD_LOG; boost::promise pt; boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); pt.set_value(std::string("hello")); std::string res(fi.get()); BOOST_CHECK(res=="hello"); boost::promise pt2; fi=BOOST_THREAD_MAKE_RV_REF(pt2.get_future()); std::string const s="goodbye"; pt2.set_value(s); res=fi.get(); BOOST_CHECK(res=="goodbye"); boost::promise pt3; fi=BOOST_THREAD_MAKE_RV_REF(pt3.get_future()); std::string s2="foo"; pt3.set_value(s2); res=fi.get(); BOOST_CHECK(res=="foo"); } boost::mutex callback_mutex; unsigned callback_called=0; void wait_callback(boost::promise& pi) { boost::lock_guard lk(callback_mutex); ++callback_called; try { pi.set_value(42); } catch(...) { } } void do_nothing_callback(boost::promise& /*pi*/) { boost::lock_guard lk(callback_mutex); ++callback_called; } BOOST_AUTO_TEST_CASE(test_wait_callback) { BOOST_DETAIL_THREAD_LOG; callback_called=0; boost::promise pi; boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); pi.set_wait_callback(wait_callback); fi.wait(); BOOST_CHECK(callback_called); BOOST_CHECK(fi.get()==42); fi.wait(); fi.wait(); BOOST_CHECK(callback_called==1); } BOOST_AUTO_TEST_CASE(test_wait_callback_with_timed_wait) { BOOST_DETAIL_THREAD_LOG; callback_called=0; boost::promise pi; boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); pi.set_wait_callback(do_nothing_callback); bool success=fi.timed_wait(boost::posix_time::milliseconds(10)); BOOST_CHECK(callback_called); BOOST_CHECK(!success); success=fi.timed_wait(boost::posix_time::milliseconds(10)); BOOST_CHECK(!success); success=fi.timed_wait(boost::posix_time::milliseconds(10)); BOOST_CHECK(!success); BOOST_CHECK(callback_called==3); pi.set_value(42); success=fi.timed_wait(boost::posix_time::milliseconds(10)); BOOST_CHECK(success); BOOST_CHECK(callback_called==3); BOOST_CHECK(fi.get()==42); BOOST_CHECK(callback_called==3); } void wait_callback_for_task(boost::packaged_task& pt) { BOOST_DETAIL_THREAD_LOG; boost::lock_guard lk(callback_mutex); ++callback_called; try { pt(); } catch(...) { } } BOOST_AUTO_TEST_CASE(test_wait_callback_for_packaged_task) { BOOST_DETAIL_THREAD_LOG; callback_called=0; boost::packaged_task pt(make_int); boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); pt.set_wait_callback(wait_callback_for_task); fi.wait(); BOOST_CHECK(callback_called); BOOST_CHECK(fi.get()==42); fi.wait(); fi.wait(); BOOST_CHECK(callback_called==1); } BOOST_AUTO_TEST_CASE(test_packaged_task_can_be_moved) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int); boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); BOOST_CHECK(!fi.is_ready()); boost::packaged_task pt2(::cast_to_rval(pt)); BOOST_CHECK(!fi.is_ready()); try { pt(); BOOST_CHECK(!"Can invoke moved task!"); } catch(boost::task_moved&) { } BOOST_CHECK(!fi.is_ready()); pt2(); BOOST_CHECK(fi.is_ready()); } BOOST_AUTO_TEST_CASE(test_destroying_a_promise_stores_broken_promise) { BOOST_DETAIL_THREAD_LOG; boost::unique_future f; { boost::promise p; f=BOOST_THREAD_MAKE_RV_REF(p.get_future()); } BOOST_CHECK(f.is_ready()); BOOST_CHECK(f.has_exception()); try { f.get(); } catch(boost::broken_promise&) { } } BOOST_AUTO_TEST_CASE(test_destroying_a_packaged_task_stores_broken_promise) { BOOST_DETAIL_THREAD_LOG; boost::unique_future f; { boost::packaged_task p(make_int); f=BOOST_THREAD_MAKE_RV_REF(p.get_future()); } BOOST_CHECK(f.is_ready()); BOOST_CHECK(f.has_exception()); try { f.get(); } catch(boost::broken_promise&) { } } int make_int_slowly() { boost::this_thread::sleep(boost::posix_time::seconds(1)); return 42; } BOOST_AUTO_TEST_CASE(test_wait_for_either_of_two_futures_1) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int_slowly); boost::unique_future f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::packaged_task pt2(make_int_slowly); boost::unique_future f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); boost::thread(::cast_to_rval(pt)); unsigned const future=boost::wait_for_any(f1,f2); BOOST_CHECK(future==0); BOOST_CHECK(f1.is_ready()); BOOST_CHECK(!f2.is_ready()); BOOST_CHECK(f1.get()==42); } BOOST_AUTO_TEST_CASE(test_wait_for_either_of_two_futures_2) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int_slowly); boost::unique_future f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::packaged_task pt2(make_int_slowly); boost::unique_future f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); boost::thread(::cast_to_rval(pt2)); unsigned const future=boost::wait_for_any(f1,f2); BOOST_CHECK(future==1); BOOST_CHECK(!f1.is_ready()); BOOST_CHECK(f2.is_ready()); BOOST_CHECK(f2.get()==42); } BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_1) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int_slowly); boost::unique_future f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::packaged_task pt2(make_int_slowly); boost::unique_future f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); boost::packaged_task pt3(make_int_slowly); boost::unique_future f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); boost::thread(::cast_to_rval(pt)); unsigned const future=boost::wait_for_any(f1,f2,f3); BOOST_CHECK(future==0); BOOST_CHECK(f1.is_ready()); BOOST_CHECK(!f2.is_ready()); BOOST_CHECK(!f3.is_ready()); BOOST_CHECK(f1.get()==42); } BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_2) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int_slowly); boost::unique_future f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::packaged_task pt2(make_int_slowly); boost::unique_future f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); boost::packaged_task pt3(make_int_slowly); boost::unique_future f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); boost::thread(::cast_to_rval(pt2)); unsigned const future=boost::wait_for_any(f1,f2,f3); BOOST_CHECK(future==1); BOOST_CHECK(!f1.is_ready()); BOOST_CHECK(f2.is_ready()); BOOST_CHECK(!f3.is_ready()); BOOST_CHECK(f2.get()==42); } BOOST_AUTO_TEST_CASE(test_wait_for_either_of_three_futures_3) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int_slowly); boost::unique_future f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::packaged_task pt2(make_int_slowly); boost::unique_future f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); boost::packaged_task pt3(make_int_slowly); boost::unique_future f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); boost::thread(::cast_to_rval(pt3)); unsigned const future=boost::wait_for_any(f1,f2,f3); BOOST_CHECK(future==2); BOOST_CHECK(!f1.is_ready()); BOOST_CHECK(!f2.is_ready()); BOOST_CHECK(f3.is_ready()); BOOST_CHECK(f3.get()==42); } BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_1) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int_slowly); boost::unique_future f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::packaged_task pt2(make_int_slowly); boost::unique_future f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); boost::packaged_task pt3(make_int_slowly); boost::unique_future f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); boost::packaged_task pt4(make_int_slowly); boost::unique_future f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); boost::thread(::cast_to_rval(pt)); unsigned const future=boost::wait_for_any(f1,f2,f3,f4); BOOST_CHECK(future==0); BOOST_CHECK(f1.is_ready()); BOOST_CHECK(!f2.is_ready()); BOOST_CHECK(!f3.is_ready()); BOOST_CHECK(!f4.is_ready()); BOOST_CHECK(f1.get()==42); } BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_2) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int_slowly); boost::unique_future f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::packaged_task pt2(make_int_slowly); boost::unique_future f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); boost::packaged_task pt3(make_int_slowly); boost::unique_future f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); boost::packaged_task pt4(make_int_slowly); boost::unique_future f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); boost::thread(::cast_to_rval(pt2)); unsigned const future=boost::wait_for_any(f1,f2,f3,f4); BOOST_CHECK(future==1); BOOST_CHECK(!f1.is_ready()); BOOST_CHECK(f2.is_ready()); BOOST_CHECK(!f3.is_ready()); BOOST_CHECK(!f4.is_ready()); BOOST_CHECK(f2.get()==42); } BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_3) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int_slowly); boost::unique_future f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::packaged_task pt2(make_int_slowly); boost::unique_future f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); boost::packaged_task pt3(make_int_slowly); boost::unique_future f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); boost::packaged_task pt4(make_int_slowly); boost::unique_future f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); boost::thread(::cast_to_rval(pt3)); unsigned const future=boost::wait_for_any(f1,f2,f3,f4); BOOST_CHECK(future==2); BOOST_CHECK(!f1.is_ready()); BOOST_CHECK(!f2.is_ready()); BOOST_CHECK(f3.is_ready()); BOOST_CHECK(!f4.is_ready()); BOOST_CHECK(f3.get()==42); } BOOST_AUTO_TEST_CASE(test_wait_for_either_of_four_futures_4) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int_slowly); boost::unique_future f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::packaged_task pt2(make_int_slowly); boost::unique_future f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); boost::packaged_task pt3(make_int_slowly); boost::unique_future f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); boost::packaged_task pt4(make_int_slowly); boost::unique_future f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); boost::thread(::cast_to_rval(pt4)); unsigned const future=boost::wait_for_any(f1,f2,f3,f4); BOOST_CHECK(future==3); BOOST_CHECK(!f1.is_ready()); BOOST_CHECK(!f2.is_ready()); BOOST_CHECK(!f3.is_ready()); BOOST_CHECK(f4.is_ready()); BOOST_CHECK(f4.get()==42); } BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_1) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int_slowly); boost::unique_future f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::packaged_task pt2(make_int_slowly); boost::unique_future f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); boost::packaged_task pt3(make_int_slowly); boost::unique_future f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); boost::packaged_task pt4(make_int_slowly); boost::unique_future f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); boost::packaged_task pt5(make_int_slowly); boost::unique_future f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); boost::thread(::cast_to_rval(pt)); unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5); BOOST_CHECK(future==0); BOOST_CHECK(f1.is_ready()); BOOST_CHECK(!f2.is_ready()); BOOST_CHECK(!f3.is_ready()); BOOST_CHECK(!f4.is_ready()); BOOST_CHECK(!f5.is_ready()); BOOST_CHECK(f1.get()==42); } BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_2) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int_slowly); boost::unique_future f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::packaged_task pt2(make_int_slowly); boost::unique_future f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); boost::packaged_task pt3(make_int_slowly); boost::unique_future f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); boost::packaged_task pt4(make_int_slowly); boost::unique_future f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); boost::packaged_task pt5(make_int_slowly); boost::unique_future f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); boost::thread(::cast_to_rval(pt2)); unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5); BOOST_CHECK(future==1); BOOST_CHECK(!f1.is_ready()); BOOST_CHECK(f2.is_ready()); BOOST_CHECK(!f3.is_ready()); BOOST_CHECK(!f4.is_ready()); BOOST_CHECK(!f5.is_ready()); BOOST_CHECK(f2.get()==42); } BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_3) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int_slowly); boost::unique_future f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::packaged_task pt2(make_int_slowly); boost::unique_future f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); boost::packaged_task pt3(make_int_slowly); boost::unique_future f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); boost::packaged_task pt4(make_int_slowly); boost::unique_future f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); boost::packaged_task pt5(make_int_slowly); boost::unique_future f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); boost::thread(::cast_to_rval(pt3)); unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5); BOOST_CHECK(future==2); BOOST_CHECK(!f1.is_ready()); BOOST_CHECK(!f2.is_ready()); BOOST_CHECK(f3.is_ready()); BOOST_CHECK(!f4.is_ready()); BOOST_CHECK(!f5.is_ready()); BOOST_CHECK(f3.get()==42); } BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_4) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int_slowly); boost::unique_future f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::packaged_task pt2(make_int_slowly); boost::unique_future f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); boost::packaged_task pt3(make_int_slowly); boost::unique_future f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); boost::packaged_task pt4(make_int_slowly); boost::unique_future f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); boost::packaged_task pt5(make_int_slowly); boost::unique_future f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); boost::thread(::cast_to_rval(pt4)); unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5); BOOST_CHECK(future==3); BOOST_CHECK(!f1.is_ready()); BOOST_CHECK(!f2.is_ready()); BOOST_CHECK(!f3.is_ready()); BOOST_CHECK(f4.is_ready()); BOOST_CHECK(!f5.is_ready()); BOOST_CHECK(f4.get()==42); } BOOST_AUTO_TEST_CASE(test_wait_for_either_of_five_futures_5) { BOOST_DETAIL_THREAD_LOG; boost::packaged_task pt(make_int_slowly); boost::unique_future f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::packaged_task pt2(make_int_slowly); boost::unique_future f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); boost::packaged_task pt3(make_int_slowly); boost::unique_future f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); boost::packaged_task pt4(make_int_slowly); boost::unique_future f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); boost::packaged_task pt5(make_int_slowly); boost::unique_future f5(BOOST_THREAD_MAKE_RV_REF(pt5.get_future())); boost::thread(::cast_to_rval(pt5)); unsigned const future=boost::wait_for_any(f1,f2,f3,f4,f5); BOOST_CHECK(future==4); BOOST_CHECK(!f1.is_ready()); BOOST_CHECK(!f2.is_ready()); BOOST_CHECK(!f3.is_ready()); BOOST_CHECK(!f4.is_ready()); BOOST_CHECK(f5.is_ready()); BOOST_CHECK(f5.get()==42); } BOOST_AUTO_TEST_CASE(test_wait_for_either_invokes_callbacks) { BOOST_DETAIL_THREAD_LOG; callback_called=0; boost::packaged_task pt(make_int_slowly); boost::unique_future fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); boost::packaged_task pt2(make_int_slowly); boost::unique_future fi2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); pt.set_wait_callback(wait_callback_for_task); boost::thread(::cast_to_rval(pt)); boost::wait_for_any(fi,fi2); BOOST_CHECK(callback_called==1); BOOST_CHECK(fi.get()==42); } BOOST_AUTO_TEST_CASE(test_wait_for_any_from_range) { BOOST_DETAIL_THREAD_LOG; unsigned const count=10; for(unsigned i=0;i tasks[count]; boost::unique_future futures[count]; for(unsigned j=0;j(make_int_slowly); futures[j]=BOOST_THREAD_MAKE_RV_REF(tasks[j].get_future()); } boost::thread(::cast_to_rval(tasks[i])); BOOST_CHECK(boost::wait_for_any(futures,futures)==futures); boost::unique_future* const future=boost::wait_for_any(futures,futures+count); BOOST_CHECK(future==(futures+i)); for(unsigned j=0;j futures[count]; for(unsigned j=0;j task(make_int_slowly); futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); boost::thread(::cast_to_rval(task)); } boost::wait_for_all(futures,futures+count); for(unsigned j=0;j futures[count]; for(unsigned j=0;j task(make_int_slowly); futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); boost::thread(::cast_to_rval(task)); } boost::wait_for_all(futures[0],futures[1]); for(unsigned j=0;j futures[count]; for(unsigned j=0;j task(make_int_slowly); futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); boost::thread(::cast_to_rval(task)); } boost::wait_for_all(futures[0],futures[1],futures[2]); for(unsigned j=0;j futures[count]; for(unsigned j=0;j task(make_int_slowly); futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); boost::thread(::cast_to_rval(task)); } boost::wait_for_all(futures[0],futures[1],futures[2],futures[3]); for(unsigned j=0;j futures[count]; for(unsigned j=0;j task(make_int_slowly); futures[j]=BOOST_THREAD_MAKE_RV_REF(task.get_future()); boost::thread(::cast_to_rval(task)); } boost::wait_for_all(futures[0],futures[1],futures[2],futures[3],futures[4]); for(unsigned j=0;j