| // (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 <boost/thread/thread_only.hpp> |
| #include <boost/thread/mutex.hpp> |
| #include <boost/thread/condition.hpp> |
| #include <boost/thread/future.hpp> |
| #include <utility> |
| #include <memory> |
| #include <string> |
| #include <iostream> |
| |
| #include <boost/test/unit_test.hpp> |
| |
| #define LOG \ |
| if (false) {} else std::cout << std::endl << __FILE__ << "[" << __LINE__ << "]" |
| |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
| template<typename T> |
| typename boost::remove_reference<T>::type&& cast_to_rval(T&& t) |
| { |
| return static_cast<typename boost::remove_reference<T>::type&&>(t); |
| } |
| #else |
| #if defined BOOST_THREAD_USES_MOVE |
| template<typename T> |
| boost::rv<T>& cast_to_rval(T& t) |
| { |
| return boost::move(t); |
| } |
| #else |
| template<typename T> |
| boost::detail::thread_move_t<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<int>* p) |
| { |
| p->set_value(42); |
| } |
| |
| struct my_exception |
| {}; |
| |
| void set_promise_exception_thread(boost::promise<int>* p) |
| { |
| p->set_exception(boost::copy_exception(my_exception())); |
| } |
| |
| |
| BOOST_AUTO_TEST_CASE(test_store_value_from_thread) |
| { |
| LOG; |
| try { |
| boost::promise<int> pi2; |
| LOG; |
| boost::unique_future<int> fi2(BOOST_THREAD_MAKE_RV_REF(pi2.get_future())); |
| LOG; |
| boost::thread(set_promise_thread,&pi2); |
| LOG; |
| int j=fi2.get(); |
| LOG; |
| BOOST_CHECK(j==42); |
| LOG; |
| BOOST_CHECK(fi2.is_ready()); |
| LOG; |
| BOOST_CHECK(fi2.has_value()); |
| LOG; |
| BOOST_CHECK(!fi2.has_exception()); |
| LOG; |
| BOOST_CHECK(fi2.get_state()==boost::future_state::ready); |
| LOG; |
| } |
| catch (...) |
| { |
| BOOST_CHECK(false&&"Exception thrown"); |
| } |
| } |
| |
| BOOST_AUTO_TEST_CASE(test_store_exception) |
| { |
| LOG; |
| boost::promise<int> pi3; |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::promise<int> pi; |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::promise<int> 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) |
| { |
| LOG; |
| boost::promise<int> pi; |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::promise<int> pi; |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| // boost::promise<int> pi; |
| // boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(throw_runtime_error); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::promise<void> p; |
| boost::unique_future<void> 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) |
| { |
| LOG; |
| boost::promise<int&> p; |
| boost::unique_future<int&> 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) |
| { |
| LOG; |
| boost::packaged_task<void> pt(do_nothing); |
| boost::unique_future<void> 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) |
| { |
| LOG; |
| boost::packaged_task<int&> pt(return_ref); |
| boost::unique_future<int&> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int); |
| boost::unique_future<int> fi=pt.get_future(); |
| |
| boost::shared_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int); |
| boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| |
| boost::shared_future<int> sf(::cast_to_rval(fi)); |
| boost::shared_future<int> sf2(sf); |
| boost::shared_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int); |
| boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| |
| boost::shared_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<void> pt(do_nothing); |
| boost::unique_future<void> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| |
| boost::shared_future<void> 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) |
| { |
| LOG; |
| boost::promise<int&> p; |
| boost::shared_future<int&> 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) |
| { |
| LOG; |
| boost::promise<int> pi; |
| boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); |
| |
| boost::promise<int> pi2(::cast_to_rval(pi)); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::promise<void> pi; |
| boost::unique_future<void> fi(BOOST_THREAD_MAKE_RV_REF(pi.get_future())); |
| |
| boost::promise<void> pi2(::cast_to_rval(pi)); |
| boost::unique_future<void> 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) |
| { |
| LOG; |
| boost::promise<X> pt; |
| boost::unique_future<X> 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) |
| { |
| LOG; |
| boost::promise<std::string> pt; |
| boost::unique_future<std::string> 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<std::string> 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<std::string> 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<int>& pi) |
| { |
| boost::lock_guard<boost::mutex> lk(callback_mutex); |
| ++callback_called; |
| try |
| { |
| pi.set_value(42); |
| } |
| catch(...) |
| { |
| } |
| } |
| |
| void do_nothing_callback(boost::promise<int>& /*pi*/) |
| { |
| boost::lock_guard<boost::mutex> lk(callback_mutex); |
| ++callback_called; |
| } |
| |
| BOOST_AUTO_TEST_CASE(test_wait_callback) |
| { |
| LOG; |
| callback_called=0; |
| boost::promise<int> pi; |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| callback_called=0; |
| boost::promise<int> pi; |
| boost::unique_future<int> 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<int>& pt) |
| { |
| LOG; |
| boost::lock_guard<boost::mutex> lk(callback_mutex); |
| ++callback_called; |
| try |
| { |
| pt(); |
| } |
| catch(...) |
| { |
| } |
| } |
| |
| |
| BOOST_AUTO_TEST_CASE(test_wait_callback_for_packaged_task) |
| { |
| LOG; |
| callback_called=0; |
| boost::packaged_task<int> pt(make_int); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int); |
| |
| boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| |
| BOOST_CHECK(!fi.is_ready()); |
| |
| boost::packaged_task<int> 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) |
| { |
| LOG; |
| boost::unique_future<int> f; |
| |
| { |
| boost::promise<int> 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) |
| { |
| LOG; |
| boost::unique_future<int> f; |
| |
| { |
| boost::packaged_task<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int_slowly); |
| boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| boost::packaged_task<int> pt2(make_int_slowly); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int_slowly); |
| boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| boost::packaged_task<int> pt2(make_int_slowly); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int_slowly); |
| boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| boost::packaged_task<int> pt2(make_int_slowly); |
| boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
| boost::packaged_task<int> pt3(make_int_slowly); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int_slowly); |
| boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| boost::packaged_task<int> pt2(make_int_slowly); |
| boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
| boost::packaged_task<int> pt3(make_int_slowly); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int_slowly); |
| boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| boost::packaged_task<int> pt2(make_int_slowly); |
| boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
| boost::packaged_task<int> pt3(make_int_slowly); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int_slowly); |
| boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| boost::packaged_task<int> pt2(make_int_slowly); |
| boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
| boost::packaged_task<int> pt3(make_int_slowly); |
| boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
| boost::packaged_task<int> pt4(make_int_slowly); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int_slowly); |
| boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| boost::packaged_task<int> pt2(make_int_slowly); |
| boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
| boost::packaged_task<int> pt3(make_int_slowly); |
| boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
| boost::packaged_task<int> pt4(make_int_slowly); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int_slowly); |
| boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| boost::packaged_task<int> pt2(make_int_slowly); |
| boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
| boost::packaged_task<int> pt3(make_int_slowly); |
| boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
| boost::packaged_task<int> pt4(make_int_slowly); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int_slowly); |
| boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| boost::packaged_task<int> pt2(make_int_slowly); |
| boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
| boost::packaged_task<int> pt3(make_int_slowly); |
| boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
| boost::packaged_task<int> pt4(make_int_slowly); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int_slowly); |
| boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| boost::packaged_task<int> pt2(make_int_slowly); |
| boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
| boost::packaged_task<int> pt3(make_int_slowly); |
| boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
| boost::packaged_task<int> pt4(make_int_slowly); |
| boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); |
| boost::packaged_task<int> pt5(make_int_slowly); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int_slowly); |
| boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| boost::packaged_task<int> pt2(make_int_slowly); |
| boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
| boost::packaged_task<int> pt3(make_int_slowly); |
| boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
| boost::packaged_task<int> pt4(make_int_slowly); |
| boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); |
| boost::packaged_task<int> pt5(make_int_slowly); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int_slowly); |
| boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| boost::packaged_task<int> pt2(make_int_slowly); |
| boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
| boost::packaged_task<int> pt3(make_int_slowly); |
| boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
| boost::packaged_task<int> pt4(make_int_slowly); |
| boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); |
| boost::packaged_task<int> pt5(make_int_slowly); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int_slowly); |
| boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| boost::packaged_task<int> pt2(make_int_slowly); |
| boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
| boost::packaged_task<int> pt3(make_int_slowly); |
| boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
| boost::packaged_task<int> pt4(make_int_slowly); |
| boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); |
| boost::packaged_task<int> pt5(make_int_slowly); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| boost::packaged_task<int> pt(make_int_slowly); |
| boost::unique_future<int> f1(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| boost::packaged_task<int> pt2(make_int_slowly); |
| boost::unique_future<int> f2(BOOST_THREAD_MAKE_RV_REF(pt2.get_future())); |
| boost::packaged_task<int> pt3(make_int_slowly); |
| boost::unique_future<int> f3(BOOST_THREAD_MAKE_RV_REF(pt3.get_future())); |
| boost::packaged_task<int> pt4(make_int_slowly); |
| boost::unique_future<int> f4(BOOST_THREAD_MAKE_RV_REF(pt4.get_future())); |
| boost::packaged_task<int> pt5(make_int_slowly); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| callback_called=0; |
| boost::packaged_task<int> pt(make_int_slowly); |
| boost::unique_future<int> fi(BOOST_THREAD_MAKE_RV_REF(pt.get_future())); |
| boost::packaged_task<int> pt2(make_int_slowly); |
| boost::unique_future<int> 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) |
| { |
| LOG; |
| unsigned const count=10; |
| for(unsigned i=0;i<count;++i) |
| { |
| boost::packaged_task<int> tasks[count]; |
| boost::unique_future<int> futures[count]; |
| for(unsigned j=0;j<count;++j) |
| { |
| tasks[j]=boost::packaged_task<int>(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<int>* const future=boost::wait_for_any(futures,futures+count); |
| |
| BOOST_CHECK(future==(futures+i)); |
| for(unsigned j=0;j<count;++j) |
| { |
| if(j!=i) |
| { |
| BOOST_CHECK(!futures[j].is_ready()); |
| } |
| else |
| { |
| BOOST_CHECK(futures[j].is_ready()); |
| } |
| } |
| BOOST_CHECK(futures[i].get()==42); |
| } |
| } |
| |
| BOOST_AUTO_TEST_CASE(test_wait_for_all_from_range) |
| { |
| LOG; |
| unsigned const count=10; |
| boost::unique_future<int> futures[count]; |
| for(unsigned j=0;j<count;++j) |
| { |
| boost::packaged_task<int> 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<count;++j) |
| { |
| BOOST_CHECK(futures[j].is_ready()); |
| } |
| } |
| |
| BOOST_AUTO_TEST_CASE(test_wait_for_all_two_futures) |
| { |
| LOG; |
| unsigned const count=2; |
| boost::unique_future<int> futures[count]; |
| for(unsigned j=0;j<count;++j) |
| { |
| boost::packaged_task<int> 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<count;++j) |
| { |
| BOOST_CHECK(futures[j].is_ready()); |
| } |
| } |
| |
| BOOST_AUTO_TEST_CASE(test_wait_for_all_three_futures) |
| { |
| LOG; |
| unsigned const count=3; |
| boost::unique_future<int> futures[count]; |
| for(unsigned j=0;j<count;++j) |
| { |
| boost::packaged_task<int> 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<count;++j) |
| { |
| BOOST_CHECK(futures[j].is_ready()); |
| } |
| } |
| |
| BOOST_AUTO_TEST_CASE(test_wait_for_all_four_futures) |
| { |
| LOG; |
| unsigned const count=4; |
| boost::unique_future<int> futures[count]; |
| for(unsigned j=0;j<count;++j) |
| { |
| boost::packaged_task<int> 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<count;++j) |
| { |
| BOOST_CHECK(futures[j].is_ready()); |
| } |
| } |
| |
| BOOST_AUTO_TEST_CASE(test_wait_for_all_five_futures) |
| { |
| LOG; |
| unsigned const count=5; |
| boost::unique_future<int> futures[count]; |
| for(unsigned j=0;j<count;++j) |
| { |
| boost::packaged_task<int> 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<count;++j) |
| { |
| BOOST_CHECK(futures[j].is_ready()); |
| } |
| } |