4e83359537
Signed-off-by: Daniela Engert <dani@ngrt.de>
1237 lines
34 KiB
C++
1237 lines
34 KiB
C++
// (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/thread/detail/log.hpp>
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
#ifdef BOOST_MSVC
|
|
# pragma warning(disable: 4267) // conversion from ... to ..., possible loss of data
|
|
#endif
|
|
|
|
#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)
|
|
{
|
|
BOOST_DETAIL_THREAD_LOG;
|
|
try {
|
|
boost::promise<int> pi2;
|
|
BOOST_DETAIL_THREAD_LOG;
|
|
boost::unique_future<int> 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<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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_LOG;
|
|
boost::lock_guard<boost::mutex> 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<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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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)
|
|
{
|
|
BOOST_DETAIL_THREAD_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());
|
|
}
|
|
}
|