Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r51433 - in sandbox/threadpool: . boost boost/tp boost/tp/detail libs libs/tp libs/tp/build libs/tp/doc libs/tp/examples libs/tp/src libs/tp/test
From: oliver.kowalke_at_[hidden]
Date: 2009-02-24 14:04:22


Author: olli
Date: 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
New Revision: 51433
URL: http://svn.boost.org/trac/boost/changeset/51433

Log:
initial import
Added:
   sandbox/threadpool/
   sandbox/threadpool/boost/
   sandbox/threadpool/boost/tp/
   sandbox/threadpool/boost/tp/bounded_channel.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/detail/
   sandbox/threadpool/boost/tp/detail/bind_processor.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/detail/bind_processor_aix.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/detail/bind_processor_hpux.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/detail/bind_processor_irix.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/detail/bind_processor_linux.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/detail/bind_processor_solaris.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/detail/bind_processor_windows.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/detail/callable.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/detail/guard.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/detail/info.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/detail/interrupter.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/detail/wsq.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/exceptions.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/fifo.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/info.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/lifo.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/pool.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/poolsize.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/priority.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/scanns.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/smart.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/task.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/tp.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/unbounded_channel.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/watermark.hpp (contents, props changed)
   sandbox/threadpool/libs/
   sandbox/threadpool/libs/tp/
   sandbox/threadpool/libs/tp/build/
   sandbox/threadpool/libs/tp/doc/
   sandbox/threadpool/libs/tp/doc/Jamfile.v2 (contents, props changed)
   sandbox/threadpool/libs/tp/doc/channel.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/doc/exceptions_ref.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/doc/forkjoin.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/doc/introduction.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/doc/meta_ref.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/doc/pool.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/doc/pool_ref.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/doc/poolsize_ref.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/doc/reference.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/doc/scanns_ref.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/doc/scheduling.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/doc/stacksize_ref.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/doc/task.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/doc/task_ref.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/doc/threadpool.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/doc/threadpool.xml (contents, props changed)
   sandbox/threadpool/libs/tp/doc/watermark_ref.qbk (contents, props changed)
   sandbox/threadpool/libs/tp/examples/
   sandbox/threadpool/libs/tp/examples/Jamfile.v2 (contents, props changed)
   sandbox/threadpool/libs/tp/examples/fork_join.cpp (contents, props changed)
   sandbox/threadpool/libs/tp/examples/interrupt.cpp (contents, props changed)
   sandbox/threadpool/libs/tp/examples/pending.cpp (contents, props changed)
   sandbox/threadpool/libs/tp/examples/priority.cpp (contents, props changed)
   sandbox/threadpool/libs/tp/examples/shutdonw_now.cpp (contents, props changed)
   sandbox/threadpool/libs/tp/examples/smart.cpp (contents, props changed)
   sandbox/threadpool/libs/tp/examples/spread_over_hardware.cpp (contents, props changed)
   sandbox/threadpool/libs/tp/examples/submit.cpp (contents, props changed)
   sandbox/threadpool/libs/tp/src/
   sandbox/threadpool/libs/tp/test/
   sandbox/threadpool/libs/tp/test/Jamfile.v2 (contents, props changed)
   sandbox/threadpool/libs/tp/test/test_bounded_queue_fifo.cpp (contents, props changed)
   sandbox/threadpool/libs/tp/test/test_bounded_queue_lifo.cpp (contents, props changed)
   sandbox/threadpool/libs/tp/test/test_bounded_queue_priority.cpp (contents, props changed)
   sandbox/threadpool/libs/tp/test/test_bounded_queue_smart.cpp (contents, props changed)
   sandbox/threadpool/libs/tp/test/test_functions.hpp (contents, props changed)
   sandbox/threadpool/libs/tp/test/test_unbounded_queue_fifo.cpp (contents, props changed)
   sandbox/threadpool/libs/tp/test/test_unbounded_queue_lifo.cpp (contents, props changed)
   sandbox/threadpool/libs/tp/test/test_unbounded_queue_priority.cpp (contents, props changed)
   sandbox/threadpool/libs/tp/test/test_unbounded_queue_smart.cpp (contents, props changed)

Added: sandbox/threadpool/boost/tp/bounded_channel.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/bounded_channel.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,409 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_BOUNDED_CHANNEL_H
+#define BOOST_TP_BOUNDED_CHANNEL_H
+
+#include <cstddef>
+#include <vector>
+
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/function.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+
+#include <boost/tp/detail/callable.hpp>
+#include <boost/tp/detail/interrupter.hpp>
+#include <boost/tp/exceptions.hpp>
+#include <boost/tp/watermark.hpp>
+
+namespace boost { namespace tp
+{
+template< typename SchedulingPolicy >
+class bounded_channel
+{
+private:
+ typedef SchedulingPolicy scheduling_policy;
+ typedef typename scheduling_policy::template impl<
+ detail::callable
+ > queue;
+
+public:
+ typedef typename queue::item item;
+ typedef scheduling_policy scheduler_type;
+
+private:
+ enum channel_state
+ {
+ channel_active,
+ channel_deactive,
+ channel_deactive_now
+ };
+
+ channel_state state_;
+ queue queue_;
+ shared_mutex mtx_;
+ condition not_empty_cond_;
+ condition not_full_cond_;
+ std::size_t hwm_;
+ std::size_t lwm_;
+
+ bool active_() const
+ { return state_ == channel_active; }
+
+ bool deactive_() const
+ { return state_ == channel_deactive; }
+
+ bool deactive_now_() const
+ { return state_ == channel_deactive_now; }
+
+ void activate_()
+ { state_ = channel_active; }
+
+ void clear_()
+ {
+ BOOST_ASSERT( ! active_() );
+ queue_.clear();
+ BOOST_ASSERT( empty_() );
+ }
+
+ void deactivate_()
+ {
+ if ( active_() )
+ {
+ state_ = channel_deactive;
+ not_empty_cond_.notify_all();
+ }
+
+ BOOST_ASSERT( deactive_() );
+ }
+
+ void deactivate_now_()
+ {
+ if ( active_() )
+ {
+ state_ = channel_deactive_now;
+ not_empty_cond_.notify_all();
+ }
+
+ BOOST_ASSERT( deactive_now_() );
+ }
+
+ const std::vector< detail::callable > drain_()
+ {
+ BOOST_ASSERT( deactive_now_() );
+ std::vector< detail::callable > unprocessed;
+ unprocessed.reserve( queue_.size() );
+ BOOST_FOREACH( item itm, queue_)
+ { unprocessed.push_back( itm.ca() ); }
+ clear_();
+ BOOST_ASSERT( empty_() );
+ return unprocessed;
+ }
+
+ bool empty_() const
+ { return queue_.empty(); }
+
+ bool full_() const
+ { return size_() >= hwm_; }
+
+ std::size_t size_() const
+ { return queue_.size(); }
+
+ void upper_bound_( std::size_t hwm)
+ {
+ if ( lwm_ > hwm )
+ throw invalid_watermark("low watermark must be less than or equal to high watermark");
+ std::size_t tmp( hwm_);
+ hwm_ = hwm;
+ if ( hwm_ > tmp) not_full_cond_.notify_one();
+ }
+
+ void lower_bound_( std::size_t lwm)
+ {
+ if ( lwm > hwm_ )
+ throw invalid_watermark("low watermark must be less than or equal to high watermark");
+ std::size_t tmp( lwm_);
+ lwm_ = lwm;
+ if ( lwm_ > tmp) not_full_cond_.notify_one();
+ }
+
+ void put_(
+ item const& itm,
+ unique_lock< shared_mutex > & lk)
+ {
+ not_full_cond_.wait(
+ lk,
+ bind(
+ & bounded_channel::producers_activate_,
+ this) );
+ if ( ! active_() )
+ throw task_rejected("channel is not active");
+ queue_.push( itm);
+ not_empty_cond_.notify_one();
+ }
+
+ template< typename Duration >
+ void put_(
+ item const& itm,
+ Duration const& rel_time,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( ! not_full_cond_.timed_wait(
+ lk,
+ rel_time,
+ bind(
+ & bounded_channel::producers_activate_,
+ this) ) )
+ throw task_rejected("timed out");
+ if ( ! active_() )
+ throw task_rejected("channel is not active");
+ queue_.push( itm);
+ not_empty_cond_.notify_one();
+ }
+
+ bool take_(
+ detail::callable & ca,
+ detail::interrupter & intr,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ try
+ {
+ not_empty_cond_.wait(
+ lk,
+ bind(
+ & bounded_channel::consumers_activate_,
+ this) );
+ }
+ catch ( thread_interrupted const& e)
+ { return false; }
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ item itm( queue_.pop() );
+ ca = itm.ca();
+ intr = itm.intr();
+ if ( size_() <= lwm_)
+ {
+ if ( lwm_ == hwm_)
+ not_full_cond_.notify_one();
+ else
+ // more than one producer could be waiting
+ // for submiting an action object
+ not_full_cond_.notify_all();
+ }
+ return ! ca.empty();
+ }
+
+ template< typename Duration >
+ bool take_(
+ detail::callable & ca,
+ detail::interrupter & intr,
+ Duration const& rel_time,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ try
+ {
+ if ( ! not_empty_cond_.timed_wait(
+ lk,
+ rel_time,
+ bind(
+ & bounded_channel::consumers_activate_,
+ this) ) )
+ return false;
+ }
+ catch ( thread_interrupted const& e)
+ { return false; }
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ item itm( queue_.pop() );
+ ca = itm.ca();
+ intr = itm.intr();
+ if ( size_() <= lwm_)
+ {
+ if ( lwm_ == hwm_)
+ not_full_cond_.notify_one();
+ else
+ // more than one producer could be waiting
+ // for submiting an action object
+ not_full_cond_.notify_all();
+ }
+ return ! ca.empty();
+ }
+
+ bool try_take_(
+ detail::callable & ca,
+ detail::interrupter & intr)
+ {
+ if ( deactive_now_() || empty_() )
+ return false;
+ item itm( queue_.pop() );
+ ca = itm.ca();
+ intr = itm.intr();
+ if ( size_() <= lwm_)
+ {
+ if ( lwm_ == hwm_)
+ not_full_cond_.notify_one();
+ else
+ // more than one producer could be waiting
+ // for submiting an action object
+ not_full_cond_.notify_all();
+ }
+ return ! ca.empty();
+ }
+
+ bool producers_activate_() const
+ { return ! active_() || ! full_(); }
+
+ bool consumers_activate_() const
+ { return ! active_() || ! empty_(); }
+
+public:
+ bounded_channel(
+ high_watermark const& hwm,
+ low_watermark const& lwm)
+ :
+ state_( channel_active),
+ queue_(),
+ mtx_(),
+ not_empty_cond_(),
+ not_full_cond_(),
+ hwm_( hwm),
+ lwm_( lwm)
+ {
+ if ( lwm_ > hwm_ )
+ throw invalid_watermark("low watermark must be less than or equal to high watermark");
+ }
+
+ bool active()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return active_();
+ }
+
+ void activate()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ activate_();
+ }
+
+ void clear()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ clear_();
+ }
+
+ bool deactive()
+ { return ! active(); }
+
+ void deactivate()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ deactivate_();
+ }
+
+ void deactivate_now()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ deactivate_now_();
+ }
+
+ const std::vector< detail::callable > drain()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return drain_();
+ }
+
+ bool empty()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return empty_();
+ }
+
+ bool full()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return full_();
+ }
+
+ std::size_t upper_bound()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return hwm_;
+ }
+
+ void upper_bound( std::size_t hwm)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ upper_bound_( hwm);
+ }
+
+ std::size_t lower_bound()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return lwm_;
+ }
+
+ void lower_bound( std::size_t lwm)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ lower_bound_( lwm);
+ }
+
+ std::size_t size()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return size_();
+ }
+
+ void put( item const& itm)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( itm, lk);
+ }
+
+ template< typename Duration >
+ void put(
+ item const& itm,
+ Duration const& rel_time)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( itm, rel_time, lk);
+ }
+
+ bool take(
+ detail::callable & ca,
+ detail::interrupter & intr)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, intr, lk);
+ }
+
+ template< typename Duration >
+ bool take(
+ detail::callable & ca,
+ detail::interrupter & intr,
+ Duration const& rel_time)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, intr, rel_time, lk);
+ }
+
+ bool try_take(
+ detail::callable & ca,
+ detail::interrupter & intr)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return try_take_( ca, intr);
+ }
+};
+} }
+
+#endif // BOOST_TP_BOUNDED_CHANNEL_H

Added: sandbox/threadpool/boost/tp/detail/bind_processor.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/detail/bind_processor.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,30 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_THREAD_BIND_PROCESSOR_H
+#define BOOST_THREAD_BIND_PROCESSOR_H
+
+#include <boost/config.hpp>
+
+#define BOOST_THREAD_BIND_PROCESSOR_AFFINITY 1
+
+#if defined(linux) || defined(__linux) || defined(__linux__)
+#include <boost/tp/detail/bind_processor_linux.hpp>
+// #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+// #include <boost/tp/detail/bind_processor_bsd.hpp>
+#elif defined(sun) || defined(__sun)
+#include <boost/tp/detail/bind_processor_solaris.hpp>
+#elif defined(__sgi)
+#include <boost/tp/detail/bind_processor_irix.hpp>
+#elif defined(__IBMCPP__) || defined(_AIX)
+#include <boost/tp/detail/bind_processor_aix.hpp>
+#elif defined(__hpux)
+#include <boost/tp/detail/bind_processor_hpux.hpp>
+#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+#include <boost/tp/detail/bind_processor_windows.hpp>
+#else
+#undef BOOST_THREAD_BIND_PROCESSOR_AFFINITY
+#endif
+
+#endif // BOOST_THREAD_BIND_PROCESSOR_H

Added: sandbox/threadpool/boost/tp/detail/bind_processor_aix.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/detail/bind_processor_aix.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,45 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_DETAIL_BIND_PROCESSOR_AIX_H
+#define BOOST_TP_DETAIL_BIND_PROCESSOR_AIX_H
+
+extern "C"
+{
+#include <sys/processor.h>
+#include <sys/thread.h>
+}
+
+#include <boost/assert.hpp>
+#include <boost/thread.hpp>
+#include <boost/system/system_error.hpp>
+
+namespace boost { namespace this_thread
+{
+ inline
+ void bind_to_processor( unsigned int n)
+ {
+ BOOST_ASSERT( n >= 0);
+ BOOST_ASSERT( n < boost::thread::hardware_concurrency() );
+
+ if ( ::bindprocessor( BINDTHREAD, ::thread_self(), static_cast< cpu_t >( n) ) == -1)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno,
+ boost::system::system_category) );
+ }
+
+
+ inline
+ void bind_to_any_processor()
+ {
+ if ( ::bindprocessor( BINDTHREAD, ::thread_self(), PROCESSOR_CLASS_ANY) == -1)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno,
+ boost::system::system_category) );
+ }
+}}
+
+#endif // BOOST_TP_DETAIL_BIND_PROCESSOR_AIX_H

Added: sandbox/threadpool/boost/tp/detail/bind_processor_hpux.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/detail/bind_processor_hpux.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,57 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_DETAIL_BIND_PROCESSOR_HPUX_H
+#define BOOST_TP_DETAIL_BIND_PROCESSOR_HPUX_H
+
+extern "C"
+{
+#include <sys/pthread.h>
+}
+
+#include <boost/assert.hpp>
+#include <boost/thread.hpp>
+#include <boost/system/system_error.hpp>
+
+namespace boost { namespace this_thread
+{
+ inline
+ void bind_to_processor( unsigned int n)
+ {
+ BOOST_ASSERT( n >= 0);
+ BOOST_ASSERT( n < boost::thread::hardware_concurrency() );
+
+ ::pthread_spu_t spu;
+ int errno_(
+ ::pthread_processor_bind_np(
+ PTHREAD_BIND_FORCED_NP,
+ & spu,
+ static_cast< pthread_spu_t >( n),
+ PTHREAD_SELFTID_NP) );
+ if ( errno_ != 0)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno_,
+ boost::system::system_category) );
+ }
+
+ inline
+ void bind_to_any_processor()
+ {
+ ::pthread_spu_t spu;
+ int errno_(
+ ::pthread_processor_bind_np(
+ PTHREAD_BIND_FORCED_NP,
+ & spu,
+ PTHREAD_SPUFLOAT_NP,
+ PTHREAD_SELFTID_NP) );
+ if ( errno_ != 0)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno_,
+ boost::system::system_category) );
+ }
+}}
+
+#endif // BOOST_TP_DETAIL_BIND_PROCESSOR_HPUX_H

Added: sandbox/threadpool/boost/tp/detail/bind_processor_irix.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/detail/bind_processor_irix.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,36 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_DETAIL_BIND_PROCESSOR_IRIX_H
+#define BOOST_TP_DETAIL_BIND_PROCESSOR_IRIX_H
+
+extern "C"
+{
+#include <pthread.h>
+}
+
+#include <boost/assert.hpp>
+#include <boost/thread.hpp>
+#include <boost/system/system_error.hpp>
+
+namespace boost { namespace this_thread
+{
+ inline
+ void bind_to_processor( unsigned int n)
+ {
+ BOOST_ASSERT( n >= 0);
+ BOOST_ASSERT( n < boost::thread::hardware_concurrency() );
+
+ int errno_( ::pthread_setrunon_np( n) );
+ if ( errno_ != 0)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno_,
+ boost::system::system_category) );
+ }
+
+ // bind_to_any_processor() can not be supported
+}}
+
+#endif // BOOST_TP_DETAIL_BIND_PROCESSOR_IRIX_H

Added: sandbox/threadpool/boost/tp/detail/bind_processor_linux.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/detail/bind_processor_linux.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,58 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_DETAIL_BIND_PRCESSOR_LINUX_H
+#define BOOST_TP_DETAIL_BIND_PRCESSOR_LINUX_H
+
+extern "C"
+{
+#include <pthread.h>
+#include <sched.h>
+}
+
+#include <boost/assert.hpp>
+#include <boost/thread.hpp>
+#include <boost/system/system_error.hpp>
+
+namespace boost { namespace this_thread
+{
+ inline
+ void bind_to_processor( unsigned int n)
+ {
+ BOOST_ASSERT( n >= 0);
+ BOOST_ASSERT( n < CPU_SETSIZE);
+ BOOST_ASSERT( n < boost::thread::hardware_concurrency() );
+
+ cpu_set_t cpuset;
+ CPU_ZERO( & cpuset);
+ CPU_SET( n, & cpuset);
+
+ int errno_( ::pthread_setaffinity_np( ::pthread_self(), sizeof( cpuset), & cpuset) );
+ if ( errno_ != 0)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno_,
+ boost::system::system_category) );
+ }
+
+ inline
+ void bind_to_any_processor()
+ {
+ cpu_set_t cpuset;
+ CPU_ZERO( & cpuset);
+
+ unsigned int max( boost::thread::hardware_concurrency() );
+ for ( unsigned int i( 0); i < max; ++i)
+ CPU_SET( i, & cpuset);
+
+ int errno_( ::pthread_setaffinity_np( ::pthread_self(), sizeof( cpuset), & cpuset) );
+ if ( errno_ != 0)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno_,
+ boost::system::system_category) );
+ }
+}}
+
+#endif // BOOST_TP_DETAIL_BIND_PRCESSOR_LINUX_H

Added: sandbox/threadpool/boost/tp/detail/bind_processor_solaris.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/detail/bind_processor_solaris.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,45 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_DETAIL_BIND_PROCESSOR_SOLARIS_H
+#define BOOST_TP_DETAIL_BIND_PROCESSOR_SOLARIS_H
+
+extern "C"
+{
+#include <sys/types.h>
+#include <sys/processor.h>
+#include <sys/procset.h>
+}
+
+#include <boost/assert.hpp>
+#include <boost/thread.hpp>
+#include <boost/system/system_error.hpp>
+
+namespace boost { namespace this_thread
+{
+ inline
+ void bind_to_processor( unsigned int n)
+ {
+ BOOST_ASSERT( n >= 0);
+ BOOST_ASSERT( n < boost::thread::hardware_concurrency() );
+
+ if ( ::processor_bind( P_LWPID, P_MYID, static_cast< processorid_t >( n), 0) == -1)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno,
+ boost::system::system_category) );
+ }
+
+ inline
+ void bind_to_any_processor()
+ {
+ if ( ::processor_bind( P_LWPID, P_MYID, PBIND_NONE, 0) == -1)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno,
+ boost::system::system_category) );
+ }
+}}
+
+#endif // BOOST_TP_DETAIL_BIND_PROCESSOR_SOLARIS_H

Added: sandbox/threadpool/boost/tp/detail/bind_processor_windows.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/detail/bind_processor_windows.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,47 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_DETAIL_BIND_PROCESSOR_WINDOWS_H
+#define BOOST_TP_DETAIL_BIND_PROCESSOR_WINDOWS_H
+
+extern "C"
+{
+#include <windows.h>
+}
+
+#include <boost/assert.hpp>
+#include <boost/thread.hpp>
+#include <boost/system/system_error.hpp>
+
+namespace boost { namespace this_thread
+{
+ inline
+ void bind_to_processor( unsigned int n)
+ {
+ BOOST_ASSERT( n >= 0);
+ BOOST_ASSERT( n < boost::thread::hardware_concurrency() );
+
+ if ( ::SetThreadAffinityMask( ::GetCurrentThread(), ( DWORD_PTR)1 << n) == 0)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ ::GetLastError(),
+ boost::system::system_category) );
+ }
+
+ inline
+ void bind_to_any_processor()
+ {
+ DWORD_PTR ptr( 1);
+ for ( unsigned int i( 0); i < boost::thread::hardware_concurrency(); ++i)
+ ptr = ptr << i;
+
+ if ( ::SetThreadAffinityMask( ::GetCurrentThread(), ptr) == 0)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ ::GetLastError(),
+ boost::system::system_category) );
+ }
+}}
+
+#endif // BOOST_TP_DETAIL_BIND_PROCESSOR_WINDOWS_H

Added: sandbox/threadpool/boost/tp/detail/callable.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/detail/callable.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,62 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_DETAIL_CALLABLE_H
+#define BOOST_TP_DETAIL_CALLABLE_H
+
+#include <boost/future.hpp>
+
+#include <boost/thread/detail/move.hpp>
+
+namespace boost { namespace tp {
+namespace detail
+{
+class callable
+{
+private:
+ struct impl
+ {
+ virtual ~impl() {}
+ virtual void run() = 0;
+ };
+
+ template< typename T >
+ struct impl_wrapper
+ : public impl
+ {
+ jss::packaged_task< T > tsk;
+
+ impl_wrapper( boost::detail::thread_move_t< jss::packaged_task< T > > const& t)
+ : tsk( t)
+ {}
+
+ void run()
+ { tsk(); }
+ };
+
+ boost::shared_ptr< impl > impl_;
+
+public:
+ callable()
+ : impl_()
+ {}
+
+ template< typename T >
+ callable( boost::detail::thread_move_t< jss::packaged_task< T > > const& t)
+ : impl_( new impl_wrapper< T >( t) )
+ {}
+
+ void operator()()
+ { impl_->run(); }
+
+ bool empty() const
+ { return ! impl_; }
+
+ void clear()
+ { impl_.reset(); }
+};
+} } }
+
+#endif // BOOST_TP_DETAIL_CALLABLE_H
+

Added: sandbox/threadpool/boost/tp/detail/guard.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/detail/guard.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,38 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_DETAIL_GUARD_H
+#define BOOST_TP_DETAIL_GUARD_H
+
+#include <boost/assert.hpp>
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/utility.hpp>
+
+namespace boost { namespace tp {
+namespace detail
+{
+class guard
+: private noncopyable
+{
+private:
+ volatile uint32_t & active_worker_;
+
+public:
+ guard( volatile uint32_t & active_worker)
+ : active_worker_( active_worker)
+ {
+ BOOST_ASSERT( active_worker_ >= 0);
+ interprocess::detail::atomic_inc32( & active_worker_);
+ }
+
+ ~guard()
+ {
+ interprocess::detail::atomic_dec32( & active_worker_);
+ BOOST_ASSERT( active_worker_ >= 0);
+ }
+};
+} } }
+
+#endif // BOOST_TP_DETAIL_GUARD_H
+

Added: sandbox/threadpool/boost/tp/detail/info.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/detail/info.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,19 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_DETAIL_INFO_H
+#define BOOST_TP_DETAIL_INFO_H
+
+namespace boost { namespace tp {
+namespace detail
+{
+struct has_priority
+{};
+
+struct has_no_priority
+{};
+} } }
+
+#endif // BOOST_TP_DETAIL_INFO_H
+

Added: sandbox/threadpool/boost/tp/detail/interrupter.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/detail/interrupter.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,138 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_DETAIL_INTERRUPTER_H
+#define BOOST_TP_DETAIL_INTERRUPTER_H
+
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/utility.hpp>
+
+namespace boost { namespace tp {
+namespace detail
+{
+class interrupter
+{
+private:
+ class impl
+ : private noncopyable
+ {
+ private:
+ bool interrupt_requested_;
+ condition_variable cond_;
+ mutex mtx_;
+ shared_ptr< thread > thrd_;
+
+ void interrupt_()
+ {
+ if ( ! interrupt_requested_)
+ {
+ interrupt_requested_ = true;
+ if ( thrd_) thrd_->interrupt();
+ }
+ }
+
+ public:
+ impl()
+ :
+ interrupt_requested_( false),
+ cond_(),
+ mtx_(),
+ thrd_()
+ {}
+
+ void set( shared_ptr< thread > const& thrd)
+ {
+ BOOST_ASSERT( thrd);
+ unique_lock< mutex > lk( mtx_);
+ thrd_ = thrd;
+ BOOST_ASSERT( thrd_);
+ if ( interrupt_requested_) thrd_->interrupt();
+ }
+
+ void reset()
+ {
+ unique_lock< mutex > lk( mtx_);
+ thrd_.reset();
+ BOOST_ASSERT( ! thrd_);
+ try
+ { this_thread::interruption_point(); }
+ catch ( thread_interrupted const&)
+ {}
+ BOOST_ASSERT( ! this_thread::interruption_requested() );
+ cond_.notify_all();
+ }
+
+ void interrupt()
+ {
+ unique_lock< mutex > lk( mtx_);
+ interrupt_();
+ }
+
+ void interrupt_and_wait()
+ {
+ unique_lock< mutex > lk( mtx_);
+ interrupt_();
+ cond_.wait( lk);
+ }
+
+ void interrupt_and_wait( system_time const& abs_time)
+ {
+ unique_lock< mutex > lk( mtx_);
+ interrupt_();
+ cond_.timed_wait( lk, abs_time);
+ }
+
+ template< typename DurationType >
+ void interrupt_and_wait( DurationType const& rel_time)
+ {
+ unique_lock< mutex > lk( mtx_);
+ interrupt_();
+ cond_.timed_wait( lk, rel_time);
+ }
+
+ bool interrupt_requested()
+ {
+ unique_lock< mutex > lk( mtx_);
+ return interrupt_requested_;
+ }
+ };
+
+ shared_ptr< impl > impl_;
+
+public:
+ interrupter()
+ : impl_( new impl() )
+ {}
+
+ void set( shared_ptr< thread > const& thrd)
+ { impl_->set( thrd); }
+
+ void reset()
+ { impl_->reset(); }
+
+ void interrupt()
+ { impl_->interrupt(); }
+
+ void interrupt_and_wait()
+ { impl_->interrupt_and_wait(); }
+
+ void interrupt_and_wait( system_time const& abs_time)
+ { impl_->interrupt_and_wait( abs_time); }
+
+ template< typename DurationType >
+ void interrupt_and_wait( DurationType const& rel_time)
+ { impl_->interrupt_and_wait( rel_time); }
+
+ bool interrupt_requested()
+ { return impl_->interrupt_requested(); }
+};
+}
+} }
+
+#endif // BOOST_TP_DETAIL_INTERRUPTER_H

Added: sandbox/threadpool/boost/tp/detail/wsq.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/detail/wsq.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,170 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_DETAIL_WSQ_H
+#define BOOST_TP_DETAIL_WSQ_H
+
+#include <utility>
+
+#include <boost/assert.hpp>
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/foreach.hpp>
+#include <boost/function.hpp>
+#include <boost/shared_array.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/tp/detail/interrupter.hpp>
+
+namespace boost { namespace tp {
+namespace detail
+{
+template< typename T >
+class wsq
+: private noncopyable
+{
+private:
+ class impl
+ {
+ private:
+ const int initial_size_;
+ shared_array< T > array_;
+ int capacity_;
+ int mask_;
+ volatile uint32_t head_idx_;
+ volatile uint32_t tail_idx_;
+ recursive_mutex mtx_;
+
+ public:
+ impl()
+ :
+ initial_size_( 32),
+ array_( new T[ initial_size_]),
+ capacity_( initial_size_),
+ mask_( initial_size_ - 1),
+ head_idx_( 0),
+ tail_idx_( 0),
+ mtx_()
+ {}
+
+ bool empty() const
+ { return head_idx_ >= tail_idx_; }
+
+ std::size_t size() const
+ { return tail_idx_ - head_idx_; }
+
+ void put( T const& t)
+ {
+ uint32_t tail( tail_idx_);
+ if ( tail <= head_idx_ + mask_)
+ {
+ array_[tail & mask_] = t;
+ tail_idx_ = tail + 1;
+ }
+ else
+ {
+ unique_lock< recursive_mutex > lk( mtx_);
+ uint32_t head( head_idx_);
+ int count( size() );
+
+ if ( count >= mask_)
+ {
+ capacity_ <<= 1;
+ shared_array< T > array( new T[capacity_]);
+ for ( int i( 0); i != count; ++i)
+ array[i] = array_[(i + head) & mask_];
+ array_.swap( array);
+ head_idx_ = 0;
+ tail_idx_ = tail = count;
+ mask_ = (mask_ << 1) | 1;
+ }
+ array_[tail & mask_] = t;
+ tail_idx_ = tail + 1;
+ }
+ }
+
+ bool try_take( T & t)
+ {
+ uint32_t tail( tail_idx_);
+ if ( tail == 0)
+ return false;
+ tail -= 1;
+ interprocess::detail::atomic_write32( & tail_idx_, tail);
+ if ( head_idx_ <= tail)
+ {
+ t = array_[tail & mask_];
+ return true;
+ }
+ else
+ {
+ unique_lock< recursive_mutex > lk( mtx_);
+ if ( head_idx_ <= tail)
+ {
+ t = array_[tail & mask_];
+ return true;
+ }
+ else
+ {
+ tail_idx_ = tail + 1;
+ return false;
+ }
+ }
+ }
+
+ bool try_steal( T & t)
+ {
+ recursive_mutex::scoped_try_lock lk( mtx_);
+ if ( lk.owns_lock() )
+ {
+ uint32_t head( head_idx_);
+ interprocess::detail::atomic_write32( & head_idx_, head + 1);
+ if ( head < tail_idx_)
+ {
+ t = array_[head & mask_];
+ return true;
+ }
+ else
+ {
+ head_idx_ = head;
+ return false;
+ }
+ }
+ return false;
+ }
+ };
+
+ shared_ptr< impl > impl_;
+
+public:
+ wsq()
+ : impl_( new impl() )
+ {}
+
+ bool empty() const
+ { return impl_->empty(); }
+
+ std::size_t size() const
+ { return impl_->size(); }
+
+ void put( T const& t)
+ { impl_->put( t); }
+
+ bool try_take( T & t)
+ { return impl_->try_take( t); }
+
+ bool try_steal( T & t)
+ { return impl_->try_steal( t); }
+
+ void swap( wsq & queue)
+ {
+ if ( this == & queue) return;
+ impl_.swap( queue.impl_);
+ }
+};
+} } }
+
+#endif // BOOST_TP_DETAIL_WSQ_H
+

Added: sandbox/threadpool/boost/tp/exceptions.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/exceptions.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,59 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_EXCEPTIONS_H
+#define BOOST_TP_EXCEPTIONS_H
+
+#include <stdexcept>
+#include <string>
+
+namespace boost { namespace tp
+{
+class invalid_poolsize
+: public std::invalid_argument
+{
+public:
+ invalid_poolsize( std::string const& msg)
+ : std::invalid_argument( msg)
+ {}
+};
+
+class invalid_scanns
+: public std::invalid_argument
+{
+public:
+ invalid_scanns( std::string const& msg)
+ : std::invalid_argument( msg)
+ {}
+};
+
+class invalid_timeduration
+: public std::invalid_argument
+{
+public:
+ invalid_timeduration( std::string const& msg)
+ : std::invalid_argument( msg)
+ {}
+};
+
+class invalid_watermark
+: public std::invalid_argument
+{
+public:
+ invalid_watermark( std::string const& msg)
+ : std::invalid_argument( msg)
+ {}
+};
+
+class task_rejected
+: public std::runtime_error
+{
+public:
+ task_rejected( std::string const& msg)
+ : std::runtime_error( msg)
+ {}
+};
+} }
+
+#endif // BOOST_TP_EXCEPTIONS_H

Added: sandbox/threadpool/boost/tp/fifo.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/fifo.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,92 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_FIFO_H
+#define BOOST_TP_FIFO_H
+
+#include <cstddef>
+#include <list>
+
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+
+#include <boost/tp/detail/info.hpp>
+#include <boost/tp/detail/interrupter.hpp>
+
+namespace boost { namespace tp
+{
+struct fifo
+{
+ typedef detail::has_no_priority priority_tag_type;
+
+ template< typename Callable >
+ class impl
+ {
+ private:
+ typedef Callable callable;
+
+ public:
+ class item
+ {
+ private:
+ callable ca_;
+ detail::interrupter intr_;
+
+ public:
+ item(
+ callable const& ca,
+ detail::interrupter const& intr)
+ : ca_( ca), intr_( intr)
+ { BOOST_ASSERT( ! ca_.empty() ); }
+
+ const callable ca() const
+ { return ca_; }
+
+ const detail::interrupter intr() const
+ { return intr_; }
+ };
+
+ typedef typename std::list< item >::iterator iterator;
+ typedef typename std::list< item >::const_iterator const_iterator;
+
+ private:
+ std::list< item > lst_;
+
+ public:
+ void push( item const& itm)
+ { lst_.push_back( itm); }
+
+ const item pop()
+ {
+ item itm( lst_.front() );
+ lst_.pop_front();
+ return itm;
+ }
+
+ std::size_t size() const
+ { return lst_.size(); }
+
+ bool empty() const
+ { return lst_.empty(); }
+
+ void clear()
+ { lst_.clear(); }
+
+ const iterator begin()
+ { return lst_.begin(); }
+
+ const const_iterator begin() const
+ { return lst_.begin(); }
+
+ const iterator end()
+ { return lst_.end(); }
+
+ const const_iterator end() const
+ { return lst_.end(); }
+ };
+};
+} }
+
+#endif // BOOST_TP_FIFO_H

Added: sandbox/threadpool/boost/tp/info.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/info.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,34 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_INFO_H
+#define BOOST_TP_INFO_H
+
+#include <boost/mpl/bool.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/tp/detail/info.hpp>
+
+namespace boost { namespace tp
+{
+template< typename Pool >
+struct has_priority
+:
+public mpl::bool_<
+ is_same<
+ detail::has_priority,
+ typename Pool::scheduler_type::priority_tag_type
+ >::value
+>
+{};
+
+template< typename Pool >
+struct priority_type
+{
+ typedef typename Pool::scheduler_type::attribute_type type;
+};
+} }
+
+#endif // BOOST_TP_INFO_H
+

Added: sandbox/threadpool/boost/tp/lifo.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/lifo.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,92 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_LIFO_H
+#define BOOST_TP_LIFO_H
+
+#include <cstddef>
+#include <list>
+
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+
+#include <boost/tp/detail/info.hpp>
+#include <boost/tp/detail/interrupter.hpp>
+
+namespace boost { namespace tp
+{
+struct lifo
+{
+ typedef detail::has_no_priority priority_tag_type;
+
+ template< typename Callable >
+ class impl
+ {
+ private:
+ typedef Callable callable;
+
+ public:
+ class item
+ {
+ private:
+ callable ca_;
+ detail::interrupter intr_;
+
+ public:
+ item(
+ callable const& ca,
+ detail::interrupter const& intr)
+ : ca_( ca), intr_( intr)
+ { BOOST_ASSERT( ! ca_.empty() ); }
+
+ const callable ca() const
+ { return ca_; }
+
+ const detail::interrupter intr() const
+ { return intr_; }
+ };
+
+ typedef typename std::list< item >::iterator iterator;
+ typedef typename std::list< item >::const_iterator const_iterator;
+
+ private:
+ std::list< item > lst_;
+
+ public:
+ void push( item const& itm)
+ { lst_.push_front( itm); }
+
+ const item pop()
+ {
+ item itm( lst_.front() );
+ lst_.pop_front();
+ return itm;
+ }
+
+ std::size_t size() const
+ { return lst_.size(); }
+
+ bool empty() const
+ { return lst_.empty(); }
+
+ void clear()
+ { lst_.clear(); }
+
+ const iterator begin()
+ { return lst_.begin(); }
+
+ const const_iterator begin() const
+ { return lst_.begin(); }
+
+ const iterator end()
+ { return lst_.end(); }
+
+ const const_iterator end() const
+ { return lst_.end(); }
+ };
+};
+} }
+
+#endif // BOOST_TP_LIFO_H

Added: sandbox/threadpool/boost/tp/pool.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/pool.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,748 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_POOL_H
+#define BOOST_TP_POOL_H
+
+#include <cstddef>
+#include <list>
+#include <utility>
+#include <vector>
+
+#include <boost/future.hpp>
+
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/function.hpp>
+#include <boost/interprocess/sync/interprocess_semaphore.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/mem_fun.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/random_access_index.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/random.hpp>
+#include <boost/ref.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/tss.hpp>
+#include <boost/utility.hpp>
+#include <boost/utility/result_of.hpp>
+
+#include <boost/tp/detail/callable.hpp>
+#include <boost/tp/detail/guard.hpp>
+#include <boost/tp/detail/interrupter.hpp>
+#ifdef BOOST_BIND_WORKER_TO_PROCESSORS
+#include <boost/tp/detail/bind_processor.hpp>
+#endif
+#include <boost/tp/detail/wsq.hpp>
+#include <boost/tp/exceptions.hpp>
+#include <boost/tp/poolsize.hpp>
+#include <boost/tp/scanns.hpp>
+#include <boost/tp/task.hpp>
+#include <boost/tp/watermark.hpp>
+
+// workaround until boost::move is fixed by Anthony Williams
+namespace boost
+{
+ template< typename T >
+ detail::thread_move_t< jss::packaged_task< T > > move( jss::packaged_task< T > & t)
+ {
+ return detail::thread_move_t< jss::packaged_task< T > >( t);
+ }
+}
+
+namespace boost {
+namespace tp
+{
+template< typename Channel >
+class pool
+: private noncopyable
+{
+private:
+ typedef Channel channel;
+ typedef typename channel::item channel_item;
+
+ enum state
+ {
+ active_state,
+ terminateing_state,
+ terminated_state
+ };
+
+ class worker
+ {
+ private:
+ class wimpl : private noncopyable
+ {
+ private:
+ typedef std::pair< detail::callable, detail::interrupter > item;
+
+ shared_ptr< thread > thrd_;
+ detail::wsq< item > wsq_;
+ interprocess::interprocess_semaphore shtdwn_sem_;
+ interprocess::interprocess_semaphore shtdwn_now_sem_;
+ bool shtdwn_;
+ std::size_t scns_;
+
+ public:
+ wimpl( function< void() > const& fn)
+ :
+ thrd_( new thread( fn) ),
+ wsq_(),
+ shtdwn_sem_( 0),
+ shtdwn_now_sem_( 0),
+ shtdwn_( false),
+ scns_( 0)
+ { BOOST_ASSERT( ! fn.empty() ); }
+
+ const shared_ptr< thread > thrd() const
+ { return thrd_; }
+
+ const thread::id get_id() const
+ { return thrd_->get_id(); }
+
+ void join() const
+ { thrd_->join(); }
+
+ void interrupt() const
+ { thrd_->interrupt(); }
+
+ void put(
+ detail::callable const& ca,
+ detail::interrupter const& intr)
+ {
+ BOOST_ASSERT( ! ca.empty() );
+ wsq_.put( std::make_pair( ca, intr) );
+ }
+
+ bool try_take(
+ detail::callable & ca,
+ detail::interrupter & intr)
+ {
+ item itm;
+ bool result( wsq_.try_take( itm) );
+ if ( result)
+ {
+ ca = itm.first;
+ intr = itm.second;
+ }
+ return result;
+ }
+
+ bool try_steal(
+ detail::callable & ca,
+ detail::interrupter & intr)
+ {
+ item itm;
+ bool result( wsq_.try_steal( itm) );
+ if ( result)
+ {
+ ca = itm.first;
+ intr = itm.second;
+ }
+ return result;
+ }
+
+ bool empty()
+ { return wsq_.empty(); }
+
+ void signal_shutdown()
+ { shtdwn_sem_.post(); }
+
+ void signal_shutdown_now()
+ { shtdwn_now_sem_.post(); }
+
+ bool shutdown()
+ {
+ if ( ! shtdwn_)
+ shtdwn_ = shtdwn_sem_.try_wait();
+ return shtdwn_;
+ }
+
+ bool shutdown_now()
+ { return shtdwn_now_sem_.try_wait(); }
+
+ std::size_t scanns() const
+ { return scns_; }
+
+ void increment_scanns()
+ { ++scns_; }
+
+ void reset_scanns()
+ { scns_ = 0; }
+ };
+
+ shared_ptr< wimpl > impl_;
+
+ public:
+ worker( function< void() > const& fn)
+ : impl_( new wimpl( fn) )
+ {}
+
+ const shared_ptr< thread > thrd() const
+ { return impl_->thrd(); }
+
+ const thread::id get_id() const
+ { return impl_->get_id(); }
+
+ void join() const
+ { impl_->join(); }
+
+ void interrupt() const
+ { impl_->interrupt(); }
+
+ void put(
+ detail::callable const& ca,
+ detail::interrupter const& intr)
+ { impl_->put( ca, intr); }
+
+ bool try_take(
+ detail::callable & ca,
+ detail::interrupter & intr)
+ { return impl_->try_take( ca, intr); }
+
+ bool try_steal(
+ detail::callable & ca,
+ detail::interrupter & intr)
+ { return impl_->try_steal( ca, intr); }
+
+ bool empty() const
+ { return impl_->empty(); }
+
+ void signal_shutdown()
+ { impl_->signal_shutdown(); }
+
+ void signal_shutdown_now()
+ { impl_->signal_shutdown_now(); }
+
+ bool shutdown()
+ { return impl_->shutdown(); }
+
+ bool shutdown_now()
+ { return impl_->shutdown_now(); }
+
+ std::size_t scanns() const
+ { return impl_->scanns(); }
+
+ void increment_scanns()
+ { impl_->increment_scanns(); }
+
+ void reset_scanns()
+ { impl_->reset_scanns(); }
+ };
+
+ struct id_idx_tag {};
+ struct rnd_idx_tag {};
+
+ typedef multi_index::multi_index_container<
+ worker,
+ multi_index::indexed_by<
+ multi_index::ordered_unique<
+ multi_index::tag< id_idx_tag >,
+ multi_index::const_mem_fun<
+ worker,
+ const thread::id,
+ & worker::get_id
+ >
+ >,
+ multi_index::random_access< multi_index::tag< rnd_idx_tag > >
+ >
+ > worker_list;
+
+ typedef typename worker_list::template index<
+ id_idx_tag >::type id_idx;
+ typedef typename worker_list::template index<
+ rnd_idx_tag >::type rnd_idx;
+
+ class random_idx
+ {
+ private:
+ rand48 rng_;
+ uniform_int<> six_;
+ variate_generator< rand48 &, uniform_int<> > die_;
+
+ public:
+ random_idx( worker_list & lst)
+ :
+ rng_(),
+ six_( 0, lst.size() - 1),
+ die_( rng_, six_)
+ {}
+
+ std::size_t operator()()
+ { return die_(); }
+ };
+
+ worker_list worker_;
+ shared_mutex mtx_worker_;
+ thread_specific_ptr< worker > tss_worker_;
+ thread_specific_ptr< random_idx > tss_rnd_idx_;
+ state state_;
+ shared_mutex mtx_state_;
+ channel channel_;
+ posix_time::time_duration asleep_;
+ scanns scns_;
+ volatile uint32_t active_worker_;
+ volatile uint32_t idle_worker_;
+ volatile uint32_t running_worker_;
+
+ void execute_(
+ worker & w,
+ detail::callable & ca,
+ detail::interrupter & intr,
+ shared_ptr< thread > const& thrd)
+ {
+ BOOST_ASSERT( ! ca.empty() );
+ detail::guard grd( active_worker_);
+ shared_ptr< void > ig(
+ static_cast< void * >( 0),
+ boost::bind(
+ & detail::interrupter::reset,
+ intr) );
+ intr.set( thrd);
+ ca();
+ ca.clear();
+ BOOST_ASSERT( ca.empty() );
+ }
+
+ void next_callable_( worker & w, detail::callable & ca, detail::interrupter & intr)
+ {
+ rnd_idx & ridx( worker_.get< rnd_idx_tag >() );
+ if ( ! w.try_take( ca, intr) )
+ {
+ if ( ! channel_.try_take( ca, intr) )
+ {
+ std::size_t idx( ( * tss_rnd_idx_)() );
+ for ( std::size_t j( 0); j < worker_.size(); ++j)
+ {
+ worker other( ridx[idx]);
+ if ( this_thread::get_id() == other.get_id() ) continue;
+ if ( ++idx >= worker_.size() ) idx = 0;
+ if ( other.try_steal( ca, intr) ) break;
+ }
+
+ if ( ca.empty() )
+ {
+ detail::guard grd( idle_worker_);
+ if ( shutdown_( w) ) return;
+ w.increment_scanns();
+ if ( w.scanns() >= scns_)
+ {
+ if ( size_() == idle_worker_)
+ channel_.take( ca, intr, asleep_);
+ else
+ this_thread::sleep( asleep_);
+ w.reset_scanns();
+ }
+ else
+ this_thread::yield();
+ }
+ }
+ }
+ }
+
+ template< typename R >
+ void wait_callback_( jss::shared_future< R > const& f)
+ {
+ worker * w( tss_worker_.get() );
+ BOOST_ASSERT( w);
+ shared_ptr< thread > thrd( w->thrd() );
+ BOOST_ASSERT( thrd);
+ detail::interrupter intr;
+ detail::callable ca;
+ while ( ! shutdown_( * w) && ! f.is_ready() )
+ {
+ next_callable_( * w, ca, intr);
+ if( ! ca.empty() )
+ {
+ execute_( *w, ca, intr, thrd);
+ w->reset_scanns();
+ }
+ }
+ }
+
+ void entry_()
+ {
+ shared_lock< shared_mutex > lk( mtx_worker_);
+ id_idx & iidx( worker_.get< id_idx_tag >() );
+ typename id_idx::iterator i( iidx.find( this_thread::get_id() ) );
+ lk.unlock();
+ BOOST_ASSERT( i != iidx.end() );
+
+ worker w( * i);
+ BOOST_ASSERT( w.get_id() == this_thread::get_id() );
+ tss_worker_.reset( new worker( w) );
+ shared_ptr< thread > thrd( w.thrd() );
+ BOOST_ASSERT( thrd);
+ detail::callable ca;
+ detail::interrupter intr;
+
+ tss_rnd_idx_.reset( new random_idx( worker_) );
+
+ detail::guard grd( running_worker_);
+
+ while ( ! shutdown_( w) )
+ {
+ next_callable_( w, ca, intr);
+ if( ! ca.empty() )
+ {
+ execute_( w, ca, intr, thrd);
+ w.reset_scanns();
+ }
+ }
+ }
+
+ void create_worker_()
+ {
+ BOOST_ASSERT( ! terminateing_() && ! terminated_() );
+ worker_.insert(
+ worker(
+ boost::bind(
+ & pool::entry_,
+ this) ) );
+ }
+
+#ifdef BOOST_BIND_WORKER_TO_PROCESSORS
+ void entry_( std::size_t n)
+ {
+ this_thread::bind_to_processor( n);
+ entry_();
+ }
+
+ void create_worker_( std::size_t n)
+ {
+ BOOST_ASSERT( ! terminateing_() && ! terminated_() );
+ worker w(
+ boost::bind(
+ & pool::entry_,
+ this,
+ n) );
+ worker_.insert(
+ w );
+ }
+#endif
+
+ std::size_t active_() const
+ { return active_worker_; }
+
+ std::size_t idle_() const
+ { return size_() - active_(); }
+
+ std::size_t size_() const
+ { return worker_.size(); }
+
+ bool terminated_() const
+ { return state_ == terminated_state; }
+
+ bool terminateing_() const
+ { return state_ == terminateing_state; }
+
+ bool shutdown_( worker & w)
+ {
+ if ( w.shutdown() && channel_.empty() )
+ return true;
+ else if ( w.shutdown_now() )
+ return true;
+ return false;
+ }
+
+public:
+ explicit pool(
+ poolsize const& psize,
+ posix_time::time_duration const& asleep = posix_time::microseconds( 10),
+ scanns const& scns = scanns( 20) )
+ :
+ worker_(),
+ mtx_worker_(),
+ tss_worker_(),
+ tss_rnd_idx_(),
+ state_( active_state),
+ mtx_state_(),
+ channel_(),
+ asleep_( asleep),
+ scns_( scns),
+ active_worker_( 0),
+ idle_worker_( 0),
+ running_worker_( 0)
+ {
+ if ( asleep_.is_special() || asleep_.is_negative() )
+ throw invalid_timeduration("argument asleep is not valid");
+ channel_.activate();
+ unique_lock< shared_mutex > lk( mtx_worker_);
+ for ( std::size_t i( 0); i < psize; ++i)
+ create_worker_();
+ lk.unlock();
+ }
+
+ explicit pool(
+ poolsize const& psize,
+ high_watermark const& hwm,
+ low_watermark const& lwm,
+ posix_time::time_duration const& asleep = posix_time::microseconds( 100),
+ scanns const& scns = scanns( 20) )
+ :
+ worker_(),
+ mtx_worker_(),
+ tss_worker_(),
+ tss_rnd_idx_(),
+ state_( active_state),
+ mtx_state_(),
+ channel_(
+ hwm,
+ lwm),
+ asleep_( asleep),
+ scns_( scns),
+ active_worker_( 0),
+ idle_worker_( 0),
+ running_worker_( 0)
+ {
+ if ( asleep_.is_special() || asleep_.is_negative() )
+ throw invalid_timeduration("argument asleep is not valid");
+ channel_.activate();
+ unique_lock< shared_mutex > lk( mtx_worker_);
+ for ( std::size_t i( 0); i < psize; ++i)
+ create_worker_();
+ lk.unlock();
+ }
+
+#ifdef BOOST_BIND_WORKER_TO_PROCESSORS
+ explicit pool(
+ posix_time::time_duration const& asleep = posix_time::microseconds( 10),
+ scanns const& scns = scanns( 20) )
+ :
+ worker_(),
+ mtx_worker_(),
+ tss_worker_(),
+ tss_rnd_idx_(),
+ state_( active_state),
+ mtx_state_(),
+ channel_(),
+ asleep_( asleep),
+ scns_( scns),
+ active_worker_( 0),
+ idle_worker_( 0),
+ running_worker_( 0)
+ {
+ if ( asleep_.is_special() || asleep_.is_negative() )
+ throw invalid_timeduration("argument asleep is not valid");
+ std::size_t psize( thread::hardware_concurrency() );
+ BOOST_ASSERT( psize > 0);
+ channel_.activate();
+ unique_lock< shared_mutex > lk( mtx_worker_);
+ for ( std::size_t i( 0); i < psize; ++i)
+ create_worker_( i);
+ lk.unlock();
+ }
+
+ explicit pool(
+ high_watermark const& hwm,
+ low_watermark const& lwm,
+ posix_time::time_duration const& asleep = posix_time::microseconds( 100),
+ scanns const& scns = scanns( 20) )
+ :
+ worker_(),
+ mtx_worker_(),
+ tss_worker_(),
+ tss_rnd_idx_(),
+ state_( active_state),
+ mtx_state_(),
+ channel_(
+ hwm,
+ lwm),
+ asleep_( asleep),
+ scns_( scns),
+ active_worker_( 0),
+ idle_worker_( 0),
+ running_worker_( 0)
+ {
+ if ( asleep_.is_special() || asleep_.is_negative() )
+ throw invalid_timeduration("argument asleep is not valid");
+ std::size_t psize( thread::hardware_concurrency() );
+ BOOST_ASSERT( psize > 0);
+ channel_.activate();
+ unique_lock< shared_mutex > lk( mtx_worker_);
+ for ( std::size_t i( 0); i < psize; ++i)
+ create_worker_( i);
+ lk.unlock();
+ }
+#endif
+
+ ~pool()
+ { shutdown(); }
+
+ std::size_t active()
+ {
+ shared_lock< shared_mutex > lk( mtx_worker_);
+ return active_();
+ }
+
+ std::size_t idle()
+ {
+ shared_lock< shared_mutex > lk( mtx_worker_);
+ return idle_();
+ }
+
+ void shutdown()
+ {
+ unique_lock< shared_mutex > lk1( mtx_state_);
+ if ( terminateing_() || terminated_() ) return;
+ state_ = terminateing_state;
+ lk1.unlock();
+
+ channel_.deactivate();
+ shared_lock< shared_mutex > lk2( mtx_worker_);
+ BOOST_FOREACH( worker w, worker_)
+ { w.signal_shutdown(); }
+ BOOST_FOREACH( worker w, worker_)
+ { w.join(); }
+ lk2.unlock();
+
+ lk1.lock();
+ state_ = terminated_state;
+ }
+
+ const std::vector< detail::callable > shutdown_now()
+ {
+ unique_lock< shared_mutex > lk1( mtx_state_);
+ if ( terminateing_() || terminated_() ) return std::vector< detail::callable >();
+ state_ = terminateing_state;
+ lk1.unlock();
+
+ channel_.deactivate_now();
+ shared_lock< shared_mutex > lk2( mtx_worker_);
+ BOOST_FOREACH( worker w, worker_)
+ {
+ w.signal_shutdown_now();
+ w.interrupt();
+ }
+ BOOST_FOREACH( worker w, worker_)
+ { w.join(); }
+ lk2.unlock();
+ std::vector< detail::callable > drain( channel_.drain() );
+
+ lk1.lock();
+ state_ = terminated_state;
+ lk1.unlock();
+
+ return drain;
+ }
+
+ std::size_t size()
+ {
+ shared_lock< shared_mutex > lk( mtx_worker_);
+ return size_();
+ }
+
+ bool terminated()
+ {
+ shared_lock< shared_mutex > lk( mtx_state_);
+ return terminated_();
+ }
+
+ bool terminateing()
+ {
+ shared_lock< shared_mutex > lk( mtx_state_);
+ return terminateing_();
+ }
+
+ void clear()
+ { channel_.clear(); }
+
+ bool empty()
+ { return channel_.empty(); }
+
+ std::size_t pending()
+ { return channel_.size(); }
+
+ std::size_t upper_bound()
+ { return channel_.upper_bound(); }
+
+ void upper_bound( high_watermark const& hwm)
+ { return channel_.upper_bound( hwm); }
+
+ std::size_t lower_bound()
+ { return channel_.lower_bound(); }
+
+ void lower_bound( low_watermark const lwm)
+ { return channel_.lower_bound( lwm); }
+
+ template< typename Act >
+ task< typename result_of< Act() >::type > submit( Act const& act)
+ {
+ typedef typename result_of< Act() >::type R;
+ detail::interrupter intr;
+ jss::packaged_task< R > tsk( act);
+ jss::shared_future< R > fut( tsk.get_future() );
+ worker * w( tss_worker_.get() );
+ if ( w)
+ {
+ tsk.set_wait_callback(
+ bind(
+ ( void ( pool< Channel >::*)( jss::shared_future< R > const&) ) & pool< Channel >::wait_callback_,
+ this,
+ fut) );
+ w->put( detail::callable( move( tsk) ), intr);
+ return task< R >( fut, intr);
+ }
+ else
+ {
+ shared_lock< shared_mutex > lk( mtx_state_);
+ if ( terminated_() )
+ throw task_rejected("pool ist terminated");
+ if ( terminateing_() )
+ throw task_rejected("pool ist terminateing");
+
+ channel_item itm( detail::callable( move( tsk) ), intr);
+ channel_.put( itm);
+ return task< R >( fut, intr);
+ }
+ }
+
+ template<
+ typename Act,
+ typename Attr
+ >
+ task< typename result_of< Act() >::type > submit(
+ Act const& act,
+ Attr const& attr)
+ {
+ typedef typename result_of< Act() >::type R;
+ detail::interrupter intr;
+ jss::packaged_task< R > tsk( act);
+ jss::shared_future< R > fut( tsk.get_future() );
+ worker * w( tss_worker_.get() );
+ if ( w)
+ {
+ tsk.set_wait_callback(
+ bind(
+ ( void ( pool< Channel >::*)( jss::shared_future< R > const&) ) & pool< Channel >::wait_callback_,
+ this,
+ fut) );
+ w->put( detail::callable( move( tsk) ), intr);
+ return task< R >( fut, intr);
+ }
+ else
+ {
+ shared_lock< shared_mutex > lk( mtx_state_);
+ if ( terminated_() )
+ throw task_rejected("pool ist terminated");
+ if ( terminateing_() )
+ throw task_rejected("pool ist terminateing");
+
+ channel_item itm( detail::callable( move( tsk) ), attr, intr);
+ channel_.put( itm);
+ return task< R >( fut, intr);
+ }
+ }
+};
+
+} }
+
+#endif // BOOST_TP_POOL_H
+

Added: sandbox/threadpool/boost/tp/poolsize.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/poolsize.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,29 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_POOLSIZE_H
+#define BOOST_TP_POOLSIZE_H
+
+#include <cstddef>
+
+#include <boost/tp/exceptions.hpp>
+
+namespace boost { namespace tp
+{
+class poolsize
+{
+private:
+ std::size_t value_;
+
+public:
+ explicit poolsize( std::size_t value)
+ : value_( value)
+ { if ( value <= 0) throw invalid_poolsize("core poolsize must be greater than zero"); }
+
+ operator std::size_t () const
+ { return value_; }
+};
+} }
+
+#endif // BOOST_TP_POOLSIZE_H

Added: sandbox/threadpool/boost/tp/priority.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/priority.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,130 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_PRIORITY_H
+#define BOOST_TP_PRIORITY_H
+
+#include <cstddef>
+#include <utility>
+
+#include <boost/assert.hpp>
+#include <boost/function.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/mem_fun.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+
+#include <boost/tp/detail/info.hpp>
+#include <boost/tp/detail/interrupter.hpp>
+
+namespace boost { namespace tp
+{
+template<
+ typename Attr,
+ typename Ord = std::less< Attr >
+>
+struct priority
+{
+ typedef Attr attribute_type;
+ typedef detail::has_priority priority_tag_type;
+
+ template< typename Callable >
+ class impl
+ {
+ private:
+ typedef Attr attribute;
+ typedef Callable callable;
+ typedef Ord ordering;
+
+ public:
+ class item
+ {
+ private:
+ callable ca_;
+ attribute attr_;
+ detail::interrupter intr_;
+
+ public:
+ item(
+ callable const& ca,
+ attribute const& attr,
+ detail::interrupter const& intr)
+ : ca_( ca), attr_( attr), intr_( intr)
+ { BOOST_ASSERT( ! ca_.empty() ); }
+
+ const callable ca() const
+ { return ca_; }
+
+ const attribute attr() const
+ { return attr_; }
+
+ const detail::interrupter intr() const
+ { return intr_; }
+ };
+
+ private:
+ typedef multi_index::multi_index_container<
+ item,
+ multi_index::indexed_by<
+ multi_index::ordered_non_unique<
+ multi_index::const_mem_fun<
+ item,
+ const attribute,
+ & item::attr
+ >,
+ ordering
+ >
+ >
+ > list;
+ typedef typename list::template nth_index< 0 >::type index;
+
+ list lst_;
+ index & idx_;
+
+ public:
+ typedef typename list::iterator iterator;
+ typedef typename list::const_iterator const_iterator;
+
+ impl()
+ :
+ lst_(),
+ idx_( lst_.get< 0 >() )
+ {}
+
+ void push( item const& itm)
+ { idx_.insert( itm); }
+
+ const item pop()
+ {
+ iterator i( lst_.begin() );
+ BOOST_ASSERT( i != lst_.end() );
+ item itm( * i);
+ lst_.erase( i);
+ return itm;
+ }
+
+ std::size_t size() const
+ { return lst_.size(); }
+
+ bool empty() const
+ { return lst_.empty(); }
+
+ void clear()
+ { lst_.clear(); }
+
+ const iterator begin()
+ { return lst_.begin(); }
+
+ const const_iterator begin() const
+ { return lst_.begin(); }
+
+ const iterator end()
+ { return lst_.end(); }
+
+ const const_iterator end() const
+ { return lst_.end(); }
+ };
+};
+} }
+
+#endif // BOOST_TP_PRIORITY_H

Added: sandbox/threadpool/boost/tp/scanns.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/scanns.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,30 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_SCANNS_H
+#define BOOST_TP_SCANNS_H
+
+#include <cstddef>
+
+#include <boost/tp/exceptions.hpp>
+
+namespace boost { namespace tp
+{
+
+class scanns
+{
+private:
+ std::size_t value_;
+
+public:
+ explicit scanns( std::size_t value)
+ : value_( value)
+ { if ( value < 0) throw invalid_scanns("scanns must be greater than or equal to zero"); }
+
+ operator std::size_t () const
+ { return value_; }
+};
+} }
+
+#endif // BOOST_TP_SCANNS_H

Added: sandbox/threadpool/boost/tp/smart.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/smart.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,174 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_SMART_H
+#define BOOST_TP_SMART_H
+
+#include <cstddef>
+
+#include <boost/assert.hpp>
+#include <boost/function.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/mem_fun.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+
+#include <boost/tp/detail/info.hpp>
+#include <boost/tp/detail/interrupter.hpp>
+
+namespace boost { namespace tp
+{
+template<
+ typename Attr,
+ typename Ord,
+ typename Enq,
+ typename Deq
+>
+struct smart
+{
+ typedef Attr attribute_type;
+ typedef detail::has_priority priority_tag_type;
+
+ template< typename Callable >
+ class impl
+ {
+ private:
+ typedef Attr attribute;
+ typedef Callable callable;
+ typedef Deq dequeue_op;
+ typedef Enq enqueue_op;
+ typedef Ord ordering;
+
+ public:
+ class item
+ {
+ private:
+ callable ca_;
+ attribute attr_;
+ detail::interrupter intr_;
+
+ public:
+ item()
+ : ca_(), attr_(), intr_()
+ {}
+
+ item(
+ callable const& ca,
+ attribute const& attr,
+ detail::interrupter const& intr)
+ : ca_( ca), attr_( attr), intr_( intr)
+ { BOOST_ASSERT( ! ca_.empty() ); }
+
+ const callable ca() const
+ { return ca_; }
+
+ const attribute attr() const
+ { return attr_; }
+
+ const detail::interrupter intr() const
+ { return intr_; }
+ };
+
+ private:
+ typedef multi_index::multi_index_container<
+ item,
+ multi_index::indexed_by<
+ multi_index::ordered_non_unique<
+ multi_index::const_mem_fun<
+ item,
+ const attribute,
+ & item::attr
+ >,
+ ordering
+ >
+ >
+ > list;
+ typedef typename list::template nth_index< 0 >::type index;
+
+ list lst_;
+ index & idx_;
+ enqueue_op enq_op_;
+ dequeue_op deq_op_;
+
+ public:
+ typedef typename index::iterator iterator;
+ typedef typename index::const_iterator const_iterator;
+
+ impl(
+ enqueue_op const& enq_op = enqueue_op(),
+ dequeue_op const& deq_op = dequeue_op() )
+ :
+ lst_(),
+ idx_( lst_.get< 0 >() ),
+ enq_op_( enq_op),
+ deq_op_( deq_op)
+ {}
+
+ void push( item const& itm)
+ { enq_op_( idx_, itm); }
+
+ const item pop()
+ {
+ item itm;
+ deq_op_( idx_, itm);
+ return itm;
+ }
+
+ std::size_t size() const
+ { return lst_.size(); }
+
+ bool empty() const
+ { return lst_.empty(); }
+
+ void clear()
+ { lst_.clear(); }
+
+ const iterator begin()
+ { return lst_.begin(); }
+
+ const const_iterator begin() const
+ { return lst_.begin(); }
+
+ const iterator end()
+ { return lst_.end(); }
+
+ const const_iterator end() const
+ { return lst_.end(); }
+ };
+};
+
+struct replace_oldest
+{
+ template<
+ typename Index,
+ typename Item
+ >
+ void operator()( Index & idx, Item const& itm)
+ {
+ typedef typename Index::iterator iterator;
+ iterator i( idx.find( itm.attr() ) );
+ if ( i == idx.end() )
+ idx.insert( itm);
+ else
+ idx.replace( i, itm);
+ }
+};
+
+struct take_oldest
+{
+ template<
+ typename Index,
+ typename Item
+ >
+ void operator()( Index & idx, Item & itm)
+ {
+ typedef typename Index::iterator iterator;
+ iterator i( idx.begin() );
+ BOOST_ASSERT( i != idx.end() );
+ itm = * i;
+ idx.erase( i);
+ }
+};
+} }
+
+#endif // BOOST_TP_SMART_H

Added: sandbox/threadpool/boost/tp/task.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/task.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,126 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_TASK_H
+#define BOOST_TP_TASK_H
+
+#include <boost/future.hpp>
+#include <boost/thread/thread_time.hpp>
+
+#include <boost/tp/detail/interrupter.hpp>
+
+namespace boost { namespace tp
+{
+template< typename R >
+class task
+{
+private:
+ jss::shared_future< R > fut_;
+ detail::interrupter intr_;
+
+public:
+ task(
+ jss::shared_future< R > const& fut,
+ detail::interrupter const& intr)
+ :
+ fut_( fut),
+ intr_( intr)
+ {}
+
+ void interrupt()
+ { intr_.interrupt(); }
+
+ void interrupt_and_wait()
+ { intr_.interrupt_and_wait(); }
+
+ void interrupt_and_wait( system_time const& abs_time)
+ { intr_.interrupt_and_wait( abs_time); }
+
+ template< typename Duration >
+ void interrupt_and_wait( Duration const& rel_time)
+ { intr_.interrupt_and_wait( rel_time); }
+
+ bool interrupt_requested()
+ { return intr_.interrupt_requested(); }
+
+ R get()
+ { return fut_.get(); }
+
+ bool is_ready() const
+ { return fut_.is_ready(); }
+
+ bool has_value() const
+ { return fut_.has_value(); }
+
+ bool has_exception() const
+ { return fut_.has_exception(); }
+
+ void wait() const
+ { fut_.wait(); }
+
+ template< typename Duration >
+ bool timed_wait( Duration const& rel_time) const
+ { return fut_.timed_wait( rel_time); }
+
+ bool timed_wait_until( system_time const& abs_time) const
+ { return fut_.timed_wait_until( abs_time); }
+};
+
+template<>
+class task< void >
+{
+private:
+ jss::shared_future< void > fut_;
+ detail::interrupter intr_;
+
+public:
+ task(
+ jss::shared_future< void > const& fut,
+ detail::interrupter const& intr)
+ :
+ fut_( fut),
+ intr_( intr)
+ {}
+
+ void interrupt()
+ { intr_.interrupt(); }
+
+ void interrupt_and_wait()
+ { intr_.interrupt_and_wait(); }
+
+ void interrupt_and_wait( system_time const& abs_time)
+ { intr_.interrupt_and_wait( abs_time); }
+
+ template< typename Duration >
+ void interrupt_and_wait( Duration const& rel_time)
+ { intr_.interrupt_and_wait( rel_time); }
+
+ bool interrupt_requested()
+ { return intr_.interrupt_requested(); }
+
+ void get()
+ { fut_.get(); }
+
+ bool is_ready() const
+ { return fut_.is_ready(); }
+
+ bool has_value() const
+ { return fut_.has_value(); }
+
+ bool has_exception() const
+ { return fut_.has_exception(); }
+
+ void wait() const
+ { fut_.wait(); }
+
+ template< typename Duration >
+ bool timed_wait( Duration const& rel_time) const
+ { return fut_.timed_wait( rel_time); }
+
+ bool timed_wait_until( system_time const& abs_time) const
+ { return fut_.timed_wait_until( abs_time); }
+};
+} }
+
+#endif // BOOST_TP_TASK_H

Added: sandbox/threadpool/boost/tp/tp.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/tp.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,23 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_TP_H
+#define BOOST_TP_TP_H
+
+#include <boost/tp/detail/bounded_channel.hpp>
+#include <boost/tp/detail/exceptions.hpp>
+#include <boost/tp/detail/fifo.hpp>
+#include <boost/tp/detail/info.hpp>
+#include <boost/tp/detail/lifo.hpp>
+#include <boost/tp/detail/pool.hpp>
+#include <boost/tp/detail/poolsize.hpp>
+#include <boost/tp/detail/priority.hpp>
+#include <boost/tp/detail/scanns.hpp>
+#include <boost/tp/detail/smart.hpp>
+#include <boost/tp/detail/task.hpp>
+#include <boost/tp/detail/unbounded_channel.hpp>
+#include <boost/tp/detail/watermark.hpp>
+
+#endif // BOOST_TP_TP_H
+

Added: sandbox/threadpool/boost/tp/unbounded_channel.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/unbounded_channel.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,294 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_UNBOUNDED_CHANNEL_H
+#define BOOST_TP_UNBOUNDED_CHANNEL_H
+
+#include <cstddef>
+#include <vector>
+
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/function.hpp>
+#include <boost/ref.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+
+#include <boost/tp/detail/callable.hpp>
+#include <boost/tp/detail/interrupter.hpp>
+#include <boost/tp/exceptions.hpp>
+
+namespace boost { namespace tp
+{
+template< typename SchedulingPolicy >
+class unbounded_channel
+{
+private:
+ typedef SchedulingPolicy scheduling_policy;
+ typedef typename scheduling_policy::template impl<
+ detail::callable
+ > queue;
+
+public:
+ typedef typename queue::item item;
+ typedef scheduling_policy scheduler_type;
+
+private:
+ enum channel_state
+ {
+ channel_active,
+ channel_deactive,
+ channel_deactive_now
+ };
+
+ channel_state state_;
+ queue queue_;
+ shared_mutex mtx_;
+ condition not_empty_cond_;
+
+ bool active_() const
+ { return state_ == channel_active; }
+
+ bool deactive_() const
+ { return state_ == channel_deactive; }
+
+ bool deactive_now_() const
+ { return state_ == channel_deactive_now; }
+
+ void activate_()
+ { state_ = channel_active; }
+
+ void clear_()
+ {
+ BOOST_ASSERT( ! active_() );
+ queue_.clear();
+ BOOST_ASSERT( empty_() );
+ }
+
+ void deactivate_()
+ {
+ if ( active_() )
+ {
+ state_ = channel_deactive;
+ not_empty_cond_.notify_all();
+ }
+
+ BOOST_ASSERT( deactive_() );
+ }
+
+ void deactivate_now_()
+ {
+ if ( active_() )
+ {
+ state_ = channel_deactive_now;
+ not_empty_cond_.notify_all();
+ }
+
+ BOOST_ASSERT( deactive_now_() );
+ }
+
+ const std::vector< detail::callable > drain_()
+ {
+ BOOST_ASSERT( deactive_now_() );
+ std::vector< detail::callable > unprocessed;
+ unprocessed.reserve( queue_.size() );
+ BOOST_FOREACH( item itm, queue_)
+ { unprocessed.push_back( itm.ca() ); }
+ clear_();
+ BOOST_ASSERT( empty_() );
+ return unprocessed;
+ }
+
+ bool empty_() const
+ { return queue_.empty(); }
+
+ std::size_t size_() const
+ { return queue_.size(); }
+
+ void put_(
+ item const& itm,
+ unique_lock< shared_mutex > & lk)
+ {
+ queue_.push( itm);
+ not_empty_cond_.notify_one();
+ }
+
+ bool take_(
+ detail::callable & ca,
+ detail::interrupter & intr,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ try
+ {
+ not_empty_cond_.wait(
+ lk,
+ bind(
+ & unbounded_channel::consumers_activate_,
+ this) );
+ }
+ catch ( thread_interrupted const& e)
+ { return false; }
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ item itm( queue_.pop() );
+ ca = itm.ca();
+ intr = itm.intr();
+ return ! ca.empty();
+ }
+
+ template< typename Duration >
+ bool take_(
+ detail::callable & ca,
+ detail::interrupter & intr,
+ Duration const& rel_time,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ try
+ {
+ if ( ! not_empty_cond_.timed_wait(
+ lk,
+ rel_time,
+ bind(
+ & unbounded_channel::consumers_activate_,
+ this) ) )
+ return false;
+ }
+ catch ( thread_interrupted const& e)
+ { return false; }
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ item itm( queue_.pop() );
+ ca = itm.ca();
+ intr = itm.intr();
+ return ! ca.empty();
+ }
+
+ bool try_take_(
+ detail::callable & ca,
+ detail::interrupter & intr)
+ {
+ if ( deactive_now_() || empty_() )
+ return false;
+ item itm( queue_.pop() );
+ ca = itm.ca();
+ intr = itm.intr();
+ return ! ca.empty();
+ }
+
+ bool consumers_activate_() const
+ { return ! active_() || ! empty_(); }
+
+public:
+ unbounded_channel()
+ :
+ state_( channel_active),
+ queue_(),
+ mtx_(),
+ not_empty_cond_()
+ {}
+
+ bool active()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return active_();
+ }
+
+ void activate()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ activate_();
+ }
+
+ void clear()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ clear_();
+ }
+
+ bool deactive()
+ { return ! active(); }
+
+ void deactivate()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ deactivate_();
+ }
+
+ void deactivate_now()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ deactivate_now_();
+ }
+
+ const std::vector< detail::callable > drain()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return drain_();
+ }
+
+ bool empty()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return empty_();
+ }
+
+ bool full()
+ { return false; }
+
+ std::size_t size()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return size_();
+ }
+
+ void put( item const& itm)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( itm, lk);
+ }
+
+ template< typename Duration >
+ void put(
+ item const& itm,
+ Duration const&)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( itm, lk);
+ }
+
+ bool take(
+ detail::callable & ca,
+ detail::interrupter & intr)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, intr, lk);
+ }
+
+ template< typename Duration >
+ bool take(
+ detail::callable & ca,
+ detail::interrupter & intr,
+ Duration const& rel_time)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, intr, rel_time, lk);
+ }
+
+ bool try_take(
+ detail::callable & ca,
+ detail::interrupter & intr)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return try_take_( ca, intr);
+ }
+};
+} }
+
+#endif // BOOST_TP_UNBOUNDED_CHANNEL_H

Added: sandbox/threadpool/boost/tp/watermark.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/watermark.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,49 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_WATER_MARK_H
+#define BOOST_TP_WATER_MARK_H
+
+#include <cstddef>
+
+#include <boost/tp/exceptions.hpp>
+
+namespace boost { namespace tp
+{
+class high_watermark
+{
+private:
+ std::size_t value_;
+
+public:
+ explicit high_watermark( std::size_t value)
+ : value_( value)
+ {
+ if ( value <= 0)
+ throw invalid_watermark("high watermark must be greater than zero");
+ }
+
+ operator std::size_t () const
+ { return value_; }
+};
+
+class low_watermark
+{
+private:
+ std::size_t value_;
+
+public:
+ explicit low_watermark( std::size_t value)
+ : value_( value)
+ {
+ if ( value < 0)
+ throw invalid_watermark("low watermark must be greater than or equal to zero");
+ }
+
+ operator std::size_t () const
+ { return value_; }
+};
+} }
+
+#endif // BOOST_TP_WATER_MARK_H

Added: sandbox/threadpool/libs/tp/doc/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/Jamfile.v2 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,12 @@
+# Boost.ThreadPool Library Documentation Jamfile
+
+# Copyright (C) 2008 Oliver Kowalke
+
+# Use, modification and distribution is subject to 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)
+
+using quickbook ;
+
+xml threadpool : threadpool.qbk ;
+boostbook standalone : threadpool ;

Added: sandbox/threadpool/libs/tp/doc/channel.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/channel.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,30 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[section:channel Channel]
+The channel synchronizes the access between application threads (producer threads) submitting __actions__ to the pool and __worker_threads__ (consumer threads). The scheduling of __actions__ queued into the channel depends on channels the scheduling policy.
+If the channel becomes empty all __worker_threads__ are set to sleep until a new __action__ is put in.
+
+[heading bounded channel]
+
+ template< typename SchedulingPolicy > class bounded_channel
+
+The number of pending __actions__ is limited in order to prevent resource exhaustion. For this purpose a high and low watermark has to be passed at construction.
+`boost::tp::high_watermark` sets the maximum of pending tasks. If this limited is reached all threads which submit a tasks will be set to sleep (blocked).
+`boost::tp::low_watermark` sets the threshold when blocked threads get woken up.
+If __hwm__ is equal to __lwm__ everytime a sleeping producer thread will be woken up and puts
+its task if one worker thread has taken a task from the channel.
+If __lwm__ is less than __hwm__ all sleeping producer threads will be woken up if
+the amount of pending tasks reaches __lwm__.
+
+[heading unbounded channel]
+
+ template< typename SchedulingPolicy > class unbounded_channel
+
+An unlimited number of __actions__ can be queued into this channel. The insertion of __actions__ will never block. If the channel becomes empty __worker_threads__ will be set to sleep until new __actions__ are inserted into the channel.
+
+[endsect]

Added: sandbox/threadpool/libs/tp/doc/exceptions_ref.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/exceptions_ref.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,126 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[section:invalid_poolsize Class `invalid_poolsize`]
+
+ #include <boost/tp/exceptions.hpp>
+
+ class invalid_poolsize
+ : public std::invalid_argument
+ {
+ public:
+ invalid_poolsize( std::string const& msg);
+ };
+
+[section:constructor Constructor]
+
+ invalid_poolsize( std::string const& msg);
+
+[variablelist
+[[Effects:] [Constructs a `boost::tp::invalid_poolsize` instance.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[endsect]
+
+
+[section:invalid_scanns Class `invalid_scanns`]
+
+ #include <boost/tp/exceptions.hpp>
+
+ class invalid_scanns
+ : public std::invalid_argument
+ {
+ public:
+ invalid_scanns( std::string const& msg);
+ };
+
+[section:constructor Constructor]
+
+ invalid_scanns( std::string const& msg);
+
+[variablelist
+[[Effects:] [Constructs a `boost::tp::invalid_scanns` instance.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[endsect]
+
+
+[section:invalid_timeduration Class `invalid_timeduration`]
+
+ #include <boost/tp/exceptions.hpp>
+
+ class invalid_timeduration
+ : public std::invalid_argument
+ {
+ public:
+ invalid_timeduration( std::string const& msg);
+ };
+
+[section:constructor Constructor]
+
+ invalid_timeduration( std::string const& msg);
+
+[variablelist
+[[Effects:] [Constructs a `boost::tp::invalid_timeduration` instance.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[endsect]
+
+
+[section:invalid_watermark Class `invalid_watermark`]
+
+ #include <boost/tp/exceptions.hpp>
+
+ class invalid_watermark
+ : public std::invalid_argument
+ {
+ public:
+ invalid_watermark( std::string const& msg);
+ };
+
+[section:constructor Constructor]
+
+ invalid_watermark( std::string const& msg);
+
+[variablelist
+[[Effects:] [Constructs a `boost::tp::invalid_watermark` instance.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[endsect]
+
+
+[section:task_rejected Class `task_rejected`]
+
+ #include <boost/tp/exceptions.hpp>
+
+ class task_rejected
+ : public std::runtime_error
+ {
+ public:
+ task_rejected( std::string const& msg);
+ };
+
+[section:constructor Constructor]
+
+ task_rejected( std::string const& msg);
+
+[variablelist
+[[Effects:] [Constructs a `boost::tp::task_rejected` instance.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[endsect]
+

Added: sandbox/threadpool/libs/tp/doc/forkjoin.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/forkjoin.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,83 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[section:forkjoin Fork/Join]
+Fork/Join algorithms are recursive divide-and-conquer algorithms which repeatedly splitt __sub_actions__ until they become small enough to solve using simple, short sequential methods, so that they run in parallel on multiple cores.
+
+The fork operation creates a new __sub_action__ (which can run in parallel) in the pool. The current __actions__ is not proceeded in the join operation until the forked __sub_actions__ have completed. In the meantime the __worker_thread__ executes other __actions__ from its local __worker_queue__.
+
+ // defines the threadpool type
+ typedef boost::tp::pool<
+ boost::tp::unbounded_channel< boost::tp::fifo >
+ > pool_type;
+
+ class fibo
+ {
+ private:
+ pool_type & pool_;
+ int cutoff_;
+
+ int seq_( int n)
+ {
+ if ( n <= 1) return n;
+ else return seq_( n - 2) + seq_( n - 1);
+ }
+
+ int par_( int n)
+ {
+ if ( n <= cutoff_) return seq_( n);
+ else
+ {
+ // fork a new sub-action t1 in pool
+ boost::tp::task< int > t1(
+ pool_.submit(
+ boost::bind(
+ & fibo::par_,
+ boost::ref( * this),
+ n - 1) ) );
+
+ // fork a new sub-action t2 in pool
+ boost::tp::task< int > t1(
+ pool_.submit(
+ boost::bind(
+ & fibo::par_,
+ boost::ref( * this),
+ n - 2) ) );
+
+ // joining the result of sub-action t1 and t2
+ return t1.get() + t2.get();
+ }
+ }
+ public:
+ fibo( pool_type & pool, int cutoff)
+ : pool_( pool), cutoff_( cutoff)
+ {}
+
+ int execute( int n)
+ {
+ int result( par_( n) );
+ return result;
+ }
+ };
+
+ // creates a threadpool with two worker-threads
+ pool_type pool( boost::tp::poolsize( 2) );
+
+ fibo fib( pool, 1);
+
+ // submit an action
+ // which calculates the fibonacci number of 10
+ boost::tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ & fibo::execute,
+ boost::ref( fib),
+ 10) ) );
+
+ std::cout << t.get() << std::endl; // prints 55
+
+[endsect]

Added: sandbox/threadpool/libs/tp/doc/introduction.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/introduction.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,34 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[section Introduction]
+__boost_threadpool__ is designed for effectively utilize the available hardware and provide a way for efficient asynchronous processing of independent time consuming operations (__actions__) in the same process.
+A __threadpool__ contains a number of __worker_threads__ to perform __actions__ in parallel, which are usually managed by a scheduler. If a __worker_thread__ completes its __action__, it will take the next __action__ from the scheduler until all __actions__ have been completed. The __worker_thread__ then sleeps until there are new __actions__ available.
+Using a pool of __worker_threads__ over creating a new thread for each __action__ may result in better performance and better system stability because the overhead for thread creation and destruction is negated.
+
+__boost_threadpool__ uses a __work_stealing__ algorithm and supports __fork_join__ parallelism (recursively splitting of __actions__ into sub-actions that are solved in parallel, waiting for them to complete, and then joining results).
+
+In order to use the classes and functions described here, you can either include the specific headers specified by the descriptions of each class or function, or include the master library header:
+
+ #include <boost/tp/tp.hpp>
+
+which includes all the other headers in turn.
+
+[note
+__boost_threadpool__ uses the futures library, N2561 C++0x proposal, from Anthony Williams ([@http://www.justsoftwaresolutions.co.uk/threading/updated-implementation-of-c++-futures-3.html]) as an implementation detail until boost has
+an official future library.]
+
+[heading Tested Platforms]
+__boost_threadpool__ has been tested on the following compilers/platforms:
+
+* FreeBSD 7.0 (amd64), GCC 4.2.1
+* Linux 2.6.26 (amd64), GCC 4.3.1
+* Linux 2.6.23.9 (i386), GCC 4.2.4
+* OpenSolaris/Nexenta 1.0.1 (amd64), GCC 4.2.1
+* Windows XP Professional (i386), MSVC 9.0
+
+[endsect]

Added: sandbox/threadpool/libs/tp/doc/meta_ref.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/meta_ref.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,36 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[section:has_priority Meta function `has_priority`]
+
+ #include <boost/tp/info.hpp>
+
+ template< typename Pool >
+ struct has_priority
+ :
+ public mpl::bool_<
+ is_same<
+ detail::has_priority,
+ typename Pool::scheduler_type::priority_tag_type
+ >::value
+ >
+ {};
+
+[endsect]
+
+
+[section:priority_type Meta function `priority_type`]
+
+ #include <boost/tp/info.hpp>
+
+ template< typename Pool >
+ struct priority_type
+ {
+ typedef typename Pool::scheduler_type::attribute_type type;
+ };
+
+[endsect]

Added: sandbox/threadpool/libs/tp/doc/pool.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/pool.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,114 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[section:pool Pool]
+The pool manages internaly __worker_threads__ and submitted __actions__ are stored in a __channel__ (__global_queue__) for processing by the __worker_threads__ (using a __work_stealing__ algorithm). Each submitted __action__ gets associated with a __task__ object that will be returned. The __task__ object acts as a proxy for a result that is initially not known and gets evaluated later by a __worker_thread__.
+
+[heading Work-Stealing]
+Traditional thread poola do not scale because they use a single global queue protected by a global lock. The frequency at which __worker_threads__ aquire the global lock becomes a limiting factor for the throughput if:
+
+* the __actions__ become smaller
+* more processors are added
+
+A work-stealing algorithm can be used to solve this problem. It uses a special kind of queue which has two ends, and allows lock-free pushes and pops from the ['private end] (accessed by the __worker_thread__ owning the queue), but requires synchronization from the ['public end] (accessed by the other __worker_threads__). Synchronization is necessary when the queue is sufficiently small that private and public operations could conflict.
+
+The pool contains one global queue (__bounded_channel__ or __unbounded_channel__) protected by a global lock and each __worker_thread__ has its own private worker queue. If work is enqueued by a __worker_thread__ the __action__ is stored in the worker queue. If the work is enqueued by a application thread it goes into the global queue. When __worker_threads__ are looking for work, they have following search order:
+
+* look into the private worker queue - __actions__ can be dequeued without locks
+* look in the global queue - locks are used for synchronization
+* check other worker queues ('stealing' __actions__ from private worker queues of other __worker_threads__) - requires locks
+
+For a lot of recursively queued __actions__, the use of a worker queue per thread substantially reduces the synchronization necessary to complete the work. There are also fewer cache effects due to sharing of the global queue information.
+
+Operations on the private worker queue are executed in LIFO order and operations on worker queues of other __worker_threads__ in FIFO order (steals).
+
+* There are chances that memory is still hot in the cache, if the __actions__ are pushed in LIFO order into the private worker queue.
+* If a __worker_thread__ steals work in FIFO order, increases the chances that a larger 'chunk' of work will be stolen (the need for other steals will be possibly reduced). Because the __actions__ are stored in LIFO order, the oldest items are closer to the ['public end] of the queue (forming a tree). Stealing such an older __action__ also steals a (probably) larger subtree of __actions__ unfolded if the stolen work item get executed.
+
+[note __Actions__ submitted by a __worker_thread__ are stored into its private worker queue in LIFO order, thatswhy priorities and timeouts specified at the submit-function get ignored.]
+
+[important Because of the work-stealing algorithm the execution order of __actions__ may be not strict as in the global queue.]
+
+
+[heading Creation]
+The first template argument specifies the channel type and the scheduling policy.
+
+ boost::tp::pool<
+ boost::tp::unbounded_channel< boost::tp::fifo >
+ > pool(
+ boost::tp::poolsize( 6),
+ boost::posix_time::posix_time::milliseconds( 50),
+ boost::tp::scanns(10) );
+
+In the example above a __threadpool__ is created with a __unbounded_channel__, scheduling __actions__ in ['FIFO] order. The pool contains six __worker_threads__ going to sleep for 50 millisec after 10 iterations without geting an __action__ from the __global_queue__, from its local __worker_queue__ or local queues of other __worker_threads__.
+
+ boost::tp::pool<
+ boost::tp::bounded_channel< boost::tp::priority < int > >
+ > pool(
+ boost::tp::poolsize( 10),
+ boost::tp::high_watermark( 10),
+ boost::tp::low_watermark( 5) );
+
+This pool uses a __bounded_channel__ which schedules __actions__ by integer atrributes. A maximum of 10 __actions__ can be queued in the __global_queue__ without blocking the inserting thread.
+
+
+[heading Shutdown]
+If `boost::tp::pool< Channel >::shutdown()` is called - the the status of the pool is set to ['terminating] and all __worker_threads__ are joined. No futher __actions__ can be submitted by application threads. After all pending __actions__ are processed and all __worker_threads__ are joined, the pool is set to status ['terminated].
+
+[note The deconstructor calls `boost::tp::pool< Channel >::shutdown()` if the pool was not shutdown yet.]
+
+ boost::tp::pool<
+ boost::tp::unbounded_channel< boost::tp::fifo >
+ > pool( boost::tp::poolsize( 1) );
+
+ boost::tp::task< int > t1(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ boost::tp::task< int > t2(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+
+ pool.shutdown();
+
+ std::cout << t1.get() << std::endl; // 55
+ std::cout << t2.get() << std::endl; // 55
+
+[heading Shutdown immediatly]
+The function `boost::tp::pool< Channel >::shutdown_now()` sets the pool status to ['terminating] interrupts and then joins all __worker_threads__. After the __worker_threads__ are joined the status of the pool is set to ['terminated] and all pending (unprocessed) __actions__ will be returned.
+
+[important Pending __actions__ in the local __worker_queues__ are not returned if `boost::tp::pool< Channel >::shutdown_now()` was called.]
+
+
+[heading Meta functions]
+If the __threadpool__ supports priorities `boost::tp::has_priority< pool_type >` evaluates to `true`. The priority type is determined by `boost::tp::priority_type< pool_type >`.
+
+ typedef boost::tp::pool<
+ boost::tp::unbounded_channel< boost::tp::priority< int > >
+ > pool_type;
+
+ std::cout << std::boolalpha << boost::tp::has_priority< pool_type >::value << std::endl;
+ std::cout << typeid( boost::tp::priority_type< pool_type >::type).name() << std::endl;
+
+The support of fibers can be tested with meta-function `boost::tp::has_fibers< pool_type >`.
+
+ std::cout << std::boolalpha << boost::tp::has_fibers< pool_type >::value << std::endl;
+
+[heading Processor binding]
+For some applications it is convenient to bind the worker threads of the pool to processors of the system. For this purpose BOOST_BIND_WORKER_TO_PROCESSORS must be defined. Without the poolsize in the construtor the __threadpool__ will contain as many
+__worker_threads__ as processors (== __hardware_concurrency__) are available and each __worker_thread__ is bound to one processor.
+
+ boost::tp::pool<
+ boost::tp::unbounded_channel< boost::tp::fifo >
+ > pool;
+
+The code above will create a pool with two __worker_threads__ on a dual core system (each bound to one core).
+
+[endsect]

Added: sandbox/threadpool/libs/tp/doc/pool_ref.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/pool_ref.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,349 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[section:pool Class template `pool`]
+
+ #include <boost/tp/pool.hpp>
+
+ template< typename Channel >
+ class pool
+ : private noncopyable
+ {
+ public:
+ explicit pool(
+ poolsize const& psize,
+ posix_time::time_duration const& asleep = posix_time::microseconds( 10),
+ scanns const& scns = scanns( 20) );
+
+ explicit pool(
+ poolsize const& psize,
+ high_watermark const& hwm,
+ low_watermark const& lwm,
+ posix_time::time_duration const& asleep = posix_time::milliseconds( 100),
+ scanns const& scns = scanns( 20) );
+
+
+ explicit pool(
+ posix_time::time_duration const& asleep = posix_time::microseconds( 10),
+ scanns const& scns = scanns( 20) );
+
+ explicit pool(
+ high_watermark const& hwm,
+ low_watermark const& lwm,
+ posix_time::time_duration const& asleep = posix_time::milliseconds( 100),
+ scanns const& scns = scanns( 20) );
+
+ ~pool();
+
+ std::size_t size();
+ std::size_t active();
+ std::size_t idle();
+
+ void shutdown();
+ const std::vector< callable > shutdown_now();
+
+ bool terminated();
+ bool terminateing();
+ void clear();
+ bool empty();
+ std::size_t pending();
+
+ const std::size_t upper_bound();
+ void upper_bound( high_watermark const& hwm);
+ const std::size_t lower_bound();
+ void lower_bound( low_watermark const& lwm);
+
+ template< typename Act >
+ task< typename result_of< Act() >::type > submit( Act const& act);
+
+ template< typename Act, typename Attr >
+ task< typename result_of< Act() >::type > submit(
+ Act const& act,
+ Attr const& attr);
+
+ template< typename Act >
+ task< typename result_of< Act() >::type > timed_submit(
+ Act const& act,
+ system_time const& abs_time);
+
+ template< typename Act, typename Attr >
+ task< typename result_of< Act() >::type > timed_submit(
+ Act const& act,
+ Attr const& attr,
+ system_time const& abs_time);
+ };
+
+
+[section:constructor_unbounded_channel_hw Constructor (unbounded channel)]
+
+ explicit pool(
+ posix_time::time_duration const& asleep = posix_time::microseconds( 10),
+ scanns const& scns = scanns( 20) );
+
+[variablelist
+[[Preconditions:] [Operating system provides functionality for processor pining.]]
+[[Effects:] [Constructs a `boost::tp::pool< Channel >` instance. For each processor a worker-thread is created and each worker-thread is pined exactly to one processor.]]
+[[Throws:] [`boost::tp::invalid_scanns`, `boost::tp::invalid_timeduration`]]
+[[Notes:] [Constructor has to be called if a __unbounded_channel__ is used.]]
+]
+[endsect]
+
+
+[section:constructor_unbounded_channel Constructor (unbounded channel)]
+
+ explicit pool(
+ poolsize const& psize,
+ posix_time::time_duration const& asleep = posix_time::microseconds( 10),
+ scanns const& scns = scanns( 20) );
+
+[variablelist
+[[Effects:] [Constructs a `boost::tp::pool< Channel >` instance. Pool contains psize worker-threads.]]
+[[Throws:] [`boost::tp::invalid_scanns`, `boost::tp::invalid_timeduration`]]
+[[Notes:] [Constructor has to be called if a __unbounded_channel__ is used.]]
+]
+[endsect]
+
+
+[section:constructor_bounded_channel_hw Constructor (bounded channel)]
+
+ explicit pool(
+ high_watermark const& hwm,
+ low_watermark const& lwm,
+ posix_time::time_duration const& asleep = posix_time::milliseconds( 100),
+ scanns const& scns = scanns( 20) );
+
+[variablelist
+[[Preconditions:] [Operating system provides functionality for processor pining.]]
+[[Effects:] [Constructs a `boost::tp::pool< Channel >` instance. For each processor a worker-thread is created and each worker-thread is pined exactly to one processor.]]
+[[Throws:] [`boost::tp::invalid_scanns`, `boost::tp::invalid_timeduration`, `boost::tp::invalid_watermark`]]
+[[Notes:] [Constructor has to be called if a __bounded_channel__ is used.]]
+]
+[endsect]
+
+
+[section:constructor_bounded_channel Constructor (bounded channel)]
+
+ explicit pool(
+ poolsize const& psize,
+ high_watermark const& hwm,
+ low_watermark const& lwm,
+ posix_time::time_duration const& asleep = posix_time::milliseconds( 100),
+ scanns const& scns = scanns( 20) );
+
+[variablelist
+[[Effects:] [Constructs a `boost::tp::pool< Channel >` instance. Pool contains psize worker-threads.]]
+[[Throws:] [`boost::tp::invalid_scanns`, `boost::tp::invalid_timeduration`, `boost::tp::invalid_watermark`]]
+[[Notes:] [Constructor has to be called if a __bounded_channel__ is used.]]
+]
+[endsect]
+
+
+[section:destructor Destructor]
+
+ ~pool();
+
+[variablelist
+[[Effects:] [Calls `boost::tp::pool< Channel >::shutdown()` if not yet called.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+
+[section:size Member function `size()`]
+
+ std::size_t size();
+
+[variablelist
+[[Effects:] [Returns how many worker threads are running in the pool.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+
+[section:active Member function `active()`]
+
+ std::size_t active();
+
+[variablelist
+[[Effects:] [Returns how many worker threads are active (executing an __action__).]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+
+[section:idle Member function `idle()`]
+
+ std::size_t idle();
+
+[variablelist
+[[Effects:] [Returns how many worker threads are idle (not executing an __action__).]]
+[[Throws:] [Nothing]]
+[[Notes:] [The value is the difference of `size()` and `active()`]]
+]
+[endsect]
+
+
+[section:shutdown Member function `shutdown()`]
+
+ void shutdown();
+
+[variablelist
+[[Effects:] [Changes the pool state to ['terminating], deactivates the channel and joins all worker threads. The status of the pool is assigned to ['terminated] at the end.]]
+[[Throws:] [Nothing]]
+[[Notes:] [All pending __actions__ are processed.]]
+]
+[endsect]
+
+
+[section:shutdown_now Member function `shutdown_now()`]
+
+ const std::vector< callable > shutdown_now();
+
+[variablelist
+[[Effects:] [Changes the pool state to ['terminating], deactivates the channel, send interruption request to all worker threads and joins them. The status of the pool is assigned to ['terminated] at the end.]]
+[[Throws:] [Nothing]]
+[[Notes:] [Pending __actions__ are not processed but returned.]]
+]
+[endsect]
+
+
+[section:terminated Member function `terminated()`]
+
+ bool terminated();
+
+[variablelist
+[[Effects:] [Queries if the pool is in the terminated state (pool is shutdown).]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+
+[section:terminateing Member function `terminateing()`]
+
+ bool terminateing();
+
+[variablelist
+[[Effects:] [Queries if the pool is in the terminating state (tries to shutdown the pool).]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+
+[section:clear Member function `clear()`]
+
+ void clear();
+
+[variablelist
+[[Effects:] [Removes all pending __actions__ from the __channel__.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+
+[section:empty Member function `empty()`]
+
+ bool empty();
+
+[variablelist
+[[Effects:] [Queries if the __channel__ is empty.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+
+[section:pending Member function `pending()`]
+
+ std::size_t pending();
+
+[variablelist
+[[Effects:] [Queries how many __actions__ are pending in the __channel__.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+
+[section:get_upper_bound Member function `upper_bound()`]
+
+ std::size_t upper_bound();
+
+[variablelist
+[[Preconditions:] [Channel is of type __bounded_channel__.]]
+[[Effects:] [Returns the upper bound of the __bounded_channel__.]]
+[[Throws:] [Nothing]]
+[[Notes:] [Can only be used if a __bounded_channel__ is used.]]
+]
+[endsect]
+
+
+[section:set_upper_bound Member function `upper_bound( high_watermark const& hwm)`]
+
+ void upper_bound( high_watermark const& hwm);
+
+[variablelist
+[[Preconditions:] [Channel is of type __bounded_channel__.]]
+[[Effects:] [Sets the upper bound of the __bounded_channel__.]]
+[[Postconditions:] [`this->upper_bound() == hwm`.]]
+[[Throws:] [`boost::tp::invalid_watermark`]]
+[[Notes:] [Can only be used if a __bounded_channel__ is used.]]
+]
+[endsect]
+
+
+[section:get_lower_bound Member function `lower_bound()`]
+
+ std::size_t lower_bound();
+
+[variablelist
+[[Preconditions:] [Channel is of type __bounded_channel__.]]
+[[Effects:] [Returns the lower bound of the __bounded_channel__.]]
+[[Throws:] [Nothing]]
+[[Notes:] [Can only be used if a __bounded_channel__ is used.]]
+]
+[endsect]
+
+
+[section:set_lower_bound Member function `lower_bound( low_watermark const& lwm)`]
+
+ void lower_bound( low_watermark const& lwm);
+
+[variablelist
+[[Preconditions:] [Channel is of type __bounded_channel__.]]
+[[Effects:] [Sets the lower bound of the __bounded_channel__.]]
+[[Postconditions:] [`this->lower_bound() == lwm`.]]
+[[Throws:] [`boost::tp::invalid_watermark`]]
+[[Notes:] [Can only be used if a __bounded_channel__ is used.]]
+]
+[endsect]
+
+
+[section:submit Member function `submit( Act const& act)`]
+
+ template< typename Act >
+ task< typename result_of< Act() >::type > submit( Act const& act);
+
+[variablelist
+[[Preconditions:] [has_priority< pool >::value == false && ! ( pool.terminating() || pool.terminated() )]]
+[[Effects:] [Submits an __action__ to the pool and returns a __task__ object.]]
+[[Throws:] [`boost::tp::task_rejected`]]
+]
+[endsect]
+
+
+[section:submit_attr Member function `submit( Act const& act, Attr const& attr)`]
+
+ template< typename Act, typename Attr >
+ task< typename result_of< Act() >::type > submit( Act const& act, Attr const& attr);
+
+[variablelist
+[[Preconditions:] [has_priority< pool >::value == true && ! ( pool.terminating() || pool.terminated() )]]
+[[Effects:] [Submits an __action__ to the pool and returns a __task__ object. __Action__ is scheduled by the attribute.]]
+[[Throws:] [`boost::tp::task_rejected`]]
+]
+[endsect]
+
+
+[endsect]

Added: sandbox/threadpool/libs/tp/doc/poolsize_ref.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/poolsize_ref.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,43 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[section:poolsize Class `poolsize`]
+
+ #include <boost/tp/poolsize.hpp>
+
+ class poolsize
+ {
+ public:
+ explicit poolsize( std::size_t value);
+
+ operator std::size_t () const;
+ };
+
+[section:constructor Constructor]
+
+ explicit poolsize( std::size_t value);
+
+[variablelist
+[[Preconditions:][value > 0]]
+[[Effects:] [Constructs a `boost::tp::poolsize` instance.]]
+[[Postconditions:][operator std::size_t () > 0]]
+[[Throws:] [`boost::tp::invalid_poolsize`]]
+]
+[endsect]
+
+
+[section:operator Member function `operator std::size_t()`]
+
+ operator std::size_t () const;
+
+[variablelist
+[[Effects:] [Returns pool size.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[endsect]

Added: sandbox/threadpool/libs/tp/doc/reference.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/reference.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,18 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[section:reference Reference]
+
+[include pool_ref.qbk]
+[include task_ref.qbk]
+[include poolsize_ref.qbk]
+[include scanns_ref.qbk]
+[include watermark_ref.qbk]
+[include exceptions_ref.qbk]
+[include meta_ref.qbk]
+
+[endsect]

Added: sandbox/threadpool/libs/tp/doc/scanns_ref.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/scanns_ref.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,42 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[section:scanns Class `scanns`]
+
+ #include <boost/tp/scanns.hpp>
+
+ class scanns
+ {
+ public:
+ explicit scanns( std::size_t value);
+
+ operator std::size_t () const;
+ };
+
+[section:constructor Constructor]
+
+ explicit scanns( std::size_t value);
+
+[variablelist
+[[Preconditions:][value >= 0]]
+[[Effects:] [Constructs a `boost::tp::scanns` instance.]]
+[[Postconditions:][operator std::size_t () >= 0]]
+[[Throws:] [`boost::tp::invalid_scanns`]]
+]
+[endsect]
+
+[section:operator Member function `operator std::size_t()`]
+
+ operator std::size_t () const;
+
+[variablelist
+[[Effects:] [Returns scanns size.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[endsect]

Added: sandbox/threadpool/libs/tp/doc/scheduling.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/scheduling.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,84 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[section:scheduling Scheduling]
+The scheduling policy determines how __actions__ are scheduled inside the __channel__.
+
+[heading fifo]
+
+ struct fifo
+
+First inserted pending __action__ get taken first.
+
+
+[heading lifo]
+
+ struct lifo
+
+Last inserted pending __action__ get taken first.
+
+
+[heading priority]
+
+ template< typename Attr, typename Ord = std::less< Attr > > struct priority
+
+Each pending task is associated with a priority attribute which is used for ordering __actions__.
+
+
+[heading smart]
+
+ template< typename Attr, typename Ord, typename Enq, typename Deq > struct smart
+
+Each pending __actions__ is associated with an attribute. The scheduler gets an put- and take-policy
+as template arguments. The corresponding policy get applied for each insertion and removal.
+
+__boost_threadpool__ provides ['boost::tp::replace_oldest] as put policy and ['boost::tp::take_oldest] as take
+policy. Both policies allow the replacement of old __actions__ in the scheduler by new ones.
+
+ // creates a pool with unbounded channel
+ // tasks are processed depending on the associated attributed
+ // oldest tasks with the same attributed pending in the channel
+ // will be replaced by the new task
+ // this example would execute add( 1, 2) and add( 5, 6)
+ // add( 2, 3) is removed (if pending when add( 5, 6) is submitted)
+ boost::tp::pool<
+ boost::tp::unbounded_channel<
+ boost::tp::smart<
+ int,
+ std::less< int >,
+ boost::tp::replace_oldest,
+ boost::tp::take_oldest
+ >
+ >
+ > pool( boost::tp::poolsize( 1) );
+
+ pool.submit(
+ boost::bind(
+ add_fn,
+ 1,
+ 2),
+ 0);
+
+ // replaced by later task with same attribute
+ // if still pending in pool
+ pool.submit(
+ boost::bind(
+ add_fn,
+ 3,
+ 4),
+ 1);
+
+ // will replace previous pending action
+ pool.submit(
+ boost::bind(
+ add_fn,
+ 5,
+ 6),
+ 1);
+
+
+[endsect]

Added: sandbox/threadpool/libs/tp/doc/stacksize_ref.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/stacksize_ref.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,42 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[section:stacksize Class `stacksize`]
+
+ #include <boost/tp/stacksize.hpp>
+
+ class stacksize
+ {
+ public:
+ explicit stacksize( std::size_t value);
+
+ operator std::size_t () const;
+ };
+
+[section:constructor Constructor]
+
+ explicit stacksize( std::size_t value);
+
+[variablelist
+[[Preconditions:][value > 0]]
+[[Effects:] [Constructs a `boost::tp::stacksize` instance.]]
+[[Postconditions:][operator std::size_t () > 0]]
+[[Throws:] [`boost::tp::invalid_stacksize`]]
+]
+[endsect]
+
+[section:operator Member function `operator std::size_t()`]
+
+ operator std::size_t () const;
+
+[variablelist
+[[Effects:] [Returns stack size.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[endsect]

Added: sandbox/threadpool/libs/tp/doc/task.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/task.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,123 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[section:task Task]
+For each submitted __action__ a new task object will be created and returned by the pool.
+The __task__ object acts as a proxy for a result that is initially not known and gets evaluated later by a __worker_thread__. It transports the result (value or exception) of the __action__ back to the caller.
+
+ boost::tp::pool<
+ boost::tp::unbounded_channel< boost::tp::fifo >
+ > pool( boost::tp::poolsize( 10) );
+
+ // task calculates fibonacci(10)
+ // scheduled in unbounded channel with FIFO ordering
+ boost::tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+
+ std::cout << t.get() << std::endl; // 55
+
+
+[heading Interruption]
+The returned __task__ object provides the possiblity to interrupt an __action__ if it is cooperative.
+An __action__ is known as cooperative if it includes interruption points in its code:
+
+* `boost::thread::join()`
+* `boost::thread::timed_join()`
+* `boost::condition_variable::wait()`
+* `boost::condition_variable::timed_wait()`
+* `boost::condition_variable_any::wait()`
+* `boost::condition_variable_any::timed_wait()`
+* `boost::thread::sleep()`
+* `boost::this_thread::sleep()`
+* `boost::this_thread::interruption_point()`
+
+[important Interruption must not be disabled for the __worker_thread__ (class ['boost::this_thread::disable_interruption]).]
+
+The __action__ will be interrupted even if it is pending (interruption is remembered).
+A ['boost::thread_interrupted] exception will be thrown by `boost::tp::task< T >::get()` if the __action__ was interrupted.
+``
+ boost::tp::pool<
+ boost::tp::unbounded_channel< boost::tp::fifo >
+ > pool( boost::tp::poolsize( 10) );
+
+ // submit a long running task
+ boost::tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ long_running_fn) ) );
+
+ // interrupt task
+ t.interrupt();
+
+ // throws boost::thread_interrupted exception
+ std::cout << t.get() << std::endl;
+``
+
+ boost::tp::pool<
+ boost::tp::unbounded_channel< boost::tp::fifo >
+ > pool( boost::tp::poolsize( 10) );
+
+ // submit a long running task
+ boost::tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ long_running_fn) ) );
+
+ // interrupt task and wait for its termination
+ t.interrupt_and_wait();
+
+ // throws boost::thread_interrupted exception
+ std::cout << t.get() << std::endl;
+
+
+[heading Exceptions in tasks]
+Exceptions thrown inside an __action__ are transported by the associated task object.
+Exceptions rethrown by type:
+
+* `std::bad_alloc`
+* `std::bad_cast`
+* `std::bad_exception`
+* `std::bad_typeid`
+* `std::domain_error`
+* `std::invalid_argument`
+* `std::ios_base::failure`
+* `std::length_error`
+* `std::logic_error`
+* `std::out_of_range`
+* `std::overflow_error`
+* `std::range_error`
+* `std::runtime_error`
+* `std::underflow_error`
+* `boost::broken_promise`
+* `boost::future_already_set`
+* `boost::future_cancel`
+* `boost::invalid_thread_argument`
+* `boost::lock_error`
+* `boost::thread_exception`
+* `boost::thread_interrupted`
+* `boost::thread_permission_error`
+* `boost::thread_resource_error`
+* `boost::unsupported_thread_option`
+
+Exceptions derived from `std::exception` will be rethrown as `std::runtime_error` in all other cases a `std::bad_exception` is thrown.
+
+ boost::tp::pool<
+ boost::tp::unbounded_channel< boost::tp::fifo >
+ > pool( boost::tp::poolsize( 10) );
+
+ // task will throw an exception derived from std::exception
+ boost::tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ throwing_fn) ) );
+
+ std::cout << t.get() << std::endl; // will rethrow an std::runtime_error
+
+[endsect]

Added: sandbox/threadpool/libs/tp/doc/task_ref.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/task_ref.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,162 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[section:task Class template `task`]
+
+ #include <boost/tp/task.hpp>
+
+ template< typename R >
+ class task
+ {
+ public:
+ template< typename Pool >
+ task(
+ Pool * pool,
+ future< R > const& fut,
+ detail::interrupter const& intr);
+
+ void interrupt();
+ void interrupt_and_wait();
+ void interrupt_and_wait( system_time const& abs_time);
+ template< typename Duration >
+ void interrupt_and_wait( Duration const& rel_time);
+ bool interrupt_requested();
+
+ R get() const;
+
+ bool is_ready() const;
+ bool has_value() const;
+ bool has_exception() const;
+
+ void wait() const;
+ template< typename Duration >
+ bool timed_wait( Duration const& rel_time) const;
+ bool timed_wait_until( system_time const& abs_time) const;
+ };
+
+[section:constructor Constructor]
+
+ template< typename Pool >
+ task(
+ Pool * pool,
+ future< R > const& fut,
+ detail::interrupter const& intr);
+
+[variablelist
+[[Effects:] [Constructs a `boost::tp::task< R >` instance.]]
+[[Throws:] [Nothing]]
+[[Notes:] [task objects should only be constructed by the pool.]]
+]
+[endsect]
+
+
+[section:interrupt Member function `interrupt()`]
+
+ void interrupt();
+
+[variablelist
+[[Effects:] [Associated __action__ will be interrupted the next time it enters a __interruption_point__ if interruption is not disabled. The function returns immediatly.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+
+[section:interrupt_and_wait Member function `interrupt_and_wait()`]
+
+ void interrupt_and_wait();
+
+ void interrupt_and_wait( system_time const& abs_time);
+
+ template< typename DurationTime >
+ void interrupt_and_wait( DurationTime const& rel_time);
+
+[variablelist
+[[Effects:] [Associated __action__ will be interrupted the next time it enters one __interruption_point__ if interruption is not disabled. The function waits until the __action__ has terminated or the specified duration td has elapsed.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+
+[section:get Member function `get()`]
+
+ R get() const;
+
+[variablelist
+[[Effects:] [Returns fulfilled value or throws fulfilled exception.]]
+[[Throws:] [`boost::future::broken_promise`]]
+]
+[endsect]
+
+
+[section:is_read Member function `is_ready()`]
+
+ bool is_ready() const;
+
+[variablelist
+[[Effects:] [Queries if the __action__ has been fulfilled.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+
+[section:has_value Member function `has_value()`]
+
+ bool has_value() const;
+
+[variablelist
+[[Effects:] [Queries if the __action__ has been fulfilled (is ready) and has a value.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+
+[section:has_exception Member function `has_exception()`]
+
+ bool has_exception() const;
+
+[variablelist
+[[Effects:] [Queries if the __action__ has been fulfilled (is ready) and has an exception.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+
+[section:wait Member function `wait()`]
+
+ void wait() const;
+
+[variablelist
+[[Effects:] [Waits until the result is ready.]]
+[[Throws:] [Throws thread_interrupted if the result is not ready at the point of the call, and the current thread is interrupted.]]
+]
+[endsect]
+
+
+[section:timed_wait Member function `timed_wait()`]
+
+ template< typename Duration >
+ bool timed_wait( Duration const& wait_duration);
+
+[variablelist
+[[Effects:] [Waits until the result is ready, or returns false if the time specified by wait_duration has elapsed.]]
+[[Throws:] [Throws thread_interrupted if the result is not ready at the point of the call, and the current thread is interrupted.]]
+]
+[endsect]
+
+
+[section:timed_wait_until Member function `timed_wait_until()`]
+
+ bool timed_wait_until( system_time const& wait_timeout);
+
+[variablelist
+[[Effects:] [Waits until the result is ready, or returns false if the time point specified by wait_timeout has passed.]]
+[[Throws:] [Throws thread_interrupted if the result is not ready at the point of the call, and the current thread is interrupted.]]
+]
+[endsect]
+
+
+[endsect]

Added: sandbox/threadpool/libs/tp/doc/threadpool.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/threadpool.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,57 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[library Boost.Threadpool
+ [quickbook 1.4]
+ [copyright 2008 Oliver Kowalke]
+ [purpose C++ Library for executing actions in a pool of worker threads]
+ [license
+ 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])
+ ]
+ [authors [Kowalke, Oliver]]
+ [category text]
+]
+
+
+[def __action__ action]
+[def __actions__ actions]
+[def __Actions__ Actions]
+[def __boost__ [*boost-1.37.0]]
+[def __boost_future__ [*Boost.Future]]
+[def __boost_threadpool__ [*Boost.Threadpool]]
+[def __bounded_channel__ [link boost_threadpool.channel.bounded_channel ['bounded channel]]]
+[def __unbounded_channel__ [link boost_threadpool.channel.unbounded_channel ['unbounded channel]]]
+[def __channel__ [link boost_threadpool.channel ['channel]]]
+[def __channels__ [link boost_threadpool.channel ['channels]]]
+[def __fork_join__ [link boost_threadpool.forkjoin ['fork/join]]]
+[def __global_queue__ [link boost_threadpool.pool.work_stealing ['global queue]]]
+[def __hardware_concurrency__ boost::thread::hardware_concurrency]
+[def __hwm__ high watermark]
+[def __interruption_point__ [link boost_threadpool.task.interruption ['interruption point]]]
+[def __lwm__ low watermark]
+[def __scheduler_type__ [link boost_threadpool.scheduling ['scheduler type]]]
+[def __sub_action__ sub_action]
+[def __sub_actions__ sub_actions]
+[def __task__ [link boost_threadpool.task ['task]]]
+[def __tasks__ [link boost_threadpool.task ['tasks]]]
+[def __threadpool__ thread pool]
+[def __work_stealing__ [link boost_threadpool.pool.work_stealing ['work stealing]]]
+[def __worker_queue__ [link boost_threadpool.pool.work_stealing ['worker queue]]]
+[def __worker_queues__ [link boost_threadpool.pool.work_stealing ['worker queues]]]
+[def __worker_thread__ worker thread]
+[def __worker_threads__ worker threads]
+
+
+[include introduction.qbk]
+[include pool.qbk]
+[include task.qbk]
+[include channel.qbk]
+[include scheduling.qbk]
+[include forkjoin.qbk]
+[include reference.qbk]

Added: sandbox/threadpool/libs/tp/doc/threadpool.xml
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/threadpool.xml 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,2392 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<library id="boost_threadpool" name="Boost.Threadpool" dirname="boost_threadpool"
+last-revision="$Date: 2009/02/23 19:42:35 $" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <libraryinfo>
+ <authorgroup>
+ <author>
+ <firstname>Oliver</firstname> <surname>Kowalke</surname>
+ </author>
+ </authorgroup>
+ <copyright>
+ <year>2008</year> <holder>Oliver Kowalke</holder>
+ </copyright>
+ <legalnotice>
+ <para>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <ulink url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt>)
+ </para>
+ </legalnotice>
+ <librarypurpose>
+ C++ Library for executing actions in a pool of worker threads
+ </librarypurpose>
+ <librarycategory name="category:text"></librarycategory>
+ </libraryinfo>
+ <title>Boost.Threadpool</title>
+ <section id="boost_threadpool.introduction">
+ <title><link linkend="boost_threadpool.introduction">Introduction</link></title>
+ <para>
+ <emphasis role="bold">Boost.Threadpool</emphasis> is designed for effectively
+ utilize the available hardware and provide a way for efficient asynchronous
+ processing of independent time consuming operations (actions) in the same process.
+ A thread pool contains a number of worker threads to perform actions in parallel,
+ which are usually managed by a scheduler. If a worker thread completes its
+ action, it will take the next action from the scheduler until all actions have
+ been completed. The worker thread then sleeps until there are new actions available.
+ Using a pool of worker threads over creating a new thread for each action may
+ result in better performance and better system stability because the overhead
+ for thread creation and destruction is negated.
+ </para>
+ <para>
+ <emphasis role="bold">Boost.Threadpool</emphasis> uses a <link linkend="boost_threadpool.pool.work_stealing"><emphasis>work
+ stealing</emphasis></link> algorithm and supports <link linkend="boost_threadpool.forkjoin"><emphasis>fork/join</emphasis></link>
+ parallelism (recursively splitting of actions into sub-actions that are solved
+ in parallel, waiting for them to complete, and then joining results).
+ </para>
+ <para>
+ In order to use the classes and functions described here, you can either include
+ the specific headers specified by the descriptions of each class or function,
+ or include the master library header:
+ </para>
+
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">tp</phrase><phrase role="special">/</phrase><phrase role="identifier">tp</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+</programlisting>
+ <para>
+ which includes all the other headers in turn.
+ </para>
+ <note>
+ <para>
+ <emphasis role="bold">Boost.Threadpool</emphasis> uses the futures library,
+ N2561 C++0x proposal, from Anthony Williams (<ulink url="
http://www.justsoftwaresolutions.co.uk/threading/updated-implementation-of-c++-futures-3.html">http://www.justsoftwaresolutions.co.uk/threading/updated-implementation-of-c++-futures-3.html>)
+ as an implementation detail until boost has an official future library.
+ </para>
+ </note>
+ <anchor id="boost_threadpool.introduction.tested_platforms"/>
+ <bridgehead renderas="sect3">
+ <link linkend="boost_threadpool.introduction.tested_platforms">Tested Platforms</link>
+ </bridgehead>
+ <para>
+ <emphasis role="bold">Boost.Threadpool</emphasis> has been tested on the following
+ compilers/platforms:
+ </para>
+ <itemizedlist>
+ <listitem>
+ FreeBSD 7.0 (amd64), GCC 4.2.1
+ </listitem>
+ <listitem>
+ Linux 2.6.26 (amd64), GCC 4.3.1
+ </listitem>
+ <listitem>
+ Linux 2.6.23.9 (i386), GCC 4.2.4
+ </listitem>
+ <listitem>
+ OpenSolaris/Nexenta 1.0.1 (amd64), GCC 4.2.1
+ </listitem>
+ <listitem>
+ Windows XP Professional (i386), MSVC 9.0
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="boost_threadpool.pool">
+ <title><link linkend="boost_threadpool.pool"> Pool</link></title>
+ <para>
+ The pool manages internaly worker threads and submitted actions are stored
+ in a <link linkend="boost_threadpool.channel"><emphasis>channel</emphasis></link>
+ (<link linkend="boost_threadpool.pool.work_stealing"><emphasis>global queue</emphasis></link>)
+ for processing by the worker threads (using a <link linkend="boost_threadpool.pool.work_stealing"><emphasis>work
+ stealing</emphasis></link> algorithm). Each submitted action gets associated
+ with a <link linkend="boost_threadpool.task"><emphasis>task</emphasis></link>
+ object that will be returned. The <link linkend="boost_threadpool.task"><emphasis>task</emphasis></link>
+ object acts as a proxy for a result that is initially not known and gets evaluated
+ later by a worker thread.
+ </para>
+ <anchor id="boost_threadpool.pool.work_stealing"/>
+ <bridgehead renderas="sect3">
+ <link linkend="boost_threadpool.pool.work_stealing">Work-Stealing</link>
+ </bridgehead>
+ <para>
+ Traditional thread poola do not scale because they use a single global queue
+ protected by a global lock. The frequency at which worker threads aquire the
+ global lock becomes a limiting factor for the throughput if:
+ </para>
+ <itemizedlist>
+ <listitem>
+ the actions become smaller
+ </listitem>
+ <listitem>
+ more processors are added
+ </listitem>
+ </itemizedlist>
+ <para>
+ A work-stealing algorithm can be used to solve this problem. It uses a special
+ kind of queue which has two ends, and allows lock-free pushes and pops from
+ the <emphasis>private end</emphasis> (accessed by the worker thread owning
+ the queue), but requires synchronization from the <emphasis>public end</emphasis>
+ (accessed by the other worker threads). Synchronization is necessary when the
+ queue is sufficiently small that private and public operations could conflict.
+ </para>
+ <para>
+ The pool contains one global queue (<link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link> or <link linkend="boost_threadpool.channel.unbounded_channel"><emphasis>unbounded
+ channel</emphasis></link>) protected by a global lock and each worker thread
+ has its own private worker queue. If work is enqueued by a worker thread the
+ action is stored in the worker queue. If the work is enqueued by a application
+ thread it goes into the global queue. When worker threads are looking for work,
+ they have following search order:
+ </para>
+ <itemizedlist>
+ <listitem>
+ look into the private worker queue - actions can be dequeued without locks
+ </listitem>
+ <listitem>
+ look in the global queue - locks are used for synchronization
+ </listitem>
+ <listitem>
+ check other worker queues ('stealing' actions from private worker queues
+ of other worker threads) - requires locks
+ </listitem>
+ </itemizedlist>
+ <para>
+ For a lot of recursively queued actions, the use of a worker queue per thread
+ substantially reduces the synchronization necessary to complete the work. There
+ are also fewer cache effects due to sharing of the global queue information.
+ </para>
+ <para>
+ Operations on the private worker queue are executed in LIFO order and operations
+ on worker queues of other worker threads in FIFO order (steals).
+ </para>
+ <itemizedlist>
+ <listitem>
+ There are chances that memory is still hot in the cache, if the actions are
+ pushed in LIFO order into the private worker queue.
+ </listitem>
+ <listitem>
+ If a worker thread steals work in FIFO order, increases the chances that
+ a larger 'chunk' of work will be stolen (the need for other steals will be
+ possibly reduced). Because the actions are stored in LIFO order, the oldest
+ items are closer to the <emphasis>public end</emphasis> of the queue (forming
+ a tree). Stealing such an older action also steals a (probably) larger subtree
+ of actions unfolded if the stolen work item get executed.
+ </listitem>
+ </itemizedlist>
+ <note>
+ <para>
+ Actions submitted by a worker thread are stored into its private worker queue
+ in LIFO order, thatswhy priorities and timeouts specified at the submit-function
+ get ignored.
+ </para>
+ </note>
+ <important>
+ <para>
+ Because of the work-stealing algorithm the execution order of actions may
+ be not strict as in the global queue.
+ </para>
+ </important>
+ <anchor id="boost_threadpool.pool.creation"/>
+ <bridgehead renderas="sect3">
+ <link linkend="boost_threadpool.pool.creation">Creation</link>
+ </bridgehead>
+ <para>
+ The first template argument specifies the channel type and the scheduling policy.
+ </para>
+
+<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">fifo</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="special">&gt;</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">poolsize</phrase><phrase role="special">(</phrase> <phrase role="number">6</phrase><phrase role="special">),</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">milliseconds</phrase><phrase role="special">(</phrase> <phrase role="number">50</phrase><phrase role="special">),</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">scanns</phrase><phrase role="special">(</phrase><phrase role="number">10</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+</programlisting>
+ <para>
+ In the example above a thread pool is created with a <link linkend="boost_threadpool.channel.unbounded_channel"><emphasis>unbounded
+ channel</emphasis></link>, scheduling actions in <emphasis>FIFO</emphasis>
+ order. The pool contains six worker threads going to sleep for 50 millisec
+ after 10 iterations without geting an action from the <link linkend="boost_threadpool.pool.work_stealing"><emphasis>global
+ queue</emphasis></link>, from its local <link linkend="boost_threadpool.pool.work_stealing"><emphasis>worker
+ queue</emphasis></link> or local queues of other worker threads.
+ </para>
+
+<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">bounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">priority</phrase> <phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="special">&gt;</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">poolsize</phrase><phrase role="special">(</phrase> <phrase role="number">10</phrase><phrase role="special">),</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">high_watermark</phrase><phrase role="special">(</phrase> <phrase role="number">10</phrase><phrase role="special">),</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">low_watermark</phrase><phrase role="special">(</phrase> <phrase role="number">5</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+</programlisting>
+ <para>
+ This pool uses a <link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link> which schedules actions by integer atrributes. A
+ maximum of 10 actions can be queued in the <link linkend="boost_threadpool.pool.work_stealing"><emphasis>global
+ queue</emphasis></link> without blocking the inserting thread.
+ </para>
+ <anchor id="boost_threadpool.pool.shutdown"/>
+ <bridgehead renderas="sect3">
+ <link linkend="boost_threadpool.pool.shutdown">Shutdown</link>
+ </bridgehead>
+ <para>
+ If <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase
+ role="special">&lt;</phrase> <phrase role="identifier">Channel</phrase> <phrase
+ role="special">&gt;::</phrase><phrase role="identifier">shutdown</phrase><phrase
+ role="special">()</phrase></code> is called - the the status of the pool is
+ set to <emphasis>terminating</emphasis> and all worker threads are joined.
+ No futher actions can be submitted by application threads. After all pending
+ actions are processed and all worker threads are joined, the pool is set to
+ status <emphasis>terminated</emphasis>.
+ </para>
+ <note>
+ <para>
+ The deconstructor calls <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">pool</phrase><phrase role="special">&lt;</phrase> <phrase
+ role="identifier">Channel</phrase> <phrase role="special">&gt;::</phrase><phrase
+ role="identifier">shutdown</phrase><phrase role="special">()</phrase></code>
+ if the pool was not shutdown yet.
+ </para>
+ </note>
+
+<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">fifo</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="special">&gt;</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">poolsize</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">task</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">t1</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">pool</phrase><phrase role="special">.</phrase><phrase role="identifier">submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">fibonacci_fn</phrase><phrase role="special">,</phrase>
+ <phrase role="number">10</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
+<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">task</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">t2</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">pool</phrase><phrase role="special">.</phrase><phrase role="identifier">submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">fibonacci_fn</phrase><phrase role="special">,</phrase>
+ <phrase role="number">10</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+<phrase role="identifier">pool</phrase><phrase role="special">.</phrase><phrase role="identifier">shutdown</phrase><phrase role="special">();</phrase>
+
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">t1</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> <phrase role="comment">// 55
+</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">t2</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> <phrase role="comment">// 55
+</phrase></programlisting>
+ <anchor id="boost_threadpool.pool.shutdown_immediatly"/>
+ <bridgehead renderas="sect3">
+ <link linkend="boost_threadpool.pool.shutdown_immediatly">Shutdown immediatly</link>
+ </bridgehead>
+ <para>
+ The function <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase
+ role="special">&lt;</phrase> <phrase role="identifier">Channel</phrase> <phrase
+ role="special">&gt;::</phrase><phrase role="identifier">shutdown_now</phrase><phrase
+ role="special">()</phrase></code> sets the pool status to <emphasis>terminating</emphasis>
+ interrupts and then joins all worker threads. After the worker threads are
+ joined the status of the pool is set to <emphasis>terminated</emphasis> and
+ all pending (unprocessed) actions will be returned.
+ </para>
+ <important>
+ <para>
+ Pending actions in the local <link linkend="boost_threadpool.pool.work_stealing"><emphasis>worker
+ queues</emphasis></link> are not returned if <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">pool</phrase><phrase role="special">&lt;</phrase> <phrase
+ role="identifier">Channel</phrase> <phrase role="special">&gt;::</phrase><phrase
+ role="identifier">shutdown_now</phrase><phrase role="special">()</phrase></code>
+ was called.
+ </para>
+ </important>
+ <anchor id="boost_threadpool.pool.meta_functions"/>
+ <bridgehead renderas="sect3">
+ <link linkend="boost_threadpool.pool.meta_functions">Meta functions</link>
+ </bridgehead>
+ <para>
+ If the thread pool supports priorities <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">has_priority</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">pool_type</phrase> <phrase role="special">&gt;</phrase></code>
+ evaluates to <code><phrase role="keyword">true</phrase></code>. The priority
+ type is determined by <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">priority_type</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">pool_type</phrase> <phrase role="special">&gt;</phrase></code>.
+ </para>
+
+<programlisting><phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">priority</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="special">&gt;</phrase> <phrase role="identifier">pool_type</phrase><phrase role="special">;</phrase>
+
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">boolalpha</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">has_priority</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">pool_type</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="keyword">typeid</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">priority_type</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">pool_type</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase><phrase role="special">).</phrase><phrase role="identifier">name</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ The support of fibers can be tested with meta-function <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">has_fibers</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">pool_type</phrase> <phrase role="special">&gt;</phrase></code>.
+ </para>
+
+<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">boolalpha</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">has_fibers</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">pool_type</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <anchor id="boost_threadpool.pool.processor_binding"/>
+ <bridgehead renderas="sect3">
+ <link linkend="boost_threadpool.pool.processor_binding">Processor binding</link>
+ </bridgehead>
+ <para>
+ For some applications it is convenient to bind the worker threads of the pool
+ to processors of the system. For this purpose BOOST_BIND_WORKER_TO_PROCESSORS
+ must be defined. Without the poolsize in the construtor the thread pool will
+ contain as many worker threads as processors (== boost::thread::hardware_concurrency)
+ are available and each worker thread is bound to one processor.
+ </para>
+
+<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">fifo</phrase> <phrase role="special">&gt;</phrase>
+ <phrase role="special">&gt;</phrase> <phrase role="identifier">pool</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <para>
+ The code above will create a pool with two worker threads on a dual core system
+ (each bound to one core).
+ </para>
+ </section>
+ <section id="boost_threadpool.task">
+ <title><link linkend="boost_threadpool.task"> Task</link></title>
+ <para>
+ For each submitted action a new task object will be created and returned by
+ the pool. The <link linkend="boost_threadpool.task"><emphasis>task</emphasis></link>
+ object acts as a proxy for a result that is initially not known and gets evaluated
+ later by a worker thread. It transports the result (value or exception) of
+ the action back to the caller.
+ </para>
+
+<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">fifo</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="special">&gt;</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">poolsize</phrase><phrase role="special">(</phrase> <phrase role="number">10</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+<phrase role="comment">// task calculates fibonacci(10)
+</phrase><phrase role="comment">// scheduled in unbounded channel with FIFO ordering
+</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">task</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">t</phrase><phrase role="special">(</phrase>
+<phrase role="identifier">pool</phrase><phrase role="special">.</phrase><phrase role="identifier">submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">fibonacci_fn</phrase><phrase role="special">,</phrase>
+ <phrase role="number">10</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">t</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> <phrase role="comment">// 55
+</phrase></programlisting>
+ <anchor id="boost_threadpool.task.interruption"/>
+ <bridgehead renderas="sect3">
+ <link linkend="boost_threadpool.task.interruption">Interruption</link>
+ </bridgehead>
+ <para>
+ The returned <link linkend="boost_threadpool.task"><emphasis>task</emphasis></link>
+ object provides the possiblity to interrupt an action if it is cooperative.
+ An action is known as cooperative if it includes interruption points in its
+ code:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">thread</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">join</phrase><phrase role="special">()</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">thread</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">timed_join</phrase><phrase role="special">()</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">wait</phrase><phrase role="special">()</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">condition_variable</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">timed_wait</phrase><phrase role="special">()</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">condition_variable_any</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">wait</phrase><phrase role="special">()</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">condition_variable_any</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">timed_wait</phrase><phrase role="special">()</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">thread</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">sleep</phrase><phrase role="special">()</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">sleep</phrase><phrase role="special">()</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">this_thread</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">interruption_point</phrase><phrase role="special">()</phrase></code>
+ </listitem>
+ </itemizedlist>
+ <important>
+ <para>
+ Interruption must not be disabled for the worker thread (class <emphasis>boost::this_thread::disable_interruption</emphasis>).
+ </para>
+ </important>
+ <para>
+ The action will be interrupted even if it is pending (interruption is remembered).
+ A <emphasis>boost::thread_interrupted</emphasis> exception will be thrown by
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">task</phrase><phrase
+ role="special">&lt;</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&gt;::</phrase><phrase
+ role="identifier">get</phrase><phrase role="special">()</phrase></code> if
+ the action was interrupted.
+<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">fifo</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="special">&gt;</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">poolsize</phrase><phrase role="special">(</phrase> <phrase role="number">10</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+<phrase role="comment">// submit a long running task
+</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">task</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">t</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">pool</phrase><phrase role="special">.</phrase><phrase role="identifier">submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">long_running_fn</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+<phrase role="comment">// interrupt task
+</phrase><phrase role="identifier">t</phrase><phrase role="special">.</phrase><phrase role="identifier">interrupt</phrase><phrase role="special">();</phrase>
+
+<phrase role="comment">// throws boost::thread_interrupted exception
+</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">t</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
+</programlisting>
+ </para>
+
+<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">fifo</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="special">&gt;</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">poolsize</phrase><phrase role="special">(</phrase> <phrase role="number">10</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+<phrase role="comment">// submit a long running task
+</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">task</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">t</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">pool</phrase><phrase role="special">.</phrase><phrase role="identifier">submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">long_running_fn</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+<phrase role="comment">// interrupt task and wait for its termination
+</phrase><phrase role="identifier">t</phrase><phrase role="special">.</phrase><phrase role="identifier">interrupt_and_wait</phrase><phrase role="special">();</phrase>
+
+<phrase role="comment">// throws boost::thread_interrupted exception
+</phrase><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">t</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <anchor id="boost_threadpool.task.exceptions_in_tasks"/>
+ <bridgehead renderas="sect3">
+ <link linkend="boost_threadpool.task.exceptions_in_tasks">Exceptions in tasks</link>
+ </bridgehead>
+ <para>
+ Exceptions thrown inside an action are transported by the associated task object.
+ Exceptions rethrown by type:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">bad_alloc</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">bad_cast</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">bad_exception</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">bad_typeid</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">domain_error</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">invalid_argument</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">ios_base</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">failure</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">length_error</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">logic_error</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">out_of_range</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">overflow_error</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">range_error</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">runtime_error</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">underflow_error</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">broken_promise</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">future_already_set</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">future_cancel</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">invalid_thread_argument</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">lock_error</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">thread_exception</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">thread_interrupted</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">thread_permission_error</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">thread_resource_error</phrase></code>
+ </listitem>
+ <listitem>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">unsupported_thread_option</phrase></code>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Exceptions derived from <code><phrase role="identifier">std</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">exception</phrase></code>
+ will be rethrown as <code><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">runtime_error</phrase></code> in all other cases a <code><phrase
+ role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">bad_exception</phrase></code>
+ is thrown.
+ </para>
+
+<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">fifo</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="special">&gt;</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">poolsize</phrase><phrase role="special">(</phrase> <phrase role="number">10</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+<phrase role="comment">// task will throw an exception derived from std::exception
+</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">task</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">t</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">pool</phrase><phrase role="special">.</phrase><phrase role="identifier">submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">throwing_fn</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">t</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> <phrase role="comment">// will rethrow an std::runtime_error
+</phrase></programlisting>
+ </section>
+ <section id="boost_threadpool.channel">
+ <title><link linkend="boost_threadpool.channel"> Channel</link></title>
+ <para>
+ The channel synchronizes the access between application threads (producer threads)
+ submitting actions to the pool and worker threads (consumer threads). The scheduling
+ of actions queued into the channel depends on channels the scheduling policy.
+ If the channel becomes empty all worker threads are set to sleep until a new
+ action is put in.
+ </para>
+ <anchor id="boost_threadpool.channel.bounded_channel"/>
+ <bridgehead renderas="sect3">
+ <link linkend="boost_threadpool.channel.bounded_channel">bounded channel</link>
+ </bridgehead>
+
+<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">SchedulingPolicy</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">bounded_channel</phrase>
+</programlisting>
+ <para>
+ The number of pending actions is limited in order to prevent resource exhaustion.
+ For this purpose a high and low watermark has to be passed at construction.
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">high_watermark</phrase></code>
+ sets the maximum of pending tasks. If this limited is reached all threads which
+ submit a tasks will be set to sleep (blocked). <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">low_watermark</phrase></code> sets the threshold when blocked
+ threads get woken up. If high watermark is equal to low watermark everytime
+ a sleeping producer thread will be woken up and puts its task if one worker
+ thread has taken a task from the channel. If low watermark is less than high
+ watermark all sleeping producer threads will be woken up if the amount of pending
+ tasks reaches low watermark.
+ </para>
+ <anchor id="boost_threadpool.channel.unbounded_channel"/>
+ <bridgehead renderas="sect3">
+ <link linkend="boost_threadpool.channel.unbounded_channel">unbounded channel</link>
+ </bridgehead>
+
+<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">SchedulingPolicy</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">class</phrase> <phrase role="identifier">unbounded_channel</phrase>
+</programlisting>
+ <para>
+ An unlimited number of actions can be queued into this channel. The insertion
+ of actions will never block. If the channel becomes empty worker threads will
+ be set to sleep until new actions are inserted into the channel.
+ </para>
+ </section>
+ <section id="boost_threadpool.scheduling">
+ <title><link linkend="boost_threadpool.scheduling"> Scheduling</link></title>
+ <para>
+ The scheduling policy determines how actions are scheduled inside the <link
+ linkend="boost_threadpool.channel"><emphasis>channel</emphasis></link>.
+ </para>
+ <anchor id="boost_threadpool.scheduling.fifo"/>
+ <bridgehead renderas="sect3">
+ <link linkend="boost_threadpool.scheduling.fifo">fifo</link>
+ </bridgehead>
+
+<programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">fifo</phrase>
+</programlisting>
+ <para>
+ First inserted pending action get taken first.
+ </para>
+ <anchor id="boost_threadpool.scheduling.lifo"/>
+ <bridgehead renderas="sect3">
+ <link linkend="boost_threadpool.scheduling.lifo">lifo</link>
+ </bridgehead>
+
+<programlisting><phrase role="keyword">struct</phrase> <phrase role="identifier">lifo</phrase>
+</programlisting>
+ <para>
+ Last inserted pending action get taken first.
+ </para>
+ <anchor id="boost_threadpool.scheduling.priority"/>
+ <bridgehead renderas="sect3">
+ <link linkend="boost_threadpool.scheduling.priority">priority</link>
+ </bridgehead>
+
+<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Attr</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Ord</phrase> <phrase role="special">=</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">less</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Attr</phrase> <phrase role="special">&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <phrase role="identifier">priority</phrase>
+</programlisting>
+ <para>
+ Each pending task is associated with a priority attribute which is used for
+ ordering actions.
+ </para>
+ <anchor id="boost_threadpool.scheduling.smart"/>
+ <bridgehead renderas="sect3">
+ <link linkend="boost_threadpool.scheduling.smart">smart</link>
+ </bridgehead>
+
+<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Attr</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Ord</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Enq</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Deq</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">struct</phrase> <phrase role="identifier">smart</phrase>
+</programlisting>
+ <para>
+ Each pending actions is associated with an attribute. The scheduler gets an
+ put- and take-policy as template arguments. The corresponding policy get applied
+ for each insertion and removal.
+ </para>
+ <para>
+ <emphasis role="bold">Boost.Threadpool</emphasis> provides <emphasis>boost::tp::replace_oldest</emphasis>
+ as put policy and <emphasis>boost::tp::take_oldest</emphasis> as take policy.
+ Both policies allow the replacement of old actions in the scheduler by new
+ ones.
+ </para>
+
+<programlisting><phrase role="comment">// creates a pool with unbounded channel
+</phrase><phrase role="comment">// tasks are processed depending on the associated attributed
+</phrase><phrase role="comment">// oldest tasks with the same attributed pending in the channel
+</phrase><phrase role="comment">// will be replaced by the new task
+</phrase><phrase role="comment">// this example would execute add( 1, 2) and add( 5, 6)
+</phrase><phrase role="comment">// add( 2, 3) is removed (if pending when add( 5, 6) is submitted)
+</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">smart</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="keyword">int</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">less</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;,</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">replace_oldest</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">take_oldest</phrase>
+ <phrase role="special">&gt;</phrase>
+ <phrase role="special">&gt;</phrase>
+<phrase role="special">&gt;</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">poolsize</phrase><phrase role="special">(</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+<phrase role="identifier">pool</phrase><phrase role="special">.</phrase><phrase role="identifier">submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">add_fn</phrase><phrase role="special">,</phrase>
+ <phrase role="number">1</phrase><phrase role="special">,</phrase>
+ <phrase role="number">2</phrase><phrase role="special">),</phrase>
+ <phrase role="number">0</phrase><phrase role="special">);</phrase>
+
+<phrase role="comment">// replaced by later task with same attribute
+</phrase><phrase role="comment">// if still pending in pool
+</phrase><phrase role="identifier">pool</phrase><phrase role="special">.</phrase><phrase role="identifier">submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">add_fn</phrase><phrase role="special">,</phrase>
+ <phrase role="number">3</phrase><phrase role="special">,</phrase>
+ <phrase role="number">4</phrase><phrase role="special">),</phrase>
+ <phrase role="number">1</phrase><phrase role="special">);</phrase>
+
+<phrase role="comment">// will replace previous pending action
+</phrase><phrase role="identifier">pool</phrase><phrase role="special">.</phrase><phrase role="identifier">submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">add_fn</phrase><phrase role="special">,</phrase>
+ <phrase role="number">5</phrase><phrase role="special">,</phrase>
+ <phrase role="number">6</phrase><phrase role="special">),</phrase>
+ <phrase role="number">1</phrase><phrase role="special">);</phrase>
+</programlisting>
+ </section>
+ <section id="boost_threadpool.forkjoin">
+ <title><link linkend="boost_threadpool.forkjoin"> Fork/Join</link></title>
+ <para>
+ Fork/Join algorithms are recursive divide-and-conquer algorithms which repeatedly
+ splitt sub_actions until they become small enough to solve using simple, short
+ sequential methods, so that they run in parallel on multiple cores.
+ </para>
+ <para>
+ The fork operation creates a new sub_action (which can run in parallel) in
+ the pool. The current actions is not proceeded in the join operation until
+ the forked sub_actions have completed. In the meantime the worker thread executes
+ other actions from its local <link linkend="boost_threadpool.pool.work_stealing"><emphasis>worker
+ queue</emphasis></link>.
+ </para>
+
+<programlisting><phrase role="comment">// defines the threadpool type
+</phrase><phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">pool</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">unbounded_channel</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">fifo</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="special">&gt;</phrase> <phrase role="identifier">pool_type</phrase><phrase role="special">;</phrase>
+
+<phrase role="keyword">class</phrase> <phrase role="identifier">fibo</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
+ <phrase role="identifier">pool_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">pool_</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">int</phrase> <phrase role="identifier">cutoff_</phrase><phrase role="special">;</phrase>
+
+ <phrase role="keyword">int</phrase> <phrase role="identifier">seq_</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">n</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">n</phrase> <phrase role="special">&lt;=</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">n</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">else</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">seq_</phrase><phrase role="special">(</phrase> <phrase role="identifier">n</phrase> <phrase role="special">-</phrase> <phrase role="number">2</phrase><phrase role="special">)</phrase> <phrase role="special">+</phrase> <phrase role="identifier">seq_</phrase><phrase role="special">(</phrase> <phrase role="identifier">n</phrase> <phrase role="special">-</phrase> <phrase role="number">1</phrase><phrase role="special">);</phrase>
+ <phrase role="special">}</phrase>
+
+ <phrase role="keyword">int</phrase> <phrase role="identifier">par_</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">n</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">n</phrase> <phrase role="special">&lt;=</phrase> <phrase role="identifier">cutoff_</phrase><phrase role="special">)</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">seq_</phrase><phrase role="special">(</phrase> <phrase role="identifier">n</phrase><phrase role="special">);</phrase>
+ <phrase role="keyword">else</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="comment">// fork a new sub-action t1 in pool
+</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">task</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">t1</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">pool_</phrase><phrase role="special">.</phrase><phrase role="identifier">submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
+ <phrase role="special">&amp;</phrase> <phrase role="identifier">fibo</phrase><phrase role="special">::</phrase><phrase role="identifier">par_</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase role="special">),</phrase>
+ <phrase role="identifier">n</phrase> <phrase role="special">-</phrase> <phrase role="number">1</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+ <phrase role="comment">// fork a new sub-action t2 in pool
+</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">task</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">t1</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">pool_</phrase><phrase role="special">.</phrase><phrase role="identifier">submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
+ <phrase role="special">&amp;</phrase> <phrase role="identifier">fibo</phrase><phrase role="special">::</phrase><phrase role="identifier">par_</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase role="special">),</phrase>
+ <phrase role="identifier">n</phrase> <phrase role="special">-</phrase> <phrase role="number">2</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+ <phrase role="comment">// joining the result of sub-action t1 and t2
+</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">t1</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">+</phrase> <phrase role="identifier">t2</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">();</phrase>
+ <phrase role="special">}</phrase>
+ <phrase role="special">}</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="identifier">fibo</phrase><phrase role="special">(</phrase> <phrase role="identifier">pool_type</phrase> <phrase role="special">&amp;</phrase> <phrase role="identifier">pool</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">cutoff</phrase><phrase role="special">)</phrase>
+ <phrase role="special">:</phrase> <phrase role="identifier">pool_</phrase><phrase role="special">(</phrase> <phrase role="identifier">pool</phrase><phrase role="special">),</phrase> <phrase role="identifier">cutoff_</phrase><phrase role="special">(</phrase> <phrase role="identifier">cutoff</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{}</phrase>
+
+ <phrase role="keyword">int</phrase> <phrase role="identifier">execute</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">n</phrase><phrase role="special">)</phrase>
+ <phrase role="special">{</phrase>
+ <phrase role="keyword">int</phrase> <phrase role="identifier">result</phrase><phrase role="special">(</phrase> <phrase role="identifier">par_</phrase><phrase role="special">(</phrase> <phrase role="identifier">n</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+ <phrase role="keyword">return</phrase> <phrase role="identifier">result</phrase><phrase role="special">;</phrase>
+ <phrase role="special">}</phrase>
+<phrase role="special">};</phrase>
+
+<phrase role="comment">// creates a threadpool with two worker-threads
+</phrase><phrase role="identifier">pool_type</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">poolsize</phrase><phrase role="special">(</phrase> <phrase role="number">2</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+<phrase role="identifier">fibo</phrase> <phrase role="identifier">fib</phrase><phrase role="special">(</phrase> <phrase role="identifier">pool</phrase><phrase role="special">,</phrase> <phrase role="number">1</phrase><phrase role="special">);</phrase>
+
+<phrase role="comment">// submit an action
+</phrase><phrase role="comment">// which calculates the fibonacci number of 10
+</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">tp</phrase><phrase role="special">::</phrase><phrase role="identifier">task</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">t</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">pool</phrase><phrase role="special">.</phrase><phrase role="identifier">submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
+ <phrase role="special">&amp;</phrase> <phrase role="identifier">fibo</phrase><phrase role="special">::</phrase><phrase role="identifier">execute</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">ref</phrase><phrase role="special">(</phrase> <phrase role="identifier">fib</phrase><phrase role="special">),</phrase>
+ <phrase role="number">10</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">t</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="special">&lt;&lt;</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> <phrase role="comment">// prints 55
+</phrase></programlisting>
+ </section>
+ <section id="boost_threadpool.reference">
+ <title><link linkend="boost_threadpool.reference"> Reference</link></title>
+ <section id="boost_threadpool.reference.pool">
+ <title><link linkend="boost_threadpool.reference.pool"> Class template <code><phrase
+ role="identifier">pool</phrase></code></link></title>
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">tp</phrase><phrase role="special">/</phrase><phrase role="identifier">pool</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Channel</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="keyword">class</phrase> <phrase role="identifier">pool</phrase>
+<phrase role="special">:</phrase> <phrase role="keyword">private</phrase> <phrase role="identifier">noncopyable</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="keyword">explicit</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">poolsize</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">psize</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">time_duration</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">asleep</phrase> <phrase role="special">=</phrase> <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">microseconds</phrase><phrase role="special">(</phrase> <phrase role="number">10</phrase><phrase role="special">),</phrase>
+ <phrase role="identifier">scanns</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">scns</phrase> <phrase role="special">=</phrase> <phrase role="identifier">scanns</phrase><phrase role="special">(</phrase> <phrase role="number">20</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+ <phrase role="keyword">explicit</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">poolsize</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">psize</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">high_watermark</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">hwm</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">low_watermark</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">lwm</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">time_duration</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">asleep</phrase> <phrase role="special">=</phrase> <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">milliseconds</phrase><phrase role="special">(</phrase> <phrase role="number">100</phrase><phrase role="special">),</phrase>
+ <phrase role="identifier">scanns</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">scns</phrase> <phrase role="special">=</phrase> <phrase role="identifier">scanns</phrase><phrase role="special">(</phrase> <phrase role="number">20</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+
+ <phrase role="keyword">explicit</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">time_duration</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">asleep</phrase> <phrase role="special">=</phrase> <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">microseconds</phrase><phrase role="special">(</phrase> <phrase role="number">10</phrase><phrase role="special">),</phrase>
+ <phrase role="identifier">scanns</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">scns</phrase> <phrase role="special">=</phrase> <phrase role="identifier">scanns</phrase><phrase role="special">(</phrase> <phrase role="number">20</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+ <phrase role="keyword">explicit</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">high_watermark</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">hwm</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">low_watermark</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">lwm</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">time_duration</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">asleep</phrase> <phrase role="special">=</phrase> <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">milliseconds</phrase><phrase role="special">(</phrase> <phrase role="number">100</phrase><phrase role="special">),</phrase>
+ <phrase role="identifier">scanns</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">scns</phrase> <phrase role="special">=</phrase> <phrase role="identifier">scanns</phrase><phrase role="special">(</phrase> <phrase role="number">20</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+
+ <phrase role="special">~</phrase><phrase role="identifier">pool</phrase><phrase role="special">();</phrase>
+
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">();</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">active</phrase><phrase role="special">();</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">idle</phrase><phrase role="special">();</phrase>
+
+ <phrase role="keyword">void</phrase> <phrase role="identifier">shutdown</phrase><phrase role="special">();</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">callable</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">shutdown_now</phrase><phrase role="special">();</phrase>
+
+ <phrase role="keyword">bool</phrase> <phrase role="identifier">terminated</phrase><phrase role="special">();</phrase>
+ <phrase role="keyword">bool</phrase> <phrase role="identifier">terminateing</phrase><phrase role="special">();</phrase>
+ <phrase role="keyword">void</phrase> <phrase role="identifier">clear</phrase><phrase role="special">();</phrase>
+ <phrase role="keyword">bool</phrase> <phrase role="identifier">empty</phrase><phrase role="special">();</phrase>
+ <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">pending</phrase><phrase role="special">();</phrase>
+
+ <phrase role="keyword">const</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">upper_bound</phrase><phrase role="special">();</phrase>
+ <phrase role="keyword">void</phrase> <phrase role="identifier">upper_bound</phrase><phrase role="special">(</phrase> <phrase role="identifier">high_watermark</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">hwm</phrase><phrase role="special">);</phrase>
+ <phrase role="keyword">const</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">lower_bound</phrase><phrase role="special">();</phrase>
+ <phrase role="keyword">void</phrase> <phrase role="identifier">lower_bound</phrase><phrase role="special">(</phrase> <phrase role="identifier">low_watermark</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">lwm</phrase><phrase role="special">);</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Act</phrase> <phrase role="special">&gt;</phrase>
+ <phrase role="identifier">task</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Act</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">submit</phrase><phrase role="special">(</phrase> <phrase role="identifier">Act</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">act</phrase><phrase role="special">);</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Act</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Attr</phrase> <phrase role="special">&gt;</phrase>
+ <phrase role="identifier">task</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Act</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">Act</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">act</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">Attr</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">attr</phrase><phrase role="special">);</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Act</phrase> <phrase role="special">&gt;</phrase>
+ <phrase role="identifier">task</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Act</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">timed_submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">Act</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">act</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">system_time</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">);</phrase>
+
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Act</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Attr</phrase> <phrase role="special">&gt;</phrase>
+ <phrase role="identifier">task</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Act</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">timed_submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">Act</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">act</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">Attr</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">attr</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">system_time</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">);</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <section id="boost_threadpool.reference.pool.constructor_unbounded_channel_hw">
+ <title><link linkend="boost_threadpool.reference.pool.constructor_unbounded_channel_hw">
+ Constructor (unbounded channel)</link></title>
+<programlisting><phrase role="keyword">explicit</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">time_duration</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">asleep</phrase> <phrase role="special">=</phrase> <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">microseconds</phrase><phrase role="special">(</phrase> <phrase role="number">10</phrase><phrase role="special">),</phrase>
+ <phrase role="identifier">scanns</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">scns</phrase> <phrase role="special">=</phrase> <phrase role="identifier">scanns</phrase><phrase role="special">(</phrase> <phrase role="number">20</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Preconditions:</term>
+ <listitem>
+ <para>
+ Operating system provides functionality for processor pining.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Constructs a <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">pool</phrase><phrase
+ role="special">&lt;</phrase> <phrase role="identifier">Channel</phrase>
+ <phrase role="special">&gt;</phrase></code> instance. For each processor
+ a worker-thread is created and each worker-thread is pined exactly
+ to one processor.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">invalid_scanns</phrase></code>, <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">invalid_timeduration</phrase></code>
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Notes:</term>
+ <listitem>
+ <para>
+ Constructor has to be called if a <link linkend="boost_threadpool.channel.unbounded_channel"><emphasis>unbounded
+ channel</emphasis></link> is used.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.constructor_unbounded_channel">
+ <title><link linkend="boost_threadpool.reference.pool.constructor_unbounded_channel">
+ Constructor (unbounded channel)</link></title>
+<programlisting><phrase role="keyword">explicit</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">poolsize</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">psize</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">time_duration</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">asleep</phrase> <phrase role="special">=</phrase> <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">microseconds</phrase><phrase role="special">(</phrase> <phrase role="number">10</phrase><phrase role="special">),</phrase>
+ <phrase role="identifier">scanns</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">scns</phrase> <phrase role="special">=</phrase> <phrase role="identifier">scanns</phrase><phrase role="special">(</phrase> <phrase role="number">20</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Constructs a <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">pool</phrase><phrase
+ role="special">&lt;</phrase> <phrase role="identifier">Channel</phrase>
+ <phrase role="special">&gt;</phrase></code> instance. Pool contains
+ psize worker-threads.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">invalid_scanns</phrase></code>, <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">invalid_timeduration</phrase></code>
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Notes:</term>
+ <listitem>
+ <para>
+ Constructor has to be called if a <link linkend="boost_threadpool.channel.unbounded_channel"><emphasis>unbounded
+ channel</emphasis></link> is used.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.constructor_bounded_channel_hw">
+ <title><link linkend="boost_threadpool.reference.pool.constructor_bounded_channel_hw">
+ Constructor (bounded channel)</link></title>
+<programlisting><phrase role="keyword">explicit</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">high_watermark</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">hwm</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">low_watermark</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">lwm</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">time_duration</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">asleep</phrase> <phrase role="special">=</phrase> <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">milliseconds</phrase><phrase role="special">(</phrase> <phrase role="number">100</phrase><phrase role="special">),</phrase>
+ <phrase role="identifier">scanns</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">scns</phrase> <phrase role="special">=</phrase> <phrase role="identifier">scanns</phrase><phrase role="special">(</phrase> <phrase role="number">20</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Preconditions:</term>
+ <listitem>
+ <para>
+ Operating system provides functionality for processor pining.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Constructs a <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">pool</phrase><phrase
+ role="special">&lt;</phrase> <phrase role="identifier">Channel</phrase>
+ <phrase role="special">&gt;</phrase></code> instance. For each processor
+ a worker-thread is created and each worker-thread is pined exactly
+ to one processor.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">invalid_scanns</phrase></code>, <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">invalid_timeduration</phrase></code>,
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">invalid_watermark</phrase></code>
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Notes:</term>
+ <listitem>
+ <para>
+ Constructor has to be called if a <link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link> is used.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.constructor_bounded_channel">
+ <title><link linkend="boost_threadpool.reference.pool.constructor_bounded_channel">
+ Constructor (bounded channel)</link></title>
+<programlisting><phrase role="keyword">explicit</phrase> <phrase role="identifier">pool</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">poolsize</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">psize</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">high_watermark</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">hwm</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">low_watermark</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">lwm</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">time_duration</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">asleep</phrase> <phrase role="special">=</phrase> <phrase role="identifier">posix_time</phrase><phrase role="special">::</phrase><phrase role="identifier">milliseconds</phrase><phrase role="special">(</phrase> <phrase role="number">100</phrase><phrase role="special">),</phrase>
+ <phrase role="identifier">scanns</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">scns</phrase> <phrase role="special">=</phrase> <phrase role="identifier">scanns</phrase><phrase role="special">(</phrase> <phrase role="number">20</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Constructs a <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">pool</phrase><phrase
+ role="special">&lt;</phrase> <phrase role="identifier">Channel</phrase>
+ <phrase role="special">&gt;</phrase></code> instance. Pool contains
+ psize worker-threads.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">invalid_scanns</phrase></code>, <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">invalid_timeduration</phrase></code>,
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">invalid_watermark</phrase></code>
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Notes:</term>
+ <listitem>
+ <para>
+ Constructor has to be called if a <link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link> is used.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.destructor">
+ <title><link linkend="boost_threadpool.reference.pool.destructor"> Destructor</link></title>
+
+<programlisting><phrase role="special">~</phrase><phrase role="identifier">pool</phrase><phrase role="special">();</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Calls <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">pool</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">Channel</phrase> <phrase role="special">&gt;::</phrase><phrase
+ role="identifier">shutdown</phrase><phrase role="special">()</phrase></code>
+ if not yet called.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.size">
+ <title><link linkend="boost_threadpool.reference.pool.size"> Member function
+ <code><phrase role="identifier">size</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">();</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Returns how many worker threads are running in the pool.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.active">
+ <title><link linkend="boost_threadpool.reference.pool.active"> Member function
+ <code><phrase role="identifier">active</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">active</phrase><phrase role="special">();</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Returns how many worker threads are active (executing an action).
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.idle">
+ <title><link linkend="boost_threadpool.reference.pool.idle"> Member function
+ <code><phrase role="identifier">idle</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">idle</phrase><phrase role="special">();</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Returns how many worker threads are idle (not executing an action).
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Notes:</term>
+ <listitem>
+ <para>
+ The value is the difference of <code><phrase role="identifier">size</phrase><phrase
+ role="special">()</phrase></code> and <code><phrase role="identifier">active</phrase><phrase
+ role="special">()</phrase></code>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.shutdown">
+ <title><link linkend="boost_threadpool.reference.pool.shutdown"> Member function
+ <code><phrase role="identifier">shutdown</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">shutdown</phrase><phrase role="special">();</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Changes the pool state to <emphasis>terminating</emphasis>, deactivates
+ the channel and joins all worker threads. The status of the pool is
+ assigned to <emphasis>terminated</emphasis> at the end.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Notes:</term>
+ <listitem>
+ <para>
+ All pending actions are processed.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.shutdown_now">
+ <title><link linkend="boost_threadpool.reference.pool.shutdown_now"> Member
+ function <code><phrase role="identifier">shutdown_now</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="keyword">const</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">vector</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">callable</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">shutdown_now</phrase><phrase role="special">();</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Changes the pool state to <emphasis>terminating</emphasis>, deactivates
+ the channel, send interruption request to all worker threads and joins
+ them. The status of the pool is assigned to <emphasis>terminated</emphasis>
+ at the end.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Notes:</term>
+ <listitem>
+ <para>
+ Pending actions are not processed but returned.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.terminated">
+ <title><link linkend="boost_threadpool.reference.pool.terminated"> Member
+ function <code><phrase role="identifier">terminated</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">terminated</phrase><phrase role="special">();</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Queries if the pool is in the terminated state (pool is shutdown).
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.terminateing">
+ <title><link linkend="boost_threadpool.reference.pool.terminateing"> Member
+ function <code><phrase role="identifier">terminateing</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">terminateing</phrase><phrase role="special">();</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Queries if the pool is in the terminating state (tries to shutdown
+ the pool).
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.clear">
+ <title><link linkend="boost_threadpool.reference.pool.clear"> Member function
+ <code><phrase role="identifier">clear</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">clear</phrase><phrase role="special">();</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Removes all pending actions from the <link linkend="boost_threadpool.channel"><emphasis>channel</emphasis></link>.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.empty">
+ <title><link linkend="boost_threadpool.reference.pool.empty"> Member function
+ <code><phrase role="identifier">empty</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">empty</phrase><phrase role="special">();</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Queries if the <link linkend="boost_threadpool.channel"><emphasis>channel</emphasis></link>
+ is empty.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.pending">
+ <title><link linkend="boost_threadpool.reference.pool.pending"> Member function
+ <code><phrase role="identifier">pending</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">pending</phrase><phrase role="special">();</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Queries how many actions are pending in the <link linkend="boost_threadpool.channel"><emphasis>channel</emphasis></link>.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.get_upper_bound">
+ <title><link linkend="boost_threadpool.reference.pool.get_upper_bound"> Member
+ function <code><phrase role="identifier">upper_bound</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">upper_bound</phrase><phrase role="special">();</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Preconditions:</term>
+ <listitem>
+ <para>
+ Channel is of type <link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link>.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Returns the upper bound of the <link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link>.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Notes:</term>
+ <listitem>
+ <para>
+ Can only be used if a <link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link> is used.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.set_upper_bound">
+ <title><link linkend="boost_threadpool.reference.pool.set_upper_bound"> Member
+ function <code><phrase role="identifier">upper_bound</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">high_watermark</phrase> <phrase role="keyword">const</phrase><phrase
+ role="special">&amp;</phrase> <phrase role="identifier">hwm</phrase><phrase
+ role="special">)</phrase></code></link></title>
+<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">upper_bound</phrase><phrase role="special">(</phrase> <phrase role="identifier">high_watermark</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">hwm</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Preconditions:</term>
+ <listitem>
+ <para>
+ Channel is of type <link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link>.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Sets the upper bound of the <link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link>.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Postconditions:</term>
+ <listitem>
+ <para>
+ <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
+ role="identifier">upper_bound</phrase><phrase role="special">()</phrase>
+ <phrase role="special">==</phrase> <phrase role="identifier">hwm</phrase></code>.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">invalid_watermark</phrase></code>
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Notes:</term>
+ <listitem>
+ <para>
+ Can only be used if a <link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link> is used.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.get_lower_bound">
+ <title><link linkend="boost_threadpool.reference.pool.get_lower_bound"> Member
+ function <code><phrase role="identifier">lower_bound</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">lower_bound</phrase><phrase role="special">();</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Preconditions:</term>
+ <listitem>
+ <para>
+ Channel is of type <link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link>.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Returns the lower bound of the <link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link>.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Notes:</term>
+ <listitem>
+ <para>
+ Can only be used if a <link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link> is used.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.set_lower_bound">
+ <title><link linkend="boost_threadpool.reference.pool.set_lower_bound"> Member
+ function <code><phrase role="identifier">lower_bound</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">low_watermark</phrase> <phrase role="keyword">const</phrase><phrase
+ role="special">&amp;</phrase> <phrase role="identifier">lwm</phrase><phrase
+ role="special">)</phrase></code></link></title>
+<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">lower_bound</phrase><phrase role="special">(</phrase> <phrase role="identifier">low_watermark</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">lwm</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Preconditions:</term>
+ <listitem>
+ <para>
+ Channel is of type <link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link>.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Sets the lower bound of the <link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link>.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Postconditions:</term>
+ <listitem>
+ <para>
+ <code><phrase role="keyword">this</phrase><phrase role="special">-&gt;</phrase><phrase
+ role="identifier">lower_bound</phrase><phrase role="special">()</phrase>
+ <phrase role="special">==</phrase> <phrase role="identifier">lwm</phrase></code>.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">invalid_watermark</phrase></code>
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Notes:</term>
+ <listitem>
+ <para>
+ Can only be used if a <link linkend="boost_threadpool.channel.bounded_channel"><emphasis>bounded
+ channel</emphasis></link> is used.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.submit">
+ <title><link linkend="boost_threadpool.reference.pool.submit"> Member function
+ <code><phrase role="identifier">submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">Act</phrase> <phrase role="keyword">const</phrase><phrase
+ role="special">&amp;</phrase> <phrase role="identifier">act</phrase><phrase
+ role="special">)</phrase></code></link></title>
+<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Act</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="identifier">task</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Act</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">submit</phrase><phrase role="special">(</phrase> <phrase role="identifier">Act</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">act</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Preconditions:</term>
+ <listitem>
+ <para>
+ has_priority&lt; pool &gt;::value == false &amp;&amp; ! ( pool.terminating()
+ || pool.terminated() )
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Submits an action to the pool and returns a <link linkend="boost_threadpool.task"><emphasis>task</emphasis></link>
+ object.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">task_rejected</phrase></code>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.pool.submit_attr">
+ <title><link linkend="boost_threadpool.reference.pool.submit_attr"> Member
+ function <code><phrase role="identifier">submit</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">Act</phrase> <phrase role="keyword">const</phrase><phrase
+ role="special">&amp;</phrase> <phrase role="identifier">act</phrase><phrase
+ role="special">,</phrase> <phrase role="identifier">Attr</phrase> <phrase
+ role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase
+ role="identifier">attr</phrase><phrase role="special">)</phrase></code></link></title>
+
+<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Act</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Attr</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="identifier">task</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">result_of</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">Act</phrase><phrase role="special">()</phrase> <phrase role="special">&gt;::</phrase><phrase role="identifier">type</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">submit</phrase><phrase role="special">(</phrase> <phrase role="identifier">Act</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">act</phrase><phrase role="special">,</phrase> <phrase role="identifier">Attr</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">attr</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Preconditions:</term>
+ <listitem>
+ <para>
+ has_priority&lt; pool &gt;::value == true &amp;&amp; ! ( pool.terminating()
+ || pool.terminated() )
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Submits an action to the pool and returns a <link linkend="boost_threadpool.task"><emphasis>task</emphasis></link>
+ object. <emphasis role="underline">_Action</emphasis>_ is scheduled
+ by the attribute.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">task_rejected</phrase></code>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ </section>
+ <section id="boost_threadpool.reference.task">
+ <title><link linkend="boost_threadpool.reference.task"> Class template <code><phrase
+ role="identifier">task</phrase></code></link></title>
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">tp</phrase><phrase role="special">/</phrase><phrase role="identifier">task</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="keyword">class</phrase> <phrase role="identifier">task</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pool</phrase> <phrase role="special">&gt;</phrase>
+ <phrase role="identifier">task</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">Pool</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pool</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">fut</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">interrupter</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">intr</phrase><phrase role="special">);</phrase>
+
+ <phrase role="keyword">void</phrase> <phrase role="identifier">interrupt</phrase><phrase role="special">();</phrase>
+ <phrase role="keyword">void</phrase> <phrase role="identifier">interrupt_and_wait</phrase><phrase role="special">();</phrase>
+ <phrase role="keyword">void</phrase> <phrase role="identifier">interrupt_and_wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">system_time</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">);</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
+ <phrase role="keyword">void</phrase> <phrase role="identifier">interrupt_and_wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">Duration</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">);</phrase>
+ <phrase role="keyword">bool</phrase> <phrase role="identifier">interrupt_requested</phrase><phrase role="special">();</phrase>
+
+ <phrase role="identifier">R</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="keyword">bool</phrase> <phrase role="identifier">is_ready</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">bool</phrase> <phrase role="identifier">has_value</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">bool</phrase> <phrase role="identifier">has_exception</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+
+ <phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
+ <phrase role="keyword">bool</phrase> <phrase role="identifier">timed_wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">Duration</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+ <phrase role="keyword">bool</phrase> <phrase role="identifier">timed_wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">system_time</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">)</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <section id="boost_threadpool.reference.task.constructor">
+ <title><link linkend="boost_threadpool.reference.task.constructor"> Constructor</link></title>
+
+<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pool</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="identifier">task</phrase><phrase role="special">(</phrase>
+ <phrase role="identifier">Pool</phrase> <phrase role="special">*</phrase> <phrase role="identifier">pool</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">future</phrase><phrase role="special">&lt;</phrase> <phrase role="identifier">R</phrase> <phrase role="special">&gt;</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">fut</phrase><phrase role="special">,</phrase>
+ <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">interrupter</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">intr</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Constructs a <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">task</phrase><phrase
+ role="special">&lt;</phrase> <phrase role="identifier">R</phrase>
+ <phrase role="special">&gt;</phrase></code> instance.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Notes:</term>
+ <listitem>
+ <para>
+ task objects should only be constructed by the pool.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.task.interrupt">
+ <title><link linkend="boost_threadpool.reference.task.interrupt"> Member
+ function <code><phrase role="identifier">interrupt</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">interrupt</phrase><phrase role="special">();</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Associated action will be interrupted the next time it enters a <link
+ linkend="boost_threadpool.task.interruption"><emphasis>interruption
+ point</emphasis></link> if interruption is not disabled. The function
+ returns immediatly.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.task.interrupt_and_wait">
+ <title><link linkend="boost_threadpool.reference.task.interrupt_and_wait">
+ Member function <code><phrase role="identifier">interrupt_and_wait</phrase><phrase
+ role="special">()</phrase></code></link></title>
+<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">interrupt_and_wait</phrase><phrase role="special">();</phrase>
+
+<phrase role="keyword">void</phrase> <phrase role="identifier">interrupt_and_wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">system_time</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">abs_time</phrase><phrase role="special">);</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">DurationTime</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="keyword">void</phrase> <phrase role="identifier">interrupt_and_wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">DurationTime</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">rel_time</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Associated action will be interrupted the next time it enters one
+ <link linkend="boost_threadpool.task.interruption"><emphasis>interruption
+ point</emphasis></link> if interruption is not disabled. The function
+ waits until the action has terminated or the specified duration td
+ has elapsed.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.task.get">
+ <title><link linkend="boost_threadpool.reference.task.get"> Member function
+ <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="identifier">R</phrase> <phrase role="identifier">get</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Returns fulfilled value or throws fulfilled exception.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">future</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">broken_promise</phrase></code>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.task.is_read">
+ <title><link linkend="boost_threadpool.reference.task.is_read"> Member function
+ <code><phrase role="identifier">is_ready</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">is_ready</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Queries if the action has been fulfilled.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.task.has_value">
+ <title><link linkend="boost_threadpool.reference.task.has_value"> Member
+ function <code><phrase role="identifier">has_value</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">has_value</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Queries if the action has been fulfilled (is ready) and has a value.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.task.has_exception">
+ <title><link linkend="boost_threadpool.reference.task.has_exception"> Member
+ function <code><phrase role="identifier">has_exception</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">has_exception</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Queries if the action has been fulfilled (is ready) and has an exception.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.task.wait">
+ <title><link linkend="boost_threadpool.reference.task.wait"> Member function
+ <code><phrase role="identifier">wait</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">wait</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Waits until the result is ready.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Throws thread_interrupted if the result is not ready at the point of
+ the call, and the current thread is interrupted.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.task.timed_wait">
+ <title><link linkend="boost_threadpool.reference.task.timed_wait"> Member
+ function <code><phrase role="identifier">timed_wait</phrase><phrase role="special">()</phrase></code></link></title>
+
+<programlisting><phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Duration</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="keyword">bool</phrase> <phrase role="identifier">timed_wait</phrase><phrase role="special">(</phrase> <phrase role="identifier">Duration</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">wait_duration</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Waits until the result is ready, or returns false if the time specified
+ by wait_duration has elapsed.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Throws thread_interrupted if the result is not ready at the point of
+ the call, and the current thread is interrupted.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.task.timed_wait_until">
+ <title><link linkend="boost_threadpool.reference.task.timed_wait_until">
+ Member function <code><phrase role="identifier">timed_wait_until</phrase><phrase
+ role="special">()</phrase></code></link></title>
+<programlisting><phrase role="keyword">bool</phrase> <phrase role="identifier">timed_wait_until</phrase><phrase role="special">(</phrase> <phrase role="identifier">system_time</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">wait_timeout</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Waits until the result is ready, or returns false if the time point
+ specified by wait_timeout has passed.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Throws thread_interrupted if the result is not ready at the point of
+ the call, and the current thread is interrupted.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ </section>
+ <section id="boost_threadpool.reference.poolsize">
+ <title><link linkend="boost_threadpool.reference.poolsize"> Class <code><phrase
+ role="identifier">poolsize</phrase></code></link></title>
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">tp</phrase><phrase role="special">/</phrase><phrase role="identifier">poolsize</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">class</phrase> <phrase role="identifier">poolsize</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="keyword">explicit</phrase> <phrase role="identifier">poolsize</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase>
+
+ <phrase role="keyword">operator</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <section id="boost_threadpool.reference.poolsize.constructor">
+ <title><link linkend="boost_threadpool.reference.poolsize.constructor"> Constructor</link></title>
+
+<programlisting><phrase role="keyword">explicit</phrase> <phrase role="identifier">poolsize</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Preconditions:</term>
+ <listitem>
+ <para>
+ value &gt; 0
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Constructs a <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">poolsize</phrase></code>
+ instance.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Postconditions:</term>
+ <listitem>
+ <para>
+ operator std::size_t () &gt; 0
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">invalid_poolsize</phrase></code>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.poolsize.operator">
+ <title><link linkend="boost_threadpool.reference.poolsize.operator"> Member
+ function <code><phrase role="keyword">operator</phrase> <phrase role="identifier">std</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase
+ role="special">()</phrase></code></link></title>
+<programlisting><phrase role="keyword">operator</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Returns pool size.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ </section>
+ <section id="boost_threadpool.reference.scanns">
+ <title><link linkend="boost_threadpool.reference.scanns"> Class <code><phrase
+ role="identifier">scanns</phrase></code></link></title>
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">tp</phrase><phrase role="special">/</phrase><phrase role="identifier">scanns</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">class</phrase> <phrase role="identifier">scanns</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="keyword">explicit</phrase> <phrase role="identifier">scanns</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase>
+
+ <phrase role="keyword">operator</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <section id="boost_threadpool.reference.scanns.constructor">
+ <title><link linkend="boost_threadpool.reference.scanns.constructor"> Constructor</link></title>
+
+<programlisting><phrase role="keyword">explicit</phrase> <phrase role="identifier">scanns</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Preconditions:</term>
+ <listitem>
+ <para>
+ value &gt;= 0
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Constructs a <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">scanns</phrase></code>
+ instance.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Postconditions:</term>
+ <listitem>
+ <para>
+ operator std::size_t () &gt;= 0
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">invalid_scanns</phrase></code>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.scanns.operator">
+ <title><link linkend="boost_threadpool.reference.scanns.operator"> Member
+ function <code><phrase role="keyword">operator</phrase> <phrase role="identifier">std</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase
+ role="special">()</phrase></code></link></title>
+<programlisting><phrase role="keyword">operator</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Returns scanns size.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ </section>
+ <section id="boost_threadpool.reference.high_watermark">
+ <title><link linkend="boost_threadpool.reference.high_watermark"> Class <code><phrase
+ role="identifier">high_watermark</phrase></code></link></title>
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">tp</phrase><phrase role="special">/</phrase><phrase role="identifier">watermark</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">class</phrase> <phrase role="identifier">high_watermark</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="keyword">explicit</phrase> <phrase role="identifier">high_watermark</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase>
+
+ <phrase role="keyword">operator</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <section id="boost_threadpool.reference.high_watermark.constructor">
+ <title><link linkend="boost_threadpool.reference.high_watermark.constructor">
+ Constructor</link></title>
+<programlisting><phrase role="keyword">explicit</phrase> <phrase role="identifier">high_watermark</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Constructs a <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">high_watermark</phrase></code>
+ instance.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">invalid_watermark</phrase></code>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.high_watermark.operator">
+ <title><link linkend="boost_threadpool.reference.high_watermark.operator">
+ Member function <code><phrase role="keyword">operator</phrase> <phrase role="identifier">std</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase
+ role="special">()</phrase></code></link></title>
+<programlisting><phrase role="keyword">operator</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Returns high watermark.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ </section>
+ <section id="boost_threadpool.reference.low_watermark">
+ <title><link linkend="boost_threadpool.reference.low_watermark"> Class <code><phrase
+ role="identifier">low_watermark</phrase></code></link></title>
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">tp</phrase><phrase role="special">/</phrase><phrase role="identifier">watermark</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">class</phrase> <phrase role="identifier">low_watermark</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="keyword">explicit</phrase> <phrase role="identifier">low_watermark</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase>
+
+ <phrase role="keyword">operator</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <section id="boost_threadpool.reference.low_watermark.constructor">
+ <title><link linkend="boost_threadpool.reference.low_watermark.constructor">
+ Constructor</link></title>
+<programlisting><phrase role="keyword">explicit</phrase> <phrase role="identifier">low_watermark</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">value</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Constructs a <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">low_watermark</phrase></code>
+ instance.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ <code><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">tp</phrase><phrase role="special">::</phrase><phrase
+ role="identifier">invalid_watermark</phrase></code>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section id="boost_threadpool.reference.low_watermark.operator">
+ <title><link linkend="boost_threadpool.reference.low_watermark.operator">
+ Member function <code><phrase role="keyword">operator</phrase> <phrase role="identifier">std</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">size_t</phrase><phrase
+ role="special">()</phrase></code></link></title>
+<programlisting><phrase role="keyword">operator</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Returns low watermark.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ </section>
+ <section id="boost_threadpool.reference.invalid_poolsize">
+ <title><link linkend="boost_threadpool.reference.invalid_poolsize"> Class
+ <code><phrase role="identifier">invalid_poolsize</phrase></code></link></title>
+
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">tp</phrase><phrase role="special">/</phrase><phrase role="identifier">exceptions</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">class</phrase> <phrase role="identifier">invalid_poolsize</phrase>
+<phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">invalid_argument</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="identifier">invalid_poolsize</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">msg</phrase><phrase role="special">);</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <section id="boost_threadpool.reference.invalid_poolsize.constructor">
+ <title><link linkend="boost_threadpool.reference.invalid_poolsize.constructor">
+ Constructor</link></title>
+<programlisting><phrase role="identifier">invalid_poolsize</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">msg</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Constructs a <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">invalid_poolsize</phrase></code>
+ instance.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ </section>
+ <section id="boost_threadpool.reference.invalid_scanns">
+ <title><link linkend="boost_threadpool.reference.invalid_scanns"> Class <code><phrase
+ role="identifier">invalid_scanns</phrase></code></link></title>
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">tp</phrase><phrase role="special">/</phrase><phrase role="identifier">exceptions</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">class</phrase> <phrase role="identifier">invalid_scanns</phrase>
+<phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">invalid_argument</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="identifier">invalid_scanns</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">msg</phrase><phrase role="special">);</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <section id="boost_threadpool.reference.invalid_scanns.constructor">
+ <title><link linkend="boost_threadpool.reference.invalid_scanns.constructor">
+ Constructor</link></title>
+<programlisting><phrase role="identifier">invalid_scanns</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">msg</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Constructs a <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">invalid_scanns</phrase></code>
+ instance.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ </section>
+ <section id="boost_threadpool.reference.invalid_timeduration">
+ <title><link linkend="boost_threadpool.reference.invalid_timeduration"> Class
+ <code><phrase role="identifier">invalid_timeduration</phrase></code></link></title>
+
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">tp</phrase><phrase role="special">/</phrase><phrase role="identifier">exceptions</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">class</phrase> <phrase role="identifier">invalid_timeduration</phrase>
+<phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">invalid_argument</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="identifier">invalid_timeduration</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">msg</phrase><phrase role="special">);</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <section id="boost_threadpool.reference.invalid_timeduration.constructor">
+ <title><link linkend="boost_threadpool.reference.invalid_timeduration.constructor">
+ Constructor</link></title>
+<programlisting><phrase role="identifier">invalid_timeduration</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">msg</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Constructs a <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">invalid_timeduration</phrase></code>
+ instance.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ </section>
+ <section id="boost_threadpool.reference.invalid_watermark">
+ <title><link linkend="boost_threadpool.reference.invalid_watermark"> Class
+ <code><phrase role="identifier">invalid_watermark</phrase></code></link></title>
+
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">tp</phrase><phrase role="special">/</phrase><phrase role="identifier">exceptions</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">class</phrase> <phrase role="identifier">invalid_watermark</phrase>
+<phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">invalid_argument</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="identifier">invalid_watermark</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">msg</phrase><phrase role="special">);</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <section id="boost_threadpool.reference.invalid_watermark.constructor">
+ <title><link linkend="boost_threadpool.reference.invalid_watermark.constructor">
+ Constructor</link></title>
+<programlisting><phrase role="identifier">invalid_watermark</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">msg</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Constructs a <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">invalid_watermark</phrase></code>
+ instance.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ </section>
+ <section id="boost_threadpool.reference.task_rejected">
+ <title><link linkend="boost_threadpool.reference.task_rejected"> Class <code><phrase
+ role="identifier">task_rejected</phrase></code></link></title>
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">tp</phrase><phrase role="special">/</phrase><phrase role="identifier">exceptions</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">class</phrase> <phrase role="identifier">task_rejected</phrase>
+<phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">runtime_error</phrase>
+<phrase role="special">{</phrase>
+<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
+ <phrase role="identifier">task_rejected</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">msg</phrase><phrase role="special">);</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ <section id="boost_threadpool.reference.task_rejected.constructor">
+ <title><link linkend="boost_threadpool.reference.task_rejected.constructor">
+ Constructor</link></title>
+<programlisting><phrase role="identifier">task_rejected</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">string</phrase> <phrase role="keyword">const</phrase><phrase role="special">&amp;</phrase> <phrase role="identifier">msg</phrase><phrase role="special">);</phrase>
+</programlisting>
+ <variablelist>
+ <title></title> <varlistentry><term>Effects:</term>
+ <listitem>
+ <para>
+ Constructs a <code><phrase role="identifier">boost</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">tp</phrase><phrase
+ role="special">::</phrase><phrase role="identifier">task_rejected</phrase></code>
+ instance.
+ </para>
+ </listitem>
+ </varlistentry> <varlistentry><term>Throws:</term>
+ <listitem>
+ <para>
+ Nothing
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ </section>
+ <section id="boost_threadpool.reference.has_priority">
+ <title><link linkend="boost_threadpool.reference.has_priority"> Meta function
+ <code><phrase role="identifier">has_priority</phrase></code></link></title>
+
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">tp</phrase><phrase role="special">/</phrase><phrase role="identifier">info</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pool</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">has_priority</phrase>
+<phrase role="special">:</phrase>
+<phrase role="keyword">public</phrase> <phrase role="identifier">mpl</phrase><phrase role="special">::</phrase><phrase role="identifier">bool_</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">is_same</phrase><phrase role="special">&lt;</phrase>
+ <phrase role="identifier">detail</phrase><phrase role="special">::</phrase><phrase role="identifier">has_priority</phrase><phrase role="special">,</phrase>
+ <phrase role="keyword">typename</phrase> <phrase role="identifier">Pool</phrase><phrase role="special">::</phrase><phrase role="identifier">scheduler_type</phrase><phrase role="special">::</phrase><phrase role="identifier">priority_tag_type</phrase>
+ <phrase role="special">&gt;::</phrase><phrase role="identifier">value</phrase>
+<phrase role="special">&gt;</phrase>
+<phrase role="special">{};</phrase>
+</programlisting>
+ </section>
+ <section id="boost_threadpool.reference.priority_type">
+ <title><link linkend="boost_threadpool.reference.priority_type"> Meta function
+ <code><phrase role="identifier">priority_type</phrase></code></link></title>
+
+<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">tp</phrase><phrase role="special">/</phrase><phrase role="identifier">info</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">&gt;</phrase>
+
+<phrase role="keyword">template</phrase><phrase role="special">&lt;</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pool</phrase> <phrase role="special">&gt;</phrase>
+<phrase role="keyword">struct</phrase> <phrase role="identifier">priority_type</phrase>
+<phrase role="special">{</phrase>
+ <phrase role="keyword">typedef</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Pool</phrase><phrase role="special">::</phrase><phrase role="identifier">scheduler_type</phrase><phrase role="special">::</phrase><phrase role="identifier">attribute_type</phrase> <phrase role="identifier">type</phrase><phrase role="special">;</phrase>
+<phrase role="special">};</phrase>
+</programlisting>
+ </section>
+ </section>
+</library>

Added: sandbox/threadpool/libs/tp/doc/watermark_ref.qbk
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/doc/watermark_ref.qbk 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,75 @@
+[/
+ (C) Copyright 2008 Oliver Kowalke.
+ 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).
+]
+
+[section:high_watermark Class `high_watermark`]
+
+ #include <boost/tp/watermark.hpp>
+
+ class high_watermark
+ {
+ public:
+ explicit high_watermark( std::size_t value);
+
+ operator std::size_t () const;
+ };
+
+[section:constructor Constructor]
+
+ explicit high_watermark( std::size_t value);
+
+[variablelist
+[[Effects:] [Constructs a `boost::tp::high_watermark` instance.]]
+[[Throws:] [`boost::tp::invalid_watermark`]]
+]
+[endsect]
+
+[section:operator Member function `operator std::size_t()`]
+
+ operator std::size_t () const;
+
+[variablelist
+[[Effects:] [Returns high watermark.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[endsect]
+
+
+[section:low_watermark Class `low_watermark`]
+
+ #include <boost/tp/watermark.hpp>
+
+ class low_watermark
+ {
+ public:
+ explicit low_watermark( std::size_t value);
+
+ operator std::size_t () const;
+ };
+
+[section:constructor Constructor]
+
+ explicit low_watermark( std::size_t value);
+
+[variablelist
+[[Effects:] [Constructs a `boost::tp::low_watermark` instance.]]
+[[Throws:] [`boost::tp::invalid_watermark`]]
+]
+[endsect]
+
+[section:operator Member function `operator std::size_t()`]
+
+ operator std::size_t () const;
+
+[variablelist
+[[Effects:] [Returns low watermark.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[endsect]
\ No newline at end of file

Added: sandbox/threadpool/libs/tp/examples/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/examples/Jamfile.v2 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,26 @@
+# Boost.ThreadPool Library Example Jamfile
+
+# Copyright (C) 2008 Oliver Kowalke
+
+# Use, modification and distribution is subject to 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)
+
+# For more information, see http://www.boost.org/
+
+project boost/tp/example
+ : requirements
+ <library>../../thread/build//boost_thread
+ <library>../../system/build//boost_system
+ <threading>multi
+ ;
+
+exe chained_submit : chained_submit.cpp ;
+exe interrupt : interrupt.cpp ;
+exe lazy_submit : lazy_submit.cpp ;
+exe pending : pending.cpp ;
+exe priority : priority.cpp ;
+exe fork_join : fork_join.cpp ;
+exe shutdonw_now : shutdonw_now.cpp ;
+exe smart : smart.cpp ;
+exe submit : submit.cpp ;
\ No newline at end of file

Added: sandbox/threadpool/libs/tp/examples/fork_join.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/examples/fork_join.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,106 @@
+#include <iostream>
+#include <cstdlib>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include "boost/tp/fifo.hpp"
+#include "boost/tp/pool.hpp"
+#include "boost/tp/poolsize.hpp"
+#include "boost/tp/unbounded_channel.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+typedef tp::pool< tp::unbounded_channel< tp::fifo > > pool_type;
+
+class fibo
+{
+private:
+ pool_type & pool_;
+ int offset_;
+
+ int seq_( int n)
+ {
+ if ( n <= 1) return n;
+ else return seq_( n - 2) + seq_( n - 1);
+ }
+
+ int par_( int n)
+ {
+ if ( n <= offset_) return seq_( n);
+ else
+ {
+ tp::task< int > t1(
+ pool_.submit(
+ boost::bind(
+ & fibo::par_,
+ boost::ref( * this),
+ n - 1) ) );
+ tp::task< int > t2(
+ pool_.submit(
+ boost::bind(
+ & fibo::par_,
+ boost::ref( * this),
+ n - 2) ) );
+ return t1.get() + t2.get();
+ }
+ }
+
+public:
+ fibo(
+ pool_type & pool,
+ int offset)
+ :
+ pool_( pool),
+ offset_( offset)
+ {}
+
+ int execute( int n)
+ {
+ int result( par_( n) );
+ return result;
+ }
+};
+
+int main( int argc, char *argv[])
+{
+ try
+ {
+ pool_type pool( tp::poolsize( 3) );
+ fibo fib( pool, 5);
+ std::vector< tp::task< int > > results;
+ results.reserve( 40);
+
+ pt::ptime start( pt::microsec_clock::universal_time() );
+
+ for ( int i = 0; i < 32; ++i)
+ results.push_back(
+ pool.submit(
+ boost::bind(
+ & fibo::execute,
+ boost::ref( fib),
+ i) ) );
+
+ int k = 0;
+ std::vector< tp::task< int > >::iterator e( results.end() );
+ for (
+ std::vector< tp::task< int > >::iterator i( results.begin() );
+ i != e;
+ ++i)
+ std::cout << "fibonacci " << k++ << " == " << i->get() << std::endl;
+
+ pt::ptime stop( pt::microsec_clock::universal_time() );
+ std::cout << ( stop - start).total_milliseconds() << " milli seconds" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+ catch ( std::exception const& e)
+ { std::cerr << "exception: " << e.what() << std::endl; }
+ catch ( ... )
+ { std::cerr << "unhandled" << std::endl; }
+
+ return EXIT_FAILURE;
+}

Added: sandbox/threadpool/libs/tp/examples/interrupt.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/examples/interrupt.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,69 @@
+#include <iostream>
+#include <cstdlib>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include "boost/tp/fifo.hpp"
+#include "boost/tp/pool.hpp"
+#include "boost/tp/poolsize.hpp"
+#include "boost/tp/unbounded_channel.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+inline
+int fibonacci_fn( int n)
+{
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ int k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ boost::this_thread::interruption_point();
+ int tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ boost::this_thread::interruption_point();
+ return k1;
+}
+
+inline
+void long_running_fn()
+{ boost::this_thread::sleep( pt::seconds( 1) ); }
+
+int main( int argc, char *argv[])
+{
+ try
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::fifo >
+ > pool( tp::poolsize( 1) );
+ pool.submit(
+ boost::bind(
+ long_running_fn) );
+ std::cout << "poolsize == " << pool.size() << std::endl;
+ std::cout << "idle threads == " << pool.idle() << std::endl;
+ std::cout << "active threads == " << pool.active() << std::endl;
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ t.interrupt();
+ std::cout << t.get() << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+ catch ( boost::thread_interrupted const& )
+ { std::cerr << "thread_interrupted: task was canceled" << std::endl; }
+ catch ( std::exception const& e)
+ { std::cerr << "exception: " << e.what() << std::endl; }
+ catch ( ... )
+ { std::cerr << "unhandled" << std::endl; }
+
+ return EXIT_FAILURE;
+}

Added: sandbox/threadpool/libs/tp/examples/pending.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/examples/pending.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,65 @@
+#include <iostream>
+#include <cstdlib>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/ref.hpp>
+
+#include "boost/tp/fifo.hpp"
+#include "boost/tp/pool.hpp"
+#include "boost/tp/poolsize.hpp"
+#include "boost/tp/unbounded_channel.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+inline
+int fibonacci_fn( int n)
+{
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ int k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ boost::this_thread::interruption_point();
+ int tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ boost::this_thread::interruption_point();
+ return k1;
+}
+
+inline
+void long_running_fn()
+{ boost::this_thread::sleep( pt::seconds( 1) ); }
+
+int main( int argc, char *argv[])
+{
+ try
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::fifo >
+ > pool( tp::poolsize( 1) );
+ pool.submit(
+ boost::bind(
+ long_running_fn) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ std::cout << "pending tasks == " << pool.pending() << std::endl;
+ std::cout << t.get() << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+ catch ( std::exception const& e)
+ { std::cerr << "exception: " << e.what() << std::endl; }
+ catch ( ... )
+ { std::cerr << "unhandled" << std::endl; }
+
+ return EXIT_FAILURE;
+}

Added: sandbox/threadpool/libs/tp/examples/priority.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/examples/priority.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,60 @@
+#include <iostream>
+#include <cstdlib>
+#include <stdexcept>
+#include <string>
+
+#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include "boost/tp/priority.hpp"
+#include "boost/tp/pool.hpp"
+#include "boost/tp/poolsize.hpp"
+#include "boost/tp/unbounded_channel.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+inline
+void print_fn( std::string const& msg)
+{ printf("%s", msg.c_str() ); }
+
+inline
+void long_running_fn()
+{ boost::this_thread::sleep( pt::milliseconds( 250) ); }
+
+int main( int argc, char *argv[])
+{
+ try
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::priority< int > >
+ > pool( tp::poolsize( 1) );
+ pool.submit(
+ boost::bind(
+ long_running_fn),
+ 0);
+ pool.submit(
+ boost::bind(
+ print_fn,
+ "This"),
+ 0);
+ pool.submit(
+ boost::bind(
+ print_fn,
+ "a text.\n"),
+ 2);
+ pool.submit(
+ boost::bind(
+ print_fn,
+ " is "),
+ 1);
+
+ return EXIT_SUCCESS;
+ }
+ catch ( std::exception const& e)
+ { std::cerr << "exception: " << e.what() << std::endl; }
+ catch ( ... )
+ { std::cerr << "unhandled" << std::endl; }
+
+ return EXIT_FAILURE;
+}

Added: sandbox/threadpool/libs/tp/examples/shutdonw_now.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/examples/shutdonw_now.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,62 @@
+#include <iostream>
+#include <cstdlib>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/ref.hpp>
+
+#include "boost/tp/fifo.hpp"
+#include "boost/tp/pool.hpp"
+#include "boost/tp/poolsize.hpp"
+#include "boost/tp/unbounded_channel.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+inline
+int fibonacci_fn( int n)
+{
+ boost::this_thread::sleep( pt::milliseconds( 500) );
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ int k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ boost::this_thread::interruption_point();
+ int tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ boost::this_thread::interruption_point();
+ return k1;
+}
+
+int main( int argc, char *argv[])
+{
+ try
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::fifo >
+ > pool( tp::poolsize( 1) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ boost::this_thread::sleep( pt::milliseconds( 250) );
+ pool.shutdown_now();
+ std::cout << t.get() << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+ catch ( boost::thread_interrupted const& )
+ { std::cerr << "thread_interrupted: thread was interrupted" << std::endl; }
+ catch ( std::exception const& e)
+ { std::cerr << "exception: " << e.what() << std::endl; }
+ catch ( ... )
+ { std::cerr << "unhandled" << std::endl; }
+
+ return EXIT_FAILURE;
+}

Added: sandbox/threadpool/libs/tp/examples/smart.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/examples/smart.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,86 @@
+#include <iostream>
+#include <cstdlib>
+#include <stdexcept>
+#include <string>
+
+#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include "boost/tp/smart.hpp"
+#include "boost/tp/pool.hpp"
+#include "boost/tp/poolsize.hpp"
+#include "boost/tp/unbounded_channel.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+inline
+void fibonacci_fn( int n)
+{
+ if ( n == 0)
+ {
+ printf("fibonacci(%d) == 0\n", n);
+ return;
+ }
+ if ( n == 1)
+ {
+ printf("fibonacci(%d) == 1\n", n);
+ return;
+ }
+ int k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ int tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ printf("fibonacci(%d) == %d\n", n, k1);
+}
+
+inline
+void long_running_fn()
+{ boost::this_thread::sleep( pt::milliseconds( 500) ); }
+
+int main( int argc, char *argv[])
+{
+ try
+ {
+ tp::pool<
+ tp::unbounded_channel<
+ tp::smart<
+ int,
+ std::less< int >,
+ tp::replace_oldest,
+ tp::take_oldest
+ >
+ >
+ > pool( tp::poolsize( 1) );
+ pool.submit(
+ boost::bind(
+ long_running_fn),
+ 0);
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 0),
+ 1);
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 1),
+ 2);
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ 2);
+
+ return EXIT_SUCCESS;
+ }
+ catch ( std::exception const& e)
+ { std::cerr << "exception: " << e.what() << std::endl; }
+ catch ( ... )
+ { std::cerr << "unhandled" << std::endl; }
+
+ return EXIT_FAILURE;
+}

Added: sandbox/threadpool/libs/tp/examples/spread_over_hardware.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/examples/spread_over_hardware.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,107 @@
+##include <iostream>
+#include <cstdlib>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include "boost/tp/fifo.hpp"
+#include "boost/tp/pool.hpp"
+#include "boost/tp/poolsize.hpp"
+#include "boost/tp/unbounded_channel.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+typedef tp::pool< tp::unbounded_channel< tp::fifo > > pool_type;
+
+class fibo
+{
+private:
+ pool_type & pool_;
+ int offset_;
+
+ int seq_( int n)
+ {
+ if ( n <= 1) return n;
+ else return seq_( n - 2) + seq_( n - 1);
+ }
+
+ int par_( int n)
+ {
+ if ( n <= offset_) return seq_( n);
+ else
+ {
+ tp::task< int > t1(
+ pool_.submit(
+ boost::bind(
+ & fibo::par_,
+ boost::ref( * this),
+ n - 1) ) );
+ tp::task< int > t2(
+ pool_.submit(
+ boost::bind(
+ & fibo::par_,
+ boost::ref( * this),
+ n - 2) ) );
+ return t1.get() + t2.get();
+ }
+ }
+
+public:
+ fibo(
+ pool_type & pool,
+ int offset)
+ :
+ pool_( pool),
+ offset_( offset)
+ {}
+
+ int execute( int n)
+ {
+ int result( par_( n) );
+ return result;
+ }
+};
+
+int main( int argc, char *argv[])
+{
+ try
+ {
+ // ! BOOST_BIND_WORKER_TO_PROCESSORS must be defined !
+ pool_type pool;
+ fibo fib( pool, 5);
+ std::vector< tp::task< int > > results;
+ results.reserve( 40);
+
+ pt::ptime start( pt::microsec_clock::universal_time() );
+
+ for ( int i = 0; i < 32; ++i)
+ results.push_back(
+ pool.submit(
+ boost::bind(
+ & fibo::execute,
+ boost::ref( fib),
+ i) ) );
+
+ int k = 0;
+ std::vector< tp::task< int > >::iterator e( results.end() );
+ for (
+ std::vector< tp::task< int > >::iterator i( results.begin() );
+ i != e;
+ ++i)
+ std::cout << "fibonacci " << k++ << " == " << i->get() << std::endl;
+
+ pt::ptime stop( pt::microsec_clock::universal_time() );
+ std::cout << ( stop - start).total_milliseconds() << " milli seconds" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+ catch ( std::exception const& e)
+ { std::cerr << "exception: " << e.what() << std::endl; }
+ catch ( ... )
+ { std::cerr << "unhandled" << std::endl; }
+
+ return EXIT_FAILURE;
+}

Added: sandbox/threadpool/libs/tp/examples/submit.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/examples/submit.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,53 @@
+#include <iostream>
+#include <cstdlib>
+#include <stdexcept>
+
+#include <boost/bind.hpp>
+
+#include "boost/tp/fifo.hpp"
+#include "boost/tp/pool.hpp"
+#include "boost/tp/poolsize.hpp"
+#include "boost/tp/unbounded_channel.hpp"
+
+namespace tp = boost::tp;
+
+inline
+int fibonacci_fn( int n)
+{
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ int k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ boost::this_thread::interruption_point();
+ int tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ boost::this_thread::interruption_point();
+ return k1;
+}
+
+int main( int argc, char *argv[])
+{
+ try
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::fifo >
+ > pool( tp::poolsize( 1) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ std::cout << t.get() << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+ catch ( std::exception const& e)
+ { std::cerr << "exception: " << e.what() << std::endl; }
+ catch ( ... )
+ { std::cerr << "unhandled" << std::endl; }
+
+ return EXIT_FAILURE;
+}

Added: sandbox/threadpool/libs/tp/test/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/test/Jamfile.v2 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,37 @@
+# Boost.ThreadPool Library Test Jamfile
+
+# Copyright (C) 2008 Oliver Kowalke
+
+# Use, modification and distribution is subject to 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)
+
+# bring in rules for testing
+import testing ;
+
+project
+ : requirements
+ <library>../../test/build//boost_unit_test_framework
+ <library>../../thread/build//boost_thread
+ <library>../../system/build//boost_system
+ <link>static
+ <threading>multi
+ ;
+
+rule tp-test ( source )
+{
+ return
+ [ run $(source).cpp ]
+ ;
+}
+
+test-suite thread_pool :
+ [ tp-test test_bounded_queue_fifo ]
+ [ tp-test test_bounded_queue_lifo ]
+ [ tp-test test_bounded_queue_priority ]
+ [ tp-test test_bounded_queue_smart ]
+ [ tp-test test_unbounded_queue_fifo ]
+ [ tp-test test_unbounded_queue_lifo ]
+ [ tp-test test_unbounded_queue_priority ]
+ [ tp-test test_unbounded_queue_smart ]
+ ;
\ No newline at end of file

Added: sandbox/threadpool/libs/tp/test/test_bounded_queue_fifo.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/test/test_bounded_queue_fifo.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,343 @@
+// Copyright (c) 2008 Oliver Kowalke. 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/future/future.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/tp/bounded_channel.hpp>
+#include <boost/tp/exceptions.hpp>
+#include <boost/tp/fifo.hpp>
+#include <boost/tp/pool.hpp>
+#include <boost/tp/poolsize.hpp>
+#include <boost/tp/task.hpp>
+#include <boost/tp/watermark.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+class fixed_bounded_channel_fifo
+{
+public:
+ // check size, active, idle
+ void test_case_1()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::fifo >
+ > pool(
+ tp::poolsize( 3),
+ tp::high_watermark( 10),
+ tp::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()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::fifo >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ BOOST_CHECK_EQUAL( t.get(), 55);
+ }
+
+ // check timed_submit
+ void test_case_3()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::fifo >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 1),
+ tp::low_watermark( 1) );
+ boost::barrier b( 3);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) );
+ bool thrown( false);
+ try
+ {
+ pool.timed_submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ pt::millisec( 1) );
+ }
+ catch ( tp::task_rejected const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown
+ void test_case_4()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::fifo >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ BOOST_CHECK_EQUAL( t.get(), 55);
+ }
+
+ // check runtime_error throw inside task
+ void test_case_5()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::fifo >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ tp::task< void > t(
+ pool.submit(
+ boost::bind(
+ throwing_fn) ) );
+ pool.shutdown();
+ bool thrown( false);
+ try
+ { t.get(); }
+ catch ( std::runtime_error const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown with task_rejected exception
+ void test_case_6()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::fifo >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ bool thrown( false);
+ try
+ {
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ }
+ catch ( tp::task_rejected const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown_now with thread_interrupted exception
+ void test_case_7()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::fifo >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 1),
+ tp::low_watermark( 1) );
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, pt::time_duration const&) ) delay_fn,
+ 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.terminated() );
+ 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
+ { t.get(); }
+ catch ( boost::thread_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check pending
+ void test_case_8()
+ {
+ typedef tp::pool<
+ tp::bounded_channel< tp::fifo >
+ > pool_type;
+ pool_type pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > t1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) ) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ tp::task< int > t2( pool.submit( fn) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 1) );
+ tp::task< int > t3( pool.submit( fn) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 2) );
+ b.wait();
+ BOOST_CHECK_EQUAL( t1.get(), 55);
+ BOOST_CHECK_EQUAL( t2.get(), 55);
+ BOOST_CHECK_EQUAL( t3.get(), 55);
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ }
+
+ // check fifo scheduling
+ void test_case_9()
+ {
+ typedef tp::pool<
+ tp::bounded_channel< tp::fifo >
+ > pool_type;
+ pool_type pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) );
+ std::vector< int > buffer;
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10) );
+ pool.submit(
+ boost::bind(
+ 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 cancelation
+ void test_case_10()
+ {
+ typedef tp::pool<
+ tp::bounded_channel< tp::fifo >
+ > pool_type;
+ pool_type pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) );
+ std::vector< int > buffer;
+ tp::task< void > t(
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10) ) );
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0) );
+ t.interrupt();
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 1) );
+ bool thrown( false);
+ try
+ { t.get(); }
+ catch ( boost::thread_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.ThreadPool: fixed bounded_channel< fifo > pool test suite") );
+
+ boost::shared_ptr< fixed_bounded_channel_fifo > instance( new fixed_bounded_channel_fifo() );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_fifo::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_fifo::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_fifo::test_case_3, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_fifo::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_fifo::test_case_5, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_fifo::test_case_6, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_fifo::test_case_7, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_fifo::test_case_8, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_fifo::test_case_9, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_fifo::test_case_10, instance) );
+
+ return test;
+}
+

Added: sandbox/threadpool/libs/tp/test/test_bounded_queue_lifo.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/test/test_bounded_queue_lifo.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,344 @@
+// Copyright (c) 2008 Oliver Kowalke. 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/future/future.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/tp/bounded_channel.hpp>
+#include <boost/tp/exceptions.hpp>
+#include <boost/tp/lifo.hpp>
+#include <boost/tp/pool.hpp>
+#include <boost/tp/poolsize.hpp>
+#include <boost/tp/task.hpp>
+#include <boost/tp/watermark.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+class fixed_bounded_channel_lifo
+{
+public:
+ // check size, active, idle
+ void test_case_1()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::lifo >
+ > pool(
+ tp::poolsize( 3),
+ tp::high_watermark( 10),
+ tp::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()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::lifo >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ tp::task< int > f(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ BOOST_CHECK_EQUAL( f.get(), 55);
+ }
+
+ // check timed_submit
+ void test_case_3()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::lifo >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 1),
+ tp::low_watermark( 1) );
+ boost::barrier b( 3);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) );
+ bool thrown( false);
+ try
+ {
+ pool.timed_submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ pt::millisec( 1) );
+ }
+ catch ( tp::task_rejected const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown
+ void test_case_4()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::lifo >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ BOOST_CHECK_EQUAL( t.get(), 55);
+ }
+
+ // check runtime_error throw inside task
+ void test_case_5()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::lifo >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ tp::task< void > f(
+ pool.submit(
+ boost::bind(
+ throwing_fn) ) );
+ pool.shutdown();
+ bool thrown( false);
+ try
+ { f.get(); }
+ catch ( std::runtime_error const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown with task_rejected exception
+ void test_case_6()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::lifo >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ bool thrown( false);
+ try
+ {
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ }
+ catch ( tp::task_rejected const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown_now with thread_interrupted exception
+ void test_case_7()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::lifo >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 1),
+ tp::low_watermark( 1) );
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > f(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, pt::time_duration const&) ) delay_fn,
+ 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.terminated() );
+ 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
+ { f.get(); }
+ catch ( boost::thread_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check pending
+ void test_case_8()
+ {
+ typedef tp::pool<
+ tp::bounded_channel< tp::lifo >
+ > pool_type;
+ pool_type pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > f1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) ) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ tp::task< int > f2( pool.submit( fn) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 1) );
+ tp::task< int > f3( pool.submit( fn) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 2) );
+ b.wait();
+ BOOST_CHECK_EQUAL( f1.get(), 55);
+ BOOST_CHECK_EQUAL( f2.get(), 55);
+ BOOST_CHECK_EQUAL( f3.get(), 55);
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ }
+
+ // check lifo scheduling
+ void test_case_9()
+ {
+ typedef tp::pool<
+ tp::bounded_channel< tp::lifo >
+ > pool_type;
+ pool_type pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > f1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) ) );
+ std::vector< int > buffer;
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10) );
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 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 cancelation
+ void test_case_10()
+ {
+ typedef tp::pool<
+ tp::bounded_channel< tp::lifo >
+ > pool_type;
+ pool_type pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) );
+ std::vector< int > buffer;
+ tp::task< void > f(
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10) ) );
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0) );
+ f.interrupt();
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 1) );
+ bool thrown( false);
+ try
+ { f.get(); }
+ catch ( boost::thread_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.ThreadPool: fixed bounded_channel< lifo > pool test suite") );
+
+ boost::shared_ptr< fixed_bounded_channel_lifo > instance( new fixed_bounded_channel_lifo() );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_lifo::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_lifo::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_lifo::test_case_3, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_lifo::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_lifo::test_case_5, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_lifo::test_case_6, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_lifo::test_case_7, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_lifo::test_case_8, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_lifo::test_case_9, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_lifo::test_case_10, instance) );
+
+ return test;
+}
+

Added: sandbox/threadpool/libs/tp/test/test_bounded_queue_priority.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/test/test_bounded_queue_priority.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,361 @@
+// Copyright (c) 2008 Oliver Kowalke. 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/future/future.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/tp/bounded_channel.hpp>
+#include <boost/tp/exceptions.hpp>
+#include <boost/tp/priority.hpp>
+#include <boost/tp/pool.hpp>
+#include <boost/tp/poolsize.hpp>
+#include <boost/tp/task.hpp>
+#include <boost/tp/watermark.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+class fixed_bounded_channel_priority
+{
+public:
+ // check size, active, idle
+ void test_case_1()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::priority< int > >
+ > pool(
+ tp::poolsize( 3),
+ tp::high_watermark( 10),
+ tp::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()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::priority< int > >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ tp::task< int > f(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ 0) );
+ BOOST_CHECK_EQUAL( f.get(), 55);
+ }
+
+ // check timed_submit
+ void test_case_3()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::priority< int > >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 1),
+ tp::low_watermark( 1) );
+ boost::barrier b( 3);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0);
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0);
+ bool thrown( false);
+ try
+ {
+ pool.timed_submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ 0,
+ pt::millisec( 1) );
+ }
+ catch ( tp::task_rejected const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown
+ void test_case_4()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::priority< int > >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ 0) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ BOOST_CHECK_EQUAL( t.get(), 55);
+ }
+
+ // check runtime_error throw inside task
+ void test_case_5()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::priority< int > >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ tp::task< void > f(
+ pool.submit(
+ boost::bind(
+ throwing_fn),
+ 0) );
+ pool.shutdown();
+ bool thrown( false);
+ try
+ { f.get(); }
+ catch ( std::runtime_error const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown with task_rejected exception
+ void test_case_6()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::priority< int > >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ bool thrown( false);
+ try
+ {
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ 0);
+ }
+ catch ( tp::task_rejected const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown_now with thread_interrupted exception
+ void test_case_7()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::priority< int > >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 1),
+ tp::low_watermark( 1) );
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > f(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, pt::time_duration const&) ) delay_fn,
+ fn,
+ pt::millisec( 500) ),
+ 0) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 1) );
+ BOOST_CHECK_EQUAL( pool.idle(), std::size_t( 0) );
+ BOOST_CHECK_EQUAL( pool.active(), std::size_t( 1) );
+ pool.shutdown_now();
+ BOOST_CHECK( pool.terminated() );
+ 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
+ { f.get(); }
+ catch ( boost::thread_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check pending
+ void test_case_8()
+ {
+ typedef tp::pool<
+ tp::bounded_channel< tp::priority< int > >
+ > pool_type;
+ pool_type pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > f1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ tp::task< int > f2( pool.submit( fn, 0) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 1) );
+ tp::task< int > f3( pool.submit( fn, 0) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 2) );
+ b.wait();
+ BOOST_CHECK_EQUAL( f1.get(), 55);
+ BOOST_CHECK_EQUAL( f2.get(), 55);
+ BOOST_CHECK_EQUAL( f3.get(), 55);
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ }
+
+ // check priority scheduling
+ void test_case_9()
+ {
+ typedef tp::pool<
+ tp::bounded_channel< tp::priority< int > >
+ > pool_type;
+ pool_type pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > f1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0) );
+ std::vector< int > buffer;
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10),
+ 1);
+ pool.submit(
+ boost::bind(
+ 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 cancelation
+ void test_case_10()
+ {
+ typedef tp::pool<
+ tp::bounded_channel< tp::priority< int > >
+ > pool_type;
+ pool_type pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0);
+ std::vector< int > buffer;
+ tp::task< void > f(
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10),
+ 0) );
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0),
+ 0);
+ f.interrupt();
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 1) );
+ bool thrown( false);
+ try
+ { f.get(); }
+ catch ( boost::thread_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.ThreadPool: fixed bounded_channel< priority< int > > pool test suite") );
+
+ boost::shared_ptr< fixed_bounded_channel_priority > instance( new fixed_bounded_channel_priority() );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_priority::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_priority::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_priority::test_case_3, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_priority::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_priority::test_case_5, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_priority::test_case_6, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_priority::test_case_7, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_priority::test_case_8, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_priority::test_case_9, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_priority::test_case_10, instance) );
+
+ return test;
+}
+

Added: sandbox/threadpool/libs/tp/test/test_bounded_queue_smart.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/test/test_bounded_queue_smart.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,367 @@
+// Copyright (c) 2008 Oliver Kowalke. 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/future/future.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/tp/bounded_channel.hpp>
+#include <boost/tp/exceptions.hpp>
+#include <boost/tp/pool.hpp>
+#include <boost/tp/poolsize.hpp>
+#include <boost/tp/smart.hpp>
+#include <boost/tp/task.hpp>
+#include <boost/tp/watermark.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+class fixed_bounded_channel_smart
+{
+public:
+ // check size, active, idle
+ void test_case_1()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool(
+ tp::poolsize( 3),
+ tp::high_watermark( 10),
+ tp::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()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ tp::task< int > f(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ 0) );
+ BOOST_CHECK_EQUAL( f.get(), 55);
+ }
+
+ // check timed_submit
+ void test_case_3()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 1),
+ tp::low_watermark( 1) );
+ boost::barrier b( 3);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0);
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0);
+ bool thrown( false);
+ try
+ {
+ pool.timed_submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ 0,
+ pt::millisec( 1) );
+ }
+ catch ( tp::task_rejected const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown
+ void test_case_4()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ 0) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ BOOST_CHECK_EQUAL( t.get(), 55);
+ }
+
+ // check runtime_error throw inside task
+ void test_case_5()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ tp::task< void > f(
+ pool.submit(
+ boost::bind(
+ throwing_fn),
+ 0) );
+ pool.shutdown();
+ bool thrown( false);
+ try
+ { f.get(); }
+ catch ( std::runtime_error const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown with task_rejected exception
+ void test_case_6()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ bool thrown( false);
+ try
+ {
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ 0);
+ }
+ catch ( tp::task_rejected const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown_now with thread_interrupted exception
+ void test_case_7()
+ {
+ tp::pool<
+ tp::bounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 1),
+ tp::low_watermark( 1) );
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > f(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, pt::time_duration const&) ) delay_fn,
+ fn,
+ pt::millisec( 500) ),
+ 0) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 1) );
+ BOOST_CHECK_EQUAL( pool.idle(), std::size_t( 0) );
+ BOOST_CHECK_EQUAL( pool.active(), std::size_t( 1) );
+ pool.shutdown_now();
+ BOOST_CHECK( pool.terminated() );
+ 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
+ { f.get(); }
+ catch ( boost::thread_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check pending
+ void test_case_8()
+ {
+ typedef tp::pool<
+ tp::bounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool_type;
+ pool_type pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > f1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ tp::task< int > f2( pool.submit( fn, 1) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 1) );
+ tp::task< int > f3( pool.submit( fn, 2) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 2) );
+ b.wait();
+ BOOST_CHECK_EQUAL( f1.get(), 55);
+ BOOST_CHECK_EQUAL( f2.get(), 55);
+ BOOST_CHECK_EQUAL( f3.get(), 55);
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ }
+
+ // check smart scheduling
+ void test_case_9()
+ {
+ typedef tp::pool<
+ tp::bounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool_type;
+ pool_type pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > f1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0) );
+ std::vector< int > buffer;
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10),
+ 2);
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0),
+ 1);
+ pool.submit(
+ boost::bind(
+ 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) );
+ }
+
+ // check cancelation
+ void test_case_10()
+ {
+ typedef tp::pool<
+ tp::bounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool_type;
+ pool_type pool(
+ tp::poolsize( 1),
+ tp::high_watermark( 10),
+ tp::low_watermark( 10) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0);
+ std::vector< int > buffer;
+ tp::task< void > f(
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10),
+ 2) );
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0),
+ 1);
+ f.interrupt();
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 1) );
+ bool thrown( false);
+ try
+ { f.get(); }
+ catch ( boost::thread_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.ThreadPool: fixed bounded_channel< smart< int > > pool test suite") );
+
+ boost::shared_ptr< fixed_bounded_channel_smart > instance( new fixed_bounded_channel_smart() );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_smart::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_smart::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_smart::test_case_3, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_smart::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_smart::test_case_5, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_smart::test_case_6, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_smart::test_case_7, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_smart::test_case_8, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_smart::test_case_9, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_bounded_channel_smart::test_case_10, instance) );
+
+ return test;
+}
+

Added: sandbox/threadpool/libs/tp/test/test_functions.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/test/test_functions.hpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,94 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#ifndef BOOST_TP_TEST_FUNCTIONS_H
+#define BOOST_TP_TEST_FUNCTIONS_H
+
+#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/future/future.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/test/auto_unit_test.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/barrier.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/tp/bounded_channel.hpp>
+#include <boost/tp/exceptions.hpp>
+#include <boost/tp/fifo.hpp>
+#include <boost/tp/lifo.hpp>
+#include <boost/tp/pool.hpp>
+#include <boost/tp/poolsize.hpp>
+#include <boost/tp/priority.hpp>
+#include <boost/tp/smart.hpp>
+#include <boost/tp/task.hpp>
+#include <boost/tp/unbounded_channel.hpp>
+#include <boost/tp/watermark.hpp>
+
+#include <boost/tp/detail/interrupter.hpp>
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+inline
+int add_fn(
+ int a,
+ int b)
+{
+ boost::this_thread::interruption_point();
+ return a + b;
+}
+
+template< typename Fn >
+typename boost::result_of< Fn() >::type barrier_fn(
+ Fn const& fn,
+ boost::barrier & b)
+{
+ b.wait();
+ return fn();
+}
+
+template< typename Fn >
+typename boost::result_of< Fn() >::type delay_fn(
+ Fn const& fn,
+ pt::time_duration const& td)
+{
+ boost::this_thread::sleep( td);
+ return fn();
+}
+
+inline
+int fibonacci_fn( int n)
+{
+ if ( n < 2) return n;
+ int k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ boost::this_thread::interruption_point();
+ int tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ boost::this_thread::interruption_point();
+ return k1;
+}
+
+inline
+void buffer_fibonacci_fn(
+ std::vector< int > & buffer,
+ int n)
+{ buffer.push_back( fibonacci_fn( n) ); }
+
+inline
+void throwing_fn()
+{ throw std::runtime_error("exception thrown"); }
+
+#endif // BOOST_TP_TEST_FUNCTIONS_H

Added: sandbox/threadpool/libs/tp/test/test_unbounded_queue_fifo.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/test/test_unbounded_queue_fifo.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,276 @@
+// Copyright (c) 2008 Oliver Kowalke. 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/future/future.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/tp/bounded_channel.hpp>
+#include <boost/tp/exceptions.hpp>
+#include <boost/tp/fifo.hpp>
+#include <boost/tp/pool.hpp>
+#include <boost/tp/poolsize.hpp>
+#include <boost/tp/task.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+class fixed_unbounded_channel_fifo
+{
+public:
+ // check size, active, idle
+ void test_case_1()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::fifo >
+ > pool( tp::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()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::fifo >
+ > pool( tp::poolsize( 1) );
+ tp::task< int > tsk(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ BOOST_CHECK_EQUAL( tsk.get(), 55);
+ }
+
+ // check shutdown
+ void test_case_3()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::fifo >
+ > pool( tp::poolsize( 1) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ BOOST_CHECK_EQUAL( t.get(), 55);
+ }
+
+ // check runtime_error throw inside task
+ void test_case_4()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::fifo >
+ > pool( tp::poolsize( 1) );
+ tp::task< void > tsk(
+ pool.submit(
+ boost::bind(
+ throwing_fn) ) );
+ pool.shutdown();
+ bool thrown( false);
+ try
+ { tsk.get(); }
+ catch ( std::runtime_error const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown with task_rejected exception
+ void test_case_5()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::fifo >
+ > pool( tp::poolsize( 1) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ bool thrown( false);
+ try
+ {
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ }
+ catch ( tp::task_rejected const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown_now with thread_interrupted exception
+ void test_case_6()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::fifo >
+ > pool( tp::poolsize( 1) );
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > tsk(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, pt::time_duration const&) ) delay_fn,
+ 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.terminated() );
+ 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
+ { tsk.get(); }
+ catch ( boost::thread_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check pending
+ void test_case_7()
+ {
+ typedef tp::pool<
+ tp::unbounded_channel< tp::fifo >
+ > pool_type;
+ pool_type pool( tp::poolsize( 1) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > tsk1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) ) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ tp::task< int > tsk2( pool.submit( fn) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 1) );
+ tp::task< int > tsk3( pool.submit( fn) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 2) );
+ b.wait();
+ BOOST_CHECK_EQUAL( tsk1.get(), 55);
+ BOOST_CHECK_EQUAL( tsk2.get(), 55);
+ BOOST_CHECK_EQUAL( tsk3.get(), 55);
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ }
+
+ // check fifo scheduling
+ void test_case_8()
+ {
+ typedef tp::pool<
+ tp::unbounded_channel< tp::fifo >
+ > pool_type;
+ pool_type pool( tp::poolsize( 1) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > tsk1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) ) );
+ std::vector< int > buffer;
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10) );
+ pool.submit(
+ boost::bind(
+ 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 interruptation
+ void test_case_9()
+ {
+ typedef tp::pool<
+ tp::unbounded_channel< tp::fifo >
+ > pool_type;
+ pool_type pool( tp::poolsize( 1) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) );
+ std::vector< int > buffer;
+ tp::task< void > tsk(
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10) ) );
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0) );
+ tsk.interrupt();
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 1) );
+ bool thrown( false);
+ try
+ { tsk.get(); }
+ catch ( boost::thread_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.ThreadPool: fixed unbounded_channel< fifo > pool test suite") );
+
+ boost::shared_ptr< fixed_unbounded_channel_fifo > instance( new fixed_unbounded_channel_fifo() );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_3, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_5, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_6, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_7, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_8, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_9, instance) );
+
+ return test;
+}

Added: sandbox/threadpool/libs/tp/test/test_unbounded_queue_lifo.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/test/test_unbounded_queue_lifo.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,276 @@
+// Copyright (c) 2008 Oliver Kowalke. 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/future/future.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/tp/bounded_channel.hpp>
+#include <boost/tp/exceptions.hpp>
+#include <boost/tp/lifo.hpp>
+#include <boost/tp/pool.hpp>
+#include <boost/tp/poolsize.hpp>
+#include <boost/tp/task.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+class fixed_unbounded_channel_lifo
+{
+public:
+ // check size, active, idle
+ void test_case_1()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::lifo >
+ > pool( tp::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()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::lifo >
+ > pool( tp::poolsize( 1) );
+ tp::task< int > tsk(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ BOOST_CHECK_EQUAL( tsk.get(), 55);
+ }
+
+ // check shutdown
+ void test_case_3()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::lifo >
+ > pool( tp::poolsize( 1) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ BOOST_CHECK_EQUAL( t.get(), 55);
+ }
+
+ // check runtime_error throw inside task
+ void test_case_4()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::lifo >
+ > pool( tp::poolsize( 1) );
+ tp::task< void > tsk(
+ pool.submit(
+ boost::bind(
+ throwing_fn) ) );
+ pool.shutdown();
+ bool thrown( false);
+ try
+ { tsk.get(); }
+ catch ( std::runtime_error const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown with task_rejected exception
+ void test_case_5()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::lifo >
+ > pool( tp::poolsize( 1) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ bool thrown( false);
+ try
+ {
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ }
+ catch ( tp::task_rejected const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown_now with thread_interrupted exception
+ void test_case_6()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::lifo >
+ > pool( tp::poolsize( 1) );
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > tsk(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, pt::time_duration const&) ) delay_fn,
+ 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.terminated() );
+ 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
+ { tsk.get(); }
+ catch ( boost::thread_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check pending
+ void test_case_7()
+ {
+ typedef tp::pool<
+ tp::unbounded_channel< tp::lifo >
+ > pool_type;
+ pool_type pool( tp::poolsize( 1) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > tsk1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) ) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ tp::task< int > tsk2( pool.submit( fn) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 1) );
+ tp::task< int > tsk3( pool.submit( fn) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 2) );
+ b.wait();
+ BOOST_CHECK_EQUAL( tsk1.get(), 55);
+ BOOST_CHECK_EQUAL( tsk2.get(), 55);
+ BOOST_CHECK_EQUAL( tsk3.get(), 55);
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ }
+
+ // check lifo scheduling
+ void test_case_8()
+ {
+ typedef tp::pool<
+ tp::unbounded_channel< tp::lifo >
+ > pool_type;
+ pool_type pool( tp::poolsize( 1) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > tsk1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) ) );
+ std::vector< int > buffer;
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10) );
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 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 interruptation
+ void test_case_9()
+ {
+ typedef tp::pool<
+ tp::unbounded_channel< tp::lifo >
+ > pool_type;
+ pool_type pool( tp::poolsize( 1) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) );
+ std::vector< int > buffer;
+ tp::task< void > tsk(
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10) ) );
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0) );
+ tsk.interrupt();
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 1) );
+ bool thrown( false);
+ try
+ { tsk.get(); }
+ catch ( boost::thread_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.ThreadPool: fixed unbounded_channel< lifo > pool test suite") );
+
+ boost::shared_ptr< fixed_unbounded_channel_lifo > instance( new fixed_unbounded_channel_lifo() );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_lifo::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_lifo::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_lifo::test_case_3, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_lifo::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_lifo::test_case_5, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_lifo::test_case_6, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_lifo::test_case_7, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_lifo::test_case_8, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_lifo::test_case_9, instance) );
+
+ return test;
+}

Added: sandbox/threadpool/libs/tp/test/test_unbounded_queue_priority.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/test/test_unbounded_queue_priority.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,291 @@
+// Copyright (c) 2008 Oliver Kowalke. 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/future/future.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/tp/bounded_channel.hpp>
+#include <boost/tp/exceptions.hpp>
+#include <boost/tp/priority.hpp>
+#include <boost/tp/pool.hpp>
+#include <boost/tp/poolsize.hpp>
+#include <boost/tp/task.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+class fixed_unbounded_channel_priority
+{
+public:
+ // check size, active, idle
+ void test_case_1()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::priority< int > >
+ > pool( tp::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()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::priority< int > >
+ > pool( tp::poolsize( 1) );
+ tp::task< int > tsk(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ 0) );
+ BOOST_CHECK_EQUAL( tsk.get(), 55);
+ }
+
+ // check shutdown
+ void test_case_3()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::priority< int > >
+ > pool( tp::poolsize( 1) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ 0) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ BOOST_CHECK_EQUAL( t.get(), 55);
+ }
+
+ // check runtime_error throw inside task
+ void test_case_4()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::priority< int > >
+ > pool( tp::poolsize( 1) );
+ tp::task< void > tsk(
+ pool.submit(
+ boost::bind(
+ throwing_fn),
+ 0) );
+ pool.shutdown();
+ bool thrown( false);
+ try
+ { tsk.get(); }
+ catch ( std::runtime_error const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown with task_rejected exception
+ void test_case_5()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::priority< int > >
+ > pool( tp::poolsize( 1) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ bool thrown( false);
+ try
+ {
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ 0);
+ }
+ catch ( tp::task_rejected const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown_now with thread_interrupted exception
+ void test_case_6()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::priority< int > >
+ > pool( tp::poolsize( 1) );
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > tsk(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, pt::time_duration const&) ) delay_fn,
+ fn,
+ pt::millisec( 500) ),
+ 0) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 1) );
+ BOOST_CHECK_EQUAL( pool.idle(), std::size_t( 0) );
+ BOOST_CHECK_EQUAL( pool.active(), std::size_t( 1) );
+ pool.shutdown_now();
+ BOOST_CHECK( pool.terminated() );
+ 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
+ { tsk.get(); }
+ catch ( boost::thread_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check pending
+ void test_case_7()
+ {
+ typedef tp::pool<
+ tp::unbounded_channel< tp::priority< int > >
+ > pool_type;
+ pool_type pool( tp::poolsize( 1) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > tsk1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ tp::task< int > tsk2( pool.submit( fn, 0) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 1) );
+ tp::task< int > tsk3( pool.submit( fn, 0) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 2) );
+ b.wait();
+ BOOST_CHECK_EQUAL( tsk1.get(), 55);
+ BOOST_CHECK_EQUAL( tsk2.get(), 55);
+ BOOST_CHECK_EQUAL( tsk3.get(), 55);
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ }
+
+ // check priority scheduling
+ void test_case_8()
+ {
+ typedef tp::pool<
+ tp::unbounded_channel< tp::priority< int > >
+ > pool_type;
+ pool_type pool( tp::poolsize( 1) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > tsk1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0) );
+ std::vector< int > buffer;
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10),
+ 1);
+ pool.submit(
+ boost::bind(
+ 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 interruptation
+ void test_case_9()
+ {
+ typedef tp::pool<
+ tp::unbounded_channel< tp::priority< int > >
+ > pool_type;
+ pool_type pool( tp::poolsize( 1) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0);
+ std::vector< int > buffer;
+ tp::task< void > tsk(
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10),
+ 0) );
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0),
+ 0);
+ tsk.interrupt();
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 1) );
+ bool thrown( false);
+ try
+ { tsk.get(); }
+ catch ( boost::thread_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.ThreadPool: fixed unbounded_channel< priority< int > > pool test suite") );
+
+ boost::shared_ptr< fixed_unbounded_channel_priority > instance( new fixed_unbounded_channel_priority() );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_priority::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_priority::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_priority::test_case_3, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_priority::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_priority::test_case_5, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_priority::test_case_6, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_priority::test_case_7, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_priority::test_case_8, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_priority::test_case_9, instance) );
+
+ return test;
+}
+

Added: sandbox/threadpool/libs/tp/test/test_unbounded_queue_smart.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/test/test_unbounded_queue_smart.cpp 2009-02-24 14:04:16 EST (Tue, 24 Feb 2009)
@@ -0,0 +1,297 @@
+// Copyright (c) 2008 Oliver Kowalke. 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/future/future.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/tp/bounded_channel.hpp>
+#include <boost/tp/exceptions.hpp>
+#include <boost/tp/pool.hpp>
+#include <boost/tp/poolsize.hpp>
+#include <boost/tp/smart.hpp>
+#include <boost/tp/task.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+class fixed_unbounded_channel_smart
+{
+public:
+ // check size, active, idle
+ void test_case_1()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool( tp::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()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool( tp::poolsize( 1) );
+ tp::task< int > tsk(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ 0) );
+ BOOST_CHECK_EQUAL( tsk.get(), 55);
+ }
+
+ // check shutdown
+ void test_case_3()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool( tp::poolsize( 1) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ 0) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ BOOST_CHECK_EQUAL( t.get(), 55);
+ }
+
+ // check runtime_error throw inside task
+ void test_case_4()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool( tp::poolsize( 1) );
+ tp::task< void > tsk(
+ pool.submit(
+ boost::bind(
+ throwing_fn),
+ 0) );
+ pool.shutdown();
+ bool thrown( false);
+ try
+ { tsk.get(); }
+ catch ( std::runtime_error const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown with task_rejected exception
+ void test_case_5()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool( tp::poolsize( 1) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ bool thrown( false);
+ try
+ {
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10),
+ 0);
+ }
+ catch ( tp::task_rejected const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown_now with boost::thread_interrupted exception
+ void test_case_6()
+ {
+ tp::pool<
+ tp::unbounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool( tp::poolsize( 1) );
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > tsk(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, pt::time_duration const&) ) delay_fn,
+ fn,
+ pt::millisec( 500) ),
+ 0) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 1) );
+ BOOST_CHECK_EQUAL( pool.idle(), std::size_t( 0) );
+ BOOST_CHECK_EQUAL( pool.active(), std::size_t( 1) );
+ pool.shutdown_now();
+ BOOST_CHECK( pool.terminated() );
+ 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
+ { tsk.get(); }
+ catch ( boost::thread_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check pending
+ void test_case_7()
+ {
+ typedef tp::pool<
+ tp::unbounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool_type;
+ pool_type pool( tp::poolsize( 1) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > tsk1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ tp::task< int > tsk2( pool.submit( fn, 1) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 1) );
+ tp::task< int > tsk3( pool.submit( fn, 2) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 2) );
+ b.wait();
+ BOOST_CHECK_EQUAL( tsk1.get(), 55);
+ BOOST_CHECK_EQUAL( tsk2.get(), 55);
+ BOOST_CHECK_EQUAL( tsk3.get(), 55);
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ }
+
+ // check smart scheduling
+ void test_case_8()
+ {
+ typedef tp::pool<
+ tp::unbounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool_type;
+ pool_type pool( tp::poolsize( 1) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > tsk1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0) );
+ std::vector< int > buffer;
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10),
+ 2);
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0),
+ 1);
+ pool.submit(
+ boost::bind(
+ 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) );
+ }
+
+ // check interruptation
+ void test_case_9()
+ {
+ typedef tp::pool<
+ tp::unbounded_channel< tp::smart< int, std::less< int >, tp::replace_oldest, tp::take_oldest > >
+ > pool_type;
+ pool_type pool( tp::poolsize( 1) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ),
+ 0);
+ std::vector< int > buffer;
+ tp::task< void > tsk(
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10),
+ 2) );
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0),
+ 1);
+ tsk.interrupt();
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 1) );
+ bool thrown( false);
+ try
+ { tsk.get(); }
+ catch ( boost::thread_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.ThreadPool: fixed unbounded_channel< smart< int > > pool test suite") );
+
+ boost::shared_ptr< fixed_unbounded_channel_smart > instance( new fixed_unbounded_channel_smart() );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_smart::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_smart::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_smart::test_case_3, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_smart::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_smart::test_case_5, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_smart::test_case_6, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_smart::test_case_7, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_smart::test_case_8, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_smart::test_case_9, 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