2
0
mirror of https://github.com/boostorg/fiber.git synced 2026-02-20 14:42:21 +00:00
Files
fiber/libs/task/test/test_bounded_pool.cpp
Oliver Kowalke 39ec793737 initial checkin
2011-02-09 18:41:35 +01:00

510 lines
13 KiB
C++

// Copyright Oliver Kowalke 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <cstdlib>
#include <iostream>
#include <map>
#include <stdexcept>
#include <vector>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/function.hpp>
#include <boost/ref.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>
#include <boost/thread/barrier.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility.hpp>
#include <boost/task.hpp>
#include "test_functions.hpp"
namespace pt = boost::posix_time;
namespace tsk = boost::tasks;
// check size and move op
void test_case_1()
{
tsk::static_pool<
tsk::bounded_fifo
> pool1(
tsk::poolsize( 3),
tsk::high_watermark( 10),
tsk::low_watermark( 5) );
BOOST_CHECK( pool1);
BOOST_CHECK_EQUAL( pool1.size(), std::size_t( 3) );
BOOST_CHECK_EQUAL( pool1.upper_bound(), std::size_t( 10) );
BOOST_CHECK_EQUAL( pool1.lower_bound(), std::size_t( 5) );
tsk::static_pool<
tsk::bounded_fifo
> pool2;
BOOST_CHECK( ! pool2);
BOOST_CHECK_THROW( pool2.size(), tsk::pool_moved);
BOOST_CHECK_THROW( pool2.upper_bound(), tsk::pool_moved);
BOOST_CHECK_THROW( pool2.lower_bound(), tsk::pool_moved);
pool2 = boost::move( pool1);
BOOST_CHECK( ! pool1);
BOOST_CHECK_THROW( pool1.size(), tsk::pool_moved);
BOOST_CHECK_THROW( pool1.upper_bound(), tsk::pool_moved);
BOOST_CHECK_THROW( pool1.lower_bound(), tsk::pool_moved);
BOOST_CHECK( pool2);
BOOST_CHECK_EQUAL( pool2.size(), std::size_t( 3) );
BOOST_CHECK_EQUAL( pool2.upper_bound(), std::size_t( 10) );
BOOST_CHECK_EQUAL( pool2.lower_bound(), std::size_t( 5) );
tsk::task< int > t( fibonacci_fn, 10);
tsk::handle< int > h(
tsk::async( boost::move( t), pool2) );
BOOST_CHECK_EQUAL( h.get(), 55);
}
// check submit
void test_case_2()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 1),
tsk::high_watermark( 10),
tsk::low_watermark( 10) );
tsk::task< int > t( fibonacci_fn, 10);
tsk::handle< int > h(
tsk::async( boost::move( t), pool) );
BOOST_CHECK_EQUAL( h.get(), 55);
}
// check assignment
void test_case_3()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 5),
tsk::high_watermark( 10),
tsk::low_watermark( 10) );
tsk::task< int > t( fibonacci_fn, 10);
tsk::handle< int > h1;
tsk::handle< int > h2(
tsk::async( boost::move( t), pool) );
h1 = h2;
BOOST_CHECK_EQUAL( h1.get(), 55);
BOOST_CHECK_EQUAL( h2.get(), 55);
}
// check swap
void test_case_4()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 5),
tsk::high_watermark( 10),
tsk::low_watermark( 10) );
tsk::task< int > t1( fibonacci_fn, 5);
tsk::task< int > t2( fibonacci_fn, 10);
tsk::handle< int > h1(
tsk::async( boost::move( t1), pool) );
tsk::handle< int > h2(
tsk::async( boost::move( t2), pool) );
BOOST_CHECK_EQUAL( h1.get(), 5);
BOOST_CHECK_EQUAL( h2.get(), 55);
BOOST_CHECK_NO_THROW( h1.swap( h2) );
BOOST_CHECK_EQUAL( h1.get(), 55);
BOOST_CHECK_EQUAL( h2.get(), 5);
}
// check runs in pool
void test_case_5()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 1),
tsk::high_watermark( 10),
tsk::low_watermark( 10) );
tsk::task< bool > t( runs_in_pool_fn);
tsk::handle< bool > h(
tsk::async( boost::move( t), pool) );
BOOST_CHECK_EQUAL( h.get(), true);
}
// check shutdown
void test_case_6()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 1),
tsk::high_watermark( 10),
tsk::low_watermark( 10) );
tsk::task< int > t( fibonacci_fn, 10);
tsk::handle< int > h(
tsk::async( boost::move( t), pool) );
pool.shutdown();
BOOST_CHECK( pool.closed() );
BOOST_CHECK_EQUAL( h.get(), 55);
}
// check runtime_error throw inside task
void test_case_7()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 1),
tsk::high_watermark( 10),
tsk::low_watermark( 10) );
tsk::task< void > t( throwing_fn);
tsk::handle< void > h(
tsk::async( boost::move( t), pool) );
pool.shutdown();
BOOST_CHECK_THROW( h.get(), std::runtime_error);
}
// check shutdown with task_rejected exception
void test_case_8()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 1),
tsk::high_watermark( 10),
tsk::low_watermark( 10) );
tsk::task< int > t( fibonacci_fn, 10);
pool.shutdown();
BOOST_CHECK( pool.closed() );
BOOST_CHECK_THROW(
tsk::async( boost::move( t), pool),
tsk::task_rejected);
}
// check shutdown_now with thread_interrupted exception
void test_case_9()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 1),
tsk::high_watermark( 1),
tsk::low_watermark( 1) );
tsk::task< void > t( delay_fn, pt::millisec( 500) );
tsk::handle< void > h(
tsk::async( boost::move( t), pool) );
boost::this_thread::sleep( pt::millisec( 250) );
BOOST_CHECK_EQUAL( pool.size(), std::size_t( 1) );
pool.shutdown_now();
BOOST_CHECK( pool.closed() );
BOOST_CHECK_EQUAL( pool.size(), std::size_t( 0) );
BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
}
// check wait
void test_case_10()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 5),
tsk::high_watermark( 1),
tsk::low_watermark( 1) );
tsk::task< int > t( fibonacci_fn, 10);
tsk::handle< int > h(
tsk::async( boost::move( t), pool) );
h.wait();
BOOST_CHECK( h.is_ready() );
BOOST_CHECK( h.has_value() );
BOOST_CHECK( ! h.has_exception() );
BOOST_CHECK_EQUAL( h.get(), 55);
}
// check wait_for
void test_case_11()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 5),
tsk::high_watermark( 1),
tsk::low_watermark( 1) );
tsk::task< void > t( delay_fn, pt::seconds( 1) );
tsk::handle< void > h(
tsk::async( boost::move( t), pool) );
BOOST_CHECK( h.wait_for( pt::seconds( 3) ) );
BOOST_CHECK( h.is_ready() );
BOOST_CHECK( h.has_value() );
BOOST_CHECK( ! h.has_exception() );
}
// check wait_for
void test_case_12()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 5),
tsk::high_watermark( 1),
tsk::low_watermark( 1) );
tsk::task< void > t( delay_fn, pt::seconds( 3) );
tsk::handle< void > h(
tsk::async( boost::move( t), pool) );
BOOST_CHECK( ! h.wait_for( pt::seconds( 1) ) );
BOOST_CHECK( ! h.is_ready() );
BOOST_CHECK( ! h.has_value() );
BOOST_CHECK( ! h.has_exception() );
}
// check wait_for
void test_case_13()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 5),
tsk::high_watermark( 1),
tsk::low_watermark( 1) );
tsk::task< void > t( delay_fn, pt::seconds( 1) );
tsk::handle< void > h(
tsk::async( boost::move( t), pool) );
BOOST_CHECK( h.wait_until( boost::get_system_time() + pt::seconds( 3) ) );
BOOST_CHECK( h.is_ready() );
BOOST_CHECK( h.has_value() );
BOOST_CHECK( ! h.has_exception() );
}
// check wait_for
void test_case_14()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 5),
tsk::high_watermark( 1),
tsk::low_watermark( 1) );
tsk::task< void > t( delay_fn, pt::seconds( 3) );
tsk::handle< void > h(
tsk::async( boost::move( t), pool) );
BOOST_CHECK( ! h.wait_until( boost::get_system_time() + pt::seconds( 1) ) );
BOOST_CHECK( ! h.is_ready() );
BOOST_CHECK( ! h.has_value() );
BOOST_CHECK( ! h.has_exception() );
}
// check interrupt
void test_case_15()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 5),
tsk::high_watermark( 10),
tsk::low_watermark( 10) );
tsk::task< void > t( delay_fn, pt::seconds( 3) );
tsk::handle< void > h(
tsk::async( boost::move( t), pool) );
h.interrupt();
BOOST_CHECK( h.interruption_requested() );
BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
}
// check interrupt_all_worker
void test_case_16()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 5),
tsk::high_watermark( 10),
tsk::low_watermark( 10) );
tsk::task< void > t1( delay_fn, pt::seconds( 3) );
tsk::task< void > t2( delay_fn, pt::seconds( 3) );
tsk::task< void > t3( delay_fn, pt::seconds( 3) );
tsk::handle< void > h1(
tsk::async( boost::move( t1), pool) );
tsk::handle< void > h2(
tsk::async( boost::move( t2), pool) );
tsk::handle< void > h3(
tsk::async( boost::move( t3), pool) );
boost::this_thread::sleep( pt::millisec( 250) );
pool.interrupt_all_worker();
BOOST_CHECK( ! h1.interruption_requested() );
BOOST_CHECK( ! h2.interruption_requested() );
BOOST_CHECK( ! h3.interruption_requested() );
BOOST_CHECK_THROW( h1.get(), tsk::task_interrupted);
BOOST_CHECK_THROW( h2.get(), tsk::task_interrupted);
BOOST_CHECK_THROW( h3.get(), tsk::task_interrupted);
BOOST_CHECK_EQUAL( pool.size(), std::size_t( 5) );
}
// check interrupt_and_wait
void test_case_17()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 5),
tsk::high_watermark( 10),
tsk::low_watermark( 10) );
bool finished( false);
tsk::task< void > t( interrupt_fn, pt::seconds( 1), boost::ref( finished) );
tsk::handle< void > h(
tsk::async( boost::move( t), pool) );
h.interrupt_and_wait();
BOOST_CHECK( finished);
BOOST_CHECK( h.is_ready() );
BOOST_CHECK( ! h.has_value() );
BOOST_CHECK( h.has_exception() );
BOOST_CHECK( h.interruption_requested() );
BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
}
// check interrupt_and_wait_for
void test_case_18()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 5),
tsk::high_watermark( 10),
tsk::low_watermark( 10) );
bool finished( false);
tsk::task< void > t( interrupt_fn, pt::seconds( 1), boost::ref( finished) );
tsk::handle< void > h(
tsk::async( boost::move( t), pool) );
BOOST_CHECK( h.interrupt_and_wait_for( pt::seconds( 3) ) );
BOOST_CHECK( finished);
BOOST_CHECK( h.is_ready() );
BOOST_CHECK( ! h.has_value() );
BOOST_CHECK( h.has_exception() );
BOOST_CHECK( h.interruption_requested() );
BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
}
// check interrupt_and_wait_for
void test_case_19()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 5),
tsk::high_watermark( 10),
tsk::low_watermark( 10) );
tsk::task< void > t( non_interrupt_fn, 3);
tsk::handle< void > h(
tsk::async( boost::move( t), pool) );
BOOST_CHECK( ! h.interrupt_and_wait_for( pt::seconds( 1) ) );
}
// check interrupt_and_wait_until
void test_case_20()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 5),
tsk::high_watermark( 10),
tsk::low_watermark( 10) );
bool finished( false);
tsk::task< void > t(
interrupt_fn,
pt::seconds( 1),
boost::ref( finished) );
tsk::handle< void > h(
tsk::async( boost::move( t), pool) );
BOOST_CHECK( h.interrupt_and_wait_until( boost::get_system_time() + pt::seconds( 3) ) );
BOOST_CHECK( finished);
BOOST_CHECK( h.is_ready() );
BOOST_CHECK( ! h.has_value() );
BOOST_CHECK( h.has_exception() );
BOOST_CHECK( h.interruption_requested() );
BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
}
// check interrupt_and_wait_until
void test_case_21()
{
tsk::static_pool<
tsk::bounded_fifo
> pool(
tsk::poolsize( 5),
tsk::high_watermark( 10),
tsk::low_watermark( 10) );
tsk::task< void > t( non_interrupt_fn, 3);
tsk::handle< void > h(
tsk::async( boost::move( t), pool) );
BOOST_CHECK( ! h.interrupt_and_wait_until( boost::get_system_time() + pt::seconds( 1) ) );
}
// check fifo scheduling
void test_case_22()
{
typedef tsk::static_pool<
tsk::bounded_fifo
> pool_type;
BOOST_CHECK( ! tsk::has_attribute< pool_type >::value);
pool_type pool(
tsk::poolsize( 1),
tsk::high_watermark( 10),
tsk::low_watermark( 10) );
boost::barrier b( 2);
std::vector< int > buffer;
tsk::task< void > t1( barrier_fn, boost::ref( b) );
tsk::task< void > t2(
buffer_fibonacci_fn,
boost::ref( buffer),
10);
tsk::task< void > t3(
buffer_fibonacci_fn,
boost::ref( buffer),
0);
tsk::async( boost::move( t1), pool);
boost::this_thread::sleep( pt::millisec( 250) );
tsk::async( boost::move( t2), pool);
tsk::async( boost::move( t3), pool);
b.wait();
pool.shutdown();
BOOST_CHECK_EQUAL( buffer[0], 55);
BOOST_CHECK_EQUAL( buffer[1], 0);
BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
}
boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
{
boost::unit_test::test_suite * test =
BOOST_TEST_SUITE("Boost.Task: bounded-pool test suite");
test->add( BOOST_TEST_CASE( & test_case_1) );
test->add( BOOST_TEST_CASE( & test_case_2) );
test->add( BOOST_TEST_CASE( & test_case_3) );
test->add( BOOST_TEST_CASE( & test_case_4) );
test->add( BOOST_TEST_CASE( & test_case_5) );
test->add( BOOST_TEST_CASE( & test_case_6) );
test->add( BOOST_TEST_CASE( & test_case_7) );
test->add( BOOST_TEST_CASE( & test_case_8) );
test->add( BOOST_TEST_CASE( & test_case_9) );
test->add( BOOST_TEST_CASE( & test_case_10) );
test->add( BOOST_TEST_CASE( & test_case_11) );
test->add( BOOST_TEST_CASE( & test_case_12) );
test->add( BOOST_TEST_CASE( & test_case_13) );
test->add( BOOST_TEST_CASE( & test_case_14) );
test->add( BOOST_TEST_CASE( & test_case_15) );
test->add( BOOST_TEST_CASE( & test_case_16) );
test->add( BOOST_TEST_CASE( & test_case_17) );
test->add( BOOST_TEST_CASE( & test_case_18) );
test->add( BOOST_TEST_CASE( & test_case_19) );
test->add( BOOST_TEST_CASE( & test_case_20) );
test->add( BOOST_TEST_CASE( & test_case_21) );
test->add( BOOST_TEST_CASE( & test_case_22) );
return test;
}