Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r52634 - in sandbox/task: boost/task boost/task/detail libs/task/build libs/task/src libs/task/test
From: oliver.kowalke_at_[hidden]
Date: 2009-04-27 16:52:26


Author: olli
Date: 2009-04-27 16:52:25 EDT (Mon, 27 Apr 2009)
New Revision: 52634
URL: http://svn.boost.org/trac/boost/changeset/52634

Log:
* bugfix related to async_handle::interrupt_and_wait() and async_in_thread()
  (hung because condition-variable gets never notified)
* unit-test modified

Added:
   sandbox/task/libs/task/test/test_in_bounded_pool.cpp (contents, props changed)
   sandbox/task/libs/task/test/test_in_thread.cpp (contents, props changed)
   sandbox/task/libs/task/test/test_in_unbounded_pool.cpp (contents, props changed)
Text files modified:
   sandbox/task/boost/task/async.hpp | 12 ++--
   sandbox/task/boost/task/async_handle.hpp | 8 +-
   sandbox/task/boost/task/detail/interrupter.hpp | 2
   sandbox/task/boost/task/detail/thread_callable.hpp | 20 +++++--
   sandbox/task/boost/task/pool.hpp | 10 ---
   sandbox/task/libs/task/build/Jamfile.v2 | 46 +++++++++--------
   sandbox/task/libs/task/src/interrupter.cpp | 10 +++
   sandbox/task/libs/task/test/Jamfile.v2 | 6 +-
   sandbox/task/libs/task/test/test_functions.hpp | 11 ++++
   sandbox/task/libs/task/test/test_handle.cpp | 104 +++++++++++++++++++++++++++++++++------
   10 files changed, 163 insertions(+), 66 deletions(-)

Modified: sandbox/task/boost/task/async.hpp
==============================================================================
--- sandbox/task/boost/task/async.hpp (original)
+++ sandbox/task/boost/task/async.hpp 2009-04-27 16:52:25 EDT (Mon, 27 Apr 2009)
@@ -20,14 +20,14 @@
 namespace boost { namespace task
 {
 template< typename R >
-async_handle< R > async_pool( task< R > t)
+async_handle< R > async_in_pool( task< R > t)
 { return get_default_pool().submit( t); }
 
 template<
         typename R,
         typename Attr
>
-async_handle< R > async_pool(
+async_handle< R > async_in_pool(
         task< R > t,
         Attr const& attr)
 { return get_default_pool().submit( t, attr); }
@@ -36,7 +36,7 @@
         typename Channel,
         typename R
>
-async_handle< R > async_pool(
+async_handle< R > async_in_pool(
         pool< Channel > & pool,
         task< R > t)
 { return pool.submit( t); }
@@ -46,7 +46,7 @@
         typename R,
         typename Attr
>
-async_handle< R > async_pool(
+async_handle< R > async_in_pool(
         pool< Channel > & pool,
         task< R > t,
         Attr const& attr)
@@ -65,10 +65,10 @@
 }
 
 template< typename R >
-async_handle< R > async_thread( task< R > t)
+async_handle< R > async_in_thread( task< R > t)
 {
         detail::interrupter intr;
- detail::thread_callable ca( t);
+ detail::thread_callable ca( t, intr);
 
         shared_ptr< thread > thrd( new thread( ca), detail::joiner() );
         intr.set( thrd);

Modified: sandbox/task/boost/task/async_handle.hpp
==============================================================================
--- sandbox/task/boost/task/async_handle.hpp (original)
+++ sandbox/task/boost/task/async_handle.hpp 2009-04-27 16:52:25 EDT (Mon, 27 Apr 2009)
@@ -28,7 +28,7 @@
 class pool;
 
 template< typename R >
-async_handle< R > async_thread( task< R >);
+async_handle< R > async_in_thread( task< R >);
 
 template< typename R >
 class async_handle
@@ -37,7 +37,7 @@
         template< typename Channel >
         friend class pool;
         template< typename T >
- friend async_handle< T > async_thread( task< T >);
+ friend async_handle< T > async_in_thread( task< T >);
         template< typename Iterator >
         friend void waitfor_all( Iterator begin, Iterator end);
         template< typename T1, typename T2 >
@@ -103,6 +103,8 @@
                 { return fut_.get(); }
                 catch ( broken_promise const&)
                 { throw broken_task(); }
+ catch ( promise_already_satisfied const&)
+ { throw task_already_executed(); }
         }
 
         bool is_ready() const
@@ -139,7 +141,7 @@
         template< typename Channel >
         friend class pool;
         template< typename T >
- friend async_handle< T > async_thread( task< T >);
+ friend async_handle< T > async_in_thread( task< T >);
         template< typename Iterator >
         friend void waitfor_all( Iterator begin, Iterator end);
         template< typename T1, typename T2 >

Modified: sandbox/task/boost/task/detail/interrupter.hpp
==============================================================================
--- sandbox/task/boost/task/detail/interrupter.hpp (original)
+++ sandbox/task/boost/task/detail/interrupter.hpp 2009-04-27 16:52:25 EDT (Mon, 27 Apr 2009)
@@ -40,6 +40,8 @@
         public:
                 impl();
 
+ ~impl();
+
                 void set( shared_ptr< thread > const& thrd);
 
                 void reset();

Modified: sandbox/task/boost/task/detail/thread_callable.hpp
==============================================================================
--- sandbox/task/boost/task/detail/thread_callable.hpp (original)
+++ sandbox/task/boost/task/detail/thread_callable.hpp 2009-04-27 16:52:25 EDT (Mon, 27 Apr 2009)
@@ -35,23 +35,31 @@
         class impl_wrapper : public impl
         {
         private:
- task< R > t_;
+ task< R > t_;
+ interrupter i_;
 
         public:
- impl_wrapper( task< R > const& t)
- : t_( t)
+ impl_wrapper(
+ task< R > const& t,
+ interrupter const& i)
+ : t_( t), i_( i)
                 {}
 
                 void run()
- { t_(); }
+ {
+ t_();
+ i_.reset();
+ }
         };
 
         shared_ptr< impl > impl_;
 
 public:
         template< typename R >
- thread_callable( task< R > const& t)
- : impl_( new impl_wrapper< R >( t) )
+ thread_callable(
+ task< R > const& t,
+ interrupter const& i)
+ : impl_( new impl_wrapper< R >( t, i) )
         {}
 
         void operator()();

Modified: sandbox/task/boost/task/pool.hpp
==============================================================================
--- sandbox/task/boost/task/pool.hpp (original)
+++ sandbox/task/boost/task/pool.hpp 2009-04-27 16:52:25 EDT (Mon, 27 Apr 2009)
@@ -35,8 +35,6 @@
 
 namespace boost { namespace task
 {
-typedef detail::pool_callable pool_callable;
-
 template< typename Channel >
 class pool : private noncopyable
 {
@@ -244,10 +242,9 @@
                 lk.unlock();
         }
 
- const std::vector< pool_callable > shutdown_now()
+ const void shutdown_now()
         {
- if ( closed_() || close_() > 1)
- return std::vector< pool_callable >();
+ if ( closed_() || close_() > 1) return;
 
                 channel_.deactivate_now();
                 shared_lock< shared_mutex > lk( mtx_wg_);
@@ -255,9 +252,6 @@
                 wg_.interrupt_all();
                 wg_.join_all();
                 lk.unlock();
- std::vector< pool_callable > drain( channel_.drain() );
-
- return drain;
         }
 
         std::size_t size()

Modified: sandbox/task/libs/task/build/Jamfile.v2
==============================================================================
--- sandbox/task/libs/task/build/Jamfile.v2 (original)
+++ sandbox/task/libs/task/build/Jamfile.v2 2009-04-27 16:52:25 EDT (Mon, 27 Apr 2009)
@@ -30,34 +30,36 @@
 
 alias task_sources
     : ## win32 sources ##
- callable.cpp
- default_pool.cpp
- guard.cpp
- interrupter.cpp
- poolsize.cpp
- scanns.cpp
- semaphore_windows.cpp
- watermark.cpp
- worker.cpp
- worker_group.cpp
- wsq.cpp
+ default_pool.cpp
+ guard.cpp
+ interrupter.cpp
+ pool_callable.cpp
+ poolsize.cpp
+ scanns.cpp
+ semaphore_windows.cpp
+ thread_callable.cpp
+ watermark.cpp
+ worker.cpp
+ worker_group.cpp
+ wsq.cpp
     : ## requirements ##
       <taskapi>win32
     ;
 
 alias task_sources
     : ## posix sources ##
- callable.cpp
- default_pool.cpp
- guard.cpp
- interrupter.cpp
- poolsize.cpp
- scanns.cpp
- semaphore_posix.cpp
- watermark.cpp
- worker.cpp
- worker_group.cpp
- wsq.cpp
+ default_pool.cpp
+ guard.cpp
+ interrupter.cpp
+ pool_callable.cpp
+ poolsize.cpp
+ scanns.cpp
+ semaphore_posix.cpp
+ thread_callable.cpp
+ watermark.cpp
+ worker.cpp
+ worker_group.cpp
+ wsq.cpp
     : ## requirements ##
       <taskapi>posix
     ;

Modified: sandbox/task/libs/task/src/interrupter.cpp
==============================================================================
--- sandbox/task/libs/task/src/interrupter.cpp (original)
+++ sandbox/task/libs/task/src/interrupter.cpp 2009-04-27 16:52:25 EDT (Mon, 27 Apr 2009)
@@ -31,6 +31,9 @@
 thrd_()
 {}
 
+interrupter::impl::~impl()
+{ reset(); }
+
 void
 interrupter::impl::set( shared_ptr< thread > const& thrd)
 {
@@ -45,8 +48,11 @@
 interrupter::impl::reset()
 {
         unique_lock< mutex > lk( mtx_);
- BOOST_ASSERT( thrd_);
- thrd_.reset();
+// BOOST_ASSERT( thrd_);
+// try
+// { thrd_.reset(); }
+// catch (...)
+// { printf("exception\n"); }
         try
         { this_thread::interruption_point(); }
         catch ( thread_interrupted const&)

Modified: sandbox/task/libs/task/test/Jamfile.v2
==============================================================================
--- sandbox/task/libs/task/test/Jamfile.v2 (original)
+++ sandbox/task/libs/task/test/Jamfile.v2 2009-04-27 16:52:25 EDT (Mon, 27 Apr 2009)
@@ -28,7 +28,7 @@
 
 test-suite thread_pool :
     [ tp-test test_handle ]
- [ tp-test test_launch ]
- [ tp-test test_pool_unbounded_channel ]
- [ tp-test test_pool_bounded_channel ]
+ [ tp-test test_in_thread ]
+ [ tp-test test_in_unbounded_pool ]
+ [ tp-test test_in_bounded_pool ]
     ;

Modified: sandbox/task/libs/task/test/test_functions.hpp
==============================================================================
--- sandbox/task/libs/task/test/test_functions.hpp (original)
+++ sandbox/task/libs/task/test/test_functions.hpp 2009-04-27 16:52:25 EDT (Mon, 27 Apr 2009)
@@ -34,6 +34,17 @@
 void delay_fn( pt::time_duration const& td)
 { boost::this_thread::sleep( td); }
 
+void interrupt_fn( pt::time_duration const& td, bool & finished)
+{
+ try
+ { boost::this_thread::sleep( td); }
+ catch (...)
+ {
+ finished = true;
+ throw;
+ }
+}
+
 inline
 int fibonacci_fn( int n)
 {

Modified: sandbox/task/libs/task/test/test_handle.cpp
==============================================================================
--- sandbox/task/libs/task/test/test_handle.cpp (original)
+++ sandbox/task/libs/task/test/test_handle.cpp 2009-04-27 16:52:25 EDT (Mon, 27 Apr 2009)
@@ -29,33 +29,102 @@
 class test_handle
 {
 public:
- // test id
+ // check id
         void test_case_1()
         {
                 tsk::task< int > t(
                         tsk::make_task(
                                 fibonacci_fn,
                                 10) );
- tsk::handle< int > h( t.get_handle() );
- tsk::launch( t);
- BOOST_CHECK_EQUAL( t.get_id(), h.get_id() );
+ tsk::async_handle< int > h(
+ tsk::async_in_thread(
+ t) );
+ BOOST_CHECK_EQUAL( h.get_id(), t.get_id() );
                 BOOST_CHECK_EQUAL( h.get(), 55);
         }
 
- // test handle
+ // check waitfor_all()
         void test_case_2()
         {
- tsk::task< int > t(
- tsk::make_task(
- fibonacci_fn,
- 10) );
- tsk::handle< int > h1( t.get_handle() );
- tsk::handle< int > h2( t.get_handle() );
- tsk::launch( t);
- BOOST_CHECK_EQUAL( t.get_id(), h1.get_id() );
- BOOST_CHECK_EQUAL( t.get_id(), h2.get_id() );
- BOOST_CHECK_EQUAL( h1.get_id(), h2.get_id() );
- BOOST_CHECK_EQUAL( h1 == h2, true);
+ std::vector< tsk::async_handle< int > > vec;
+ for ( int i = 0; i <= 5; ++i)
+ vec.push_back(
+ tsk::async_in_pool(
+ tsk::make_task(
+ fibonacci_fn,
+ i) ) );
+ tsk::waitfor_all( vec.begin(), vec.end() );
+ BOOST_CHECK( vec[0].is_ready() );
+ BOOST_CHECK( vec[1].is_ready() );
+ BOOST_CHECK( vec[2].is_ready() );
+ BOOST_CHECK( vec[3].is_ready() );
+ BOOST_CHECK( vec[4].is_ready() );
+ BOOST_CHECK( vec[5].is_ready() );
+ BOOST_CHECK_EQUAL( vec[0].get(), 0);
+ BOOST_CHECK_EQUAL( vec[1].get(), 1);
+ BOOST_CHECK_EQUAL( vec[2].get(), 1);
+ BOOST_CHECK_EQUAL( vec[3].get(), 2);
+ BOOST_CHECK_EQUAL( vec[4].get(), 3);
+ BOOST_CHECK_EQUAL( vec[5].get(), 5);
+ }
+
+ // check waitfor_any()
+ void test_case_3()
+ {
+ tsk::async_handle< void > h1(
+ tsk::async_in_pool(
+ tsk::make_task(
+ delay_fn,
+ pt::seconds( 3) ) ) );
+ tsk::async_handle< int > h2(
+ tsk::async_in_pool(
+ tsk::make_task(
+ fibonacci_fn,
+ 10) ) );
+ tsk::waitfor_any( h1, h2);
+ BOOST_CHECK( ! h1.is_ready() );
+ BOOST_CHECK( h2.is_ready() );
+ BOOST_CHECK_EQUAL( h2.get(), 55);
+ }
+
+ // check interrupt
+ void test_case_4()
+ {
+ tsk::async_handle< void > h(
+ tsk::async_in_thread(
+ tsk::make_task(
+ delay_fn,
+ pt::seconds( 3) ) ) );
+ h.interrupt();
+ BOOST_CHECK( h.interruption_requested() );
+ bool thrown( false);
+ try
+ { h.get(); }
+ catch ( tsk::task_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check interruption
+ void test_case_5()
+ {
+ bool finished( false);
+ tsk::async_handle< void > h(
+ tsk::async_in_thread(
+ tsk::make_task(
+ interrupt_fn,
+ pt::seconds( 3),
+ boost::ref( finished) ) ) );
+ h.interrupt_and_wait();
+ BOOST_CHECK( finished);
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( h.interruption_requested() );
+ bool thrown( false);
+ try
+ { h.get(); }
+ catch ( tsk::task_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
         }
 };
 
@@ -66,6 +135,9 @@
         boost::shared_ptr< test_handle > instance( new test_handle() );
         test->add( BOOST_CLASS_TEST_CASE( & test_handle::test_case_1, instance) );
         test->add( BOOST_CLASS_TEST_CASE( & test_handle::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_handle::test_case_3, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_handle::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_handle::test_case_5, instance) );
 
         return test;
 }

Added: sandbox/task/libs/task/test/test_in_bounded_pool.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/test/test_in_bounded_pool.cpp 2009-04-27 16:52:25 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,437 @@
+
+// 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/utility.hpp>
+
+#include <boost/task.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tsk = boost::task;
+
+class test_in_bounded_pool
+{
+public:
+ // check size, active, idle
+ void test_case_1()
+ {
+ tsk::pool<
+ tsk::bounded_channel< tsk::fifo >
+ > pool(
+ tsk::poolsize( 3),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 3) );
+ BOOST_CHECK_EQUAL( pool.idle(), std::size_t( 3) );
+ BOOST_CHECK_EQUAL( pool.active(), std::size_t( 0) );
+ }
+
+ // check submit
+ void test_case_2()
+ {
+ tsk::pool<
+ tsk::bounded_channel< tsk::fifo >
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::async_handle< int > h(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ fibonacci_fn,
+ 10) ) );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check runs in pool
+ void test_case_3()
+ {
+ tsk::pool<
+ tsk::bounded_channel< tsk::fifo >
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::async_handle< bool > h(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ runs_in_pool_fn) ) );
+ BOOST_CHECK_EQUAL( h.get(), true);
+ }
+
+ // don't execute twice
+ void test_case_4()
+ {
+ tsk::pool<
+ tsk::bounded_channel< tsk::fifo >
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< int > t(
+ tsk::make_task(
+ fibonacci_fn,
+ 10) );
+ tsk::async_handle< int > h(
+ tsk::async_in_pool(
+ pool,
+ t) );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ tsk::async_in_pool(
+ pool,
+ t);
+ bool thrown( false);
+ try
+ { h.get(); }
+ catch ( tsk::task_already_executed const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown
+ void test_case_5()
+ {
+ tsk::pool<
+ tsk::bounded_channel< tsk::fifo >
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::async_handle< int > h(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ fibonacci_fn,
+ 10) ) );
+ pool.shutdown();
+ BOOST_CHECK( pool.closed() );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check runtime_error throw inside task
+ void test_case_6()
+ {
+ tsk::pool<
+ tsk::bounded_channel< tsk::fifo >
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::async_handle< void > h(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ throwing_fn) ) );
+ pool.shutdown();
+ bool thrown( false);
+ try
+ { h.get(); }
+ catch ( std::runtime_error const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown with task_rejected exception
+ void test_case_7()
+ {
+ tsk::pool<
+ tsk::bounded_channel< tsk::fifo >
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ pool.shutdown();
+ BOOST_CHECK( pool.closed() );
+ bool thrown( false);
+ try
+ {
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ }
+ catch ( tsk::task_rejected const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown_now with thread_interrupted exception
+ void test_case_8()
+ {
+ tsk::pool<
+ tsk::bounded_channel< tsk::fifo >
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 1),
+ tsk::low_watermark( 1) );
+ tsk::async_handle< void > h(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ delay_fn,
+ pt::millisec( 500) ) ) );
+ 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( 1) );
+ BOOST_CHECK_EQUAL( pool.idle(), std::size_t( 1) );
+ BOOST_CHECK_EQUAL( pool.active(), std::size_t( 0) );
+ bool thrown( false);
+ try
+ { h.get(); }
+ catch ( tsk::task_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check pending
+ void test_case_9()
+ {
+ typedef tsk::pool<
+ tsk::bounded_channel< tsk::fifo >
+ > pool_type;
+ pool_type pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ boost::barrier b( 2);
+ tsk::async_handle< void > h1(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ barrier_fn,
+ boost::ref( b) ) ) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ tsk::async_handle< int > h2(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ fibonacci_fn,
+ 10) ) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 1) );
+ tsk::async_handle< int > h3(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ fibonacci_fn,
+ 10) ) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 2) );
+ b.wait();
+ h1.get();
+ BOOST_CHECK_EQUAL( h2.get(), 55);
+ BOOST_CHECK_EQUAL( h3.get(), 55);
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ }
+
+ // check interruption
+ void test_case_10()
+ {
+ typedef tsk::pool<
+ tsk::bounded_channel< tsk::fifo >
+ > pool_type;
+ pool_type pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ boost::barrier b( 2);
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ barrier_fn,
+ boost::ref( b) ) );
+ std::vector< int > buffer;
+ tsk::async_handle< void > h(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10) ) );
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0) );
+ h.interrupt();
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 1) );
+ bool thrown( false);
+ try
+ { h.get(); }
+ catch ( tsk::task_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check fifo scheduling
+ void test_case_11()
+ {
+ typedef tsk::pool<
+ tsk::bounded_channel< tsk::fifo >
+ > pool_type;
+ pool_type pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ boost::barrier b( 2);
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ barrier_fn,
+ boost::ref( b) ) );
+ std::vector< int > buffer;
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10) );
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0) );
+ 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) );
+ }
+
+ // check priority scheduling
+ void test_case_12()
+ {
+ typedef tsk::pool<
+ tsk::bounded_channel< tsk::priority< int > >
+ > pool_type;
+ pool_type pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ boost::barrier b( 2);
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ barrier_fn,
+ boost::ref( b) ),
+ 0);
+ std::vector< int > buffer;
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10),
+ 1);
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0),
+ 0);
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer[1], 55);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
+ }
+
+ // check smart scheduling
+ void test_case_13()
+ {
+ typedef tsk::pool<
+ tsk::bounded_channel< tsk::smart< int, std::less< int >, tsk::replace_oldest, tsk::take_oldest > >
+ > pool_type;
+ pool_type pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ boost::barrier b( 2);
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ barrier_fn,
+ boost::ref( b) ),
+ 0);
+ std::vector< int > buffer;
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10),
+ 2);
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0),
+ 1);
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 1),
+ 2);
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer[1], 1);
+ 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: test suite") );
+
+ boost::shared_ptr< test_in_bounded_pool > instance( new test_in_bounded_pool() );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_bounded_pool::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_bounded_pool::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_bounded_pool::test_case_3, instance) );
+ //test->add( BOOST_CLASS_TEST_CASE( & test_in_bounded_pool::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_bounded_pool::test_case_5, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_bounded_pool::test_case_6, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_bounded_pool::test_case_7, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_bounded_pool::test_case_8, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_bounded_pool::test_case_9, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_bounded_pool::test_case_10, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_bounded_pool::test_case_11, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_bounded_pool::test_case_12, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_bounded_pool::test_case_13, instance) );
+
+ return test;
+}
+

Added: sandbox/task/libs/task/test/test_in_thread.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/test/test_in_thread.cpp 2009-04-27 16:52:25 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,118 @@
+
+// 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/utility.hpp>
+
+#include <boost/task.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tsk = boost::task;
+
+class test_in_thread
+{
+public:
+ // check submit
+ void test_case_1()
+ {
+ tsk::async_handle< int > h(
+ tsk::async_in_thread(
+ tsk::make_task(
+ fibonacci_fn,
+ 10) ) );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check runs not in pool
+ void test_case_2()
+ {
+ tsk::async_handle< bool > h(
+ tsk::async_in_thread(
+ tsk::make_task(
+ runs_in_pool_fn) ) );
+ BOOST_CHECK_EQUAL( h.get(), false);
+ }
+
+ // don't execute twice
+ void test_case_3()
+ {
+ tsk::task< int > t(
+ tsk::make_task(
+ fibonacci_fn,
+ 10) );
+ tsk::async_in_thread( t);
+ tsk::async_handle< int > h( tsk::async_in_thread( t) );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ bool thrown( false);
+ try
+ { h.get(); }
+ catch ( tsk::task_already_executed const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check runtime_error thrown inside the task
+ void test_case_4()
+ {
+ tsk::async_handle< void > h(
+ tsk::async_in_thread(
+ tsk::make_task(
+ throwing_fn) ) );
+ bool thrown( false);
+ try
+ { h.get(); }
+ catch ( std::runtime_error const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check interruptation
+ void test_case_5()
+ {
+ boost::barrier b( 2);
+ tsk::async_handle< void > h(
+ tsk::async_in_thread(
+ tsk::make_task(
+ barrier_fn,
+ boost::ref( b) ) ) );
+ h.interrupt();
+ b.wait();
+ bool thrown( false);
+ try
+ { h.get(); }
+ catch ( tsk::task_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+};
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test( BOOST_TEST_SUITE("Boost.Task: test suite") );
+
+ boost::shared_ptr< test_in_thread > instance( new test_in_thread() );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_thread::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_thread::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_thread::test_case_3, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_thread::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_thread::test_case_5, instance) );
+
+ return test;
+}

Added: sandbox/task/libs/task/test/test_in_unbounded_pool.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/test/test_in_unbounded_pool.cpp 2009-04-27 16:52:25 EDT (Mon, 27 Apr 2009)
@@ -0,0 +1,395 @@
+
+// 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/utility.hpp>
+
+#include <boost/task.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tsk = boost::task;
+
+class test_in_unbounded_pool
+{
+public:
+ // check size, active, idle
+ void test_case_1()
+ {
+ tsk::pool<
+ tsk::unbounded_channel< tsk::fifo >
+ > pool( tsk::poolsize( 3) );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 3) );
+ BOOST_CHECK_EQUAL( pool.idle(), std::size_t( 3) );
+ BOOST_CHECK_EQUAL( pool.active(), std::size_t( 0) );
+ }
+
+ // check submit
+ void test_case_2()
+ {
+ tsk::pool<
+ tsk::unbounded_channel< tsk::fifo >
+ > pool( tsk::poolsize( 1) );
+ tsk::async_handle< int > h(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ fibonacci_fn,
+ 10) ) );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check runs in pool
+ void test_case_3()
+ {
+ tsk::pool<
+ tsk::unbounded_channel< tsk::fifo >
+ > pool( tsk::poolsize( 1) );
+ tsk::async_handle< bool > h(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ runs_in_pool_fn) ) );
+ BOOST_CHECK_EQUAL( h.get(), true);
+ }
+
+ // don't execute twice
+ void test_case_4()
+ {
+ tsk::pool<
+ tsk::unbounded_channel< tsk::fifo >
+ > pool( tsk::poolsize( 1) );
+ tsk::task< int > t(
+ tsk::make_task(
+ fibonacci_fn,
+ 10) );
+ tsk::async_handle< int > h(
+ tsk::async_in_pool(
+ pool,
+ t) );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ tsk::async_in_pool(
+ pool,
+ t);
+ bool thrown( false);
+ try
+ { h.get(); }
+ catch ( tsk::task_already_executed const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown
+ void test_case_5()
+ {
+ tsk::pool<
+ tsk::unbounded_channel< tsk::fifo >
+ > pool( tsk::poolsize( 1) );
+ tsk::async_handle< int > h(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ fibonacci_fn,
+ 10) ) );
+ pool.shutdown();
+ BOOST_CHECK( pool.closed() );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check runtime_error throw inside task
+ void test_case_6()
+ {
+ tsk::pool<
+ tsk::unbounded_channel< tsk::fifo >
+ > pool( tsk::poolsize( 1) );
+ tsk::async_handle< void > h(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ throwing_fn) ) );
+ pool.shutdown();
+ bool thrown( false);
+ try
+ { h.get(); }
+ catch ( std::runtime_error const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown with task_rejected exception
+ void test_case_7()
+ {
+ tsk::pool<
+ tsk::unbounded_channel< tsk::fifo >
+ > pool( tsk::poolsize( 1) );
+ pool.shutdown();
+ BOOST_CHECK( pool.closed() );
+ bool thrown( false);
+ try
+ {
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ }
+ catch ( tsk::task_rejected const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown_now with thread_interrupted exception
+ void test_case_8()
+ {
+ tsk::pool<
+ tsk::unbounded_channel< tsk::fifo >
+ > pool( tsk::poolsize( 1) );
+ tsk::async_handle< void > h(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ delay_fn,
+ pt::millisec( 500) ) ) );
+ 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( 1) );
+ BOOST_CHECK_EQUAL( pool.idle(), std::size_t( 1) );
+ BOOST_CHECK_EQUAL( pool.active(), std::size_t( 0) );
+ bool thrown( false);
+ try
+ { h.get(); }
+ catch ( tsk::task_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check pending
+ void test_case_9()
+ {
+ typedef tsk::pool<
+ tsk::unbounded_channel< tsk::fifo >
+ > pool_type;
+ pool_type pool( tsk::poolsize( 1) );
+ boost::barrier b( 2);
+ tsk::async_handle< void > h1(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ barrier_fn,
+ boost::ref( b) ) ) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ tsk::async_handle< int > h2(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ fibonacci_fn,
+ 10) ) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 1) );
+ tsk::async_handle< int > h3(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ fibonacci_fn,
+ 10) ) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 2) );
+ b.wait();
+ h1.get();
+ BOOST_CHECK_EQUAL( h2.get(), 55);
+ BOOST_CHECK_EQUAL( h3.get(), 55);
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ }
+
+ // check interruptation
+ void test_case_10()
+ {
+ typedef tsk::pool<
+ tsk::unbounded_channel< tsk::fifo >
+ > pool_type;
+ pool_type pool( tsk::poolsize( 1) );
+ boost::barrier b( 2);
+ pool.submit(
+ tsk::make_task(
+ barrier_fn,
+ boost::ref( b) ) );
+ std::vector< int > buffer;
+ tsk::async_handle< void > h(
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10) ) );
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0) );
+ h.interrupt();
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 1) );
+ bool thrown( false);
+ try
+ { h.get(); }
+ catch ( tsk::task_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check fifo scheduling
+ void test_case_11()
+ {
+ typedef tsk::pool<
+ tsk::unbounded_channel< tsk::fifo >
+ > pool_type;
+ pool_type pool( tsk::poolsize( 1) );
+ boost::barrier b( 2);
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ barrier_fn,
+ boost::ref( b) ) );
+ std::vector< int > buffer;
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10) );
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0) );
+ 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) );
+ }
+
+ // check priority scheduling
+ void test_case_12()
+ {
+ typedef tsk::pool<
+ tsk::unbounded_channel< tsk::priority< int > >
+ > pool_type;
+ pool_type pool( tsk::poolsize( 1) );
+ boost::barrier b( 2);
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ barrier_fn,
+ boost::ref( b) ),
+ 0);
+ std::vector< int > buffer;
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10),
+ 1);
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0),
+ 0);
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer[1], 55);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
+ }
+
+ // check smart scheduling
+ void test_case_13()
+ {
+ typedef tsk::pool<
+ tsk::unbounded_channel< tsk::smart< int, std::less< int >, tsk::replace_oldest, tsk::take_oldest > >
+ > pool_type;
+ pool_type pool( tsk::poolsize( 1) );
+ boost::barrier b( 2);
+ pool.submit(
+ tsk::make_task(
+ barrier_fn,
+ boost::ref( b) ),
+ 0);
+ std::vector< int > buffer;
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10),
+ 2);
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0),
+ 1);
+ tsk::async_in_pool(
+ pool,
+ tsk::make_task(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 1),
+ 2);
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer[1], 1);
+ 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: test suite") );
+
+ boost::shared_ptr< test_in_unbounded_pool > instance( new test_in_unbounded_pool() );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_unbounded_pool::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_unbounded_pool::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_unbounded_pool::test_case_3, instance) );
+// test->add( BOOST_CLASS_TEST_CASE( & test_in_unbounded_pool::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_unbounded_pool::test_case_5, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_unbounded_pool::test_case_6, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_unbounded_pool::test_case_7, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_unbounded_pool::test_case_8, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_unbounded_pool::test_case_9, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_unbounded_pool::test_case_10, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_unbounded_pool::test_case_11, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_unbounded_pool::test_case_12, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_in_unbounded_pool::test_case_13, instance) );
+
+ return test;
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk