|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r56311 - in sandbox/task: boost boost/task boost/task/detail libs/task/build libs/task/doc libs/task/examples libs/task/src libs/task/test
From: oliver.kowalke_at_[hidden]
Date: 2009-09-19 15:06:53
Author: olli
Date: 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
New Revision: 56311
URL: http://svn.boost.org/trac/boost/changeset/56311
Log:
- takeover of 0.3.0 changes
Added:
sandbox/task/boost/task/bounded_onelock_fifo.hpp (contents, props changed)
sandbox/task/boost/task/bounded_onelock_prio_queue.hpp (contents, props changed)
sandbox/task/boost/task/bounded_onelock_smart_queue.hpp (contents, props changed)
sandbox/task/boost/task/bounded_twolock_fifo.hpp (contents, props changed)
sandbox/task/boost/task/detail/smart.hpp (contents, props changed)
sandbox/task/boost/task/local_rr_ums.hpp (contents, props changed)
sandbox/task/boost/task/unbounded_onelock_fifo.hpp (contents, props changed)
sandbox/task/boost/task/unbounded_onelock_prio_queue.hpp (contents, props changed)
sandbox/task/boost/task/unbounded_onelock_smart_queue.hpp (contents, props changed)
sandbox/task/boost/task/unbounded_twolock_fifo.hpp (contents, props changed)
sandbox/task/libs/task/doc/queue.qbk (contents, props changed)
sandbox/task/libs/task/src/context.cpp (contents, props changed)
sandbox/task/libs/task/test/test_bounded_onelock_pool.cpp (contents, props changed)
sandbox/task/libs/task/test/test_bounded_twolock_pool.cpp (contents, props changed)
sandbox/task/libs/task/test/test_unbounded_onelock_pool.cpp (contents, props changed)
sandbox/task/libs/task/test/test_unbounded_twolock_pool.cpp (contents, props changed)
Removed:
sandbox/task/boost/task/bounded_channel.hpp
sandbox/task/boost/task/detail/interrupter.hpp
sandbox/task/boost/task/fifo.hpp
sandbox/task/boost/task/priority.hpp
sandbox/task/boost/task/smart.hpp
sandbox/task/boost/task/unbounded_channel.hpp
sandbox/task/libs/task/doc/channel.qbk
sandbox/task/libs/task/examples/pending.cpp
sandbox/task/libs/task/src/interrupter.cpp
sandbox/task/libs/task/test/test_bounded_pool.cpp
sandbox/task/libs/task/test/test_unbounded_pool.cpp
Text files modified:
sandbox/task/boost/task.hpp | 14 +++-
sandbox/task/boost/task/as_sub_task.hpp | 5 +
sandbox/task/boost/task/async.hpp | 8 +-
sandbox/task/boost/task/callable.hpp | 34 ++++--------
sandbox/task/boost/task/context.hpp | 67 ++++++++++++++++++------
sandbox/task/boost/task/detail/atomic_gcc_ppc.hpp | 4
sandbox/task/boost/task/detail/atomic_gcc_x86.hpp | 4
sandbox/task/boost/task/detail/atomic_interlocked.hpp | 4
sandbox/task/boost/task/detail/atomic_solaris.hpp | 4
sandbox/task/boost/task/detail/atomic_sync.hpp | 4
sandbox/task/boost/task/detail/fiber_posix.hpp | 22 +-------
sandbox/task/boost/task/detail/fiber_windows.hpp | 7 +-
sandbox/task/boost/task/detail/pool_base.hpp | 79 ++++++++----------------------
sandbox/task/boost/task/detail/worker.hpp | 47 ++++++++++++++---
sandbox/task/boost/task/handle.hpp | 28 ++++------
sandbox/task/boost/task/meta.hpp | 4
sandbox/task/boost/task/new_thread.hpp | 9 +-
sandbox/task/boost/task/own_thread.hpp | 4
sandbox/task/boost/task/static_pool.hpp | 68 ++++++-------------------
sandbox/task/libs/task/build/Jamfile.v2 | 8 +-
sandbox/task/libs/task/doc/acknowledgements.qbk | 2
sandbox/task/libs/task/doc/boost_task.qbk | 13 +---
sandbox/task/libs/task/doc/fork_join.qbk | 6 -
sandbox/task/libs/task/doc/introduction.qbk | 6 -
sandbox/task/libs/task/doc/meta_functions.qbk | 6 -
sandbox/task/libs/task/doc/overview.qbk | 6 -
sandbox/task/libs/task/doc/pool.qbk | 11 +---
sandbox/task/libs/task/doc/processor_binding.qbk | 4
sandbox/task/libs/task/doc/ref_callable.qbk | 30 ++++++++---
sandbox/task/libs/task/doc/ref_context.qbk | 56 ++++++++++++++++----
sandbox/task/libs/task/doc/ref_handle.qbk | 13 ++++
sandbox/task/libs/task/doc/ref_static_pool.qbk | 104 +++++++++------------------------------
sandbox/task/libs/task/doc/ref_utility.qbk | 65 +++++++++++++++++++++++-
sandbox/task/libs/task/doc/scheduler.qbk | 8 +-
sandbox/task/libs/task/doc/shutdown.qbk | 12 ---
sandbox/task/libs/task/doc/static_pool.qbk | 17 +-----
sandbox/task/libs/task/doc/task.qbk | 6 -
sandbox/task/libs/task/doc/todo.qbk | 4 -
sandbox/task/libs/task/doc/user_defined_executor.qbk | 54 --------------------
sandbox/task/libs/task/doc/utilities.qbk | 23 ++++++++
sandbox/task/libs/task/doc/work_stealing.qbk | 2
sandbox/task/libs/task/examples/Jamfile.v2 | 1
sandbox/task/libs/task/examples/bind_to_processors.cpp | 2
sandbox/task/libs/task/examples/buffer_multi.cpp | 2
sandbox/task/libs/task/examples/buffer_multi2.cpp | 2
sandbox/task/libs/task/examples/buffer_pool.cpp | 4 -
sandbox/task/libs/task/examples/buffer_pool_thread.cpp | 4 -
sandbox/task/libs/task/examples/fork_join.cpp | 2
sandbox/task/libs/task/examples/interrupt.cpp | 4 -
sandbox/task/libs/task/examples/no_deadlock_pool.cpp | 4 -
sandbox/task/libs/task/examples/no_deadlock_pool3.cpp | 4 -
sandbox/task/libs/task/examples/priority.cpp | 4 -
sandbox/task/libs/task/examples/semaphore_pool.cpp | 4 -
sandbox/task/libs/task/examples/semaphore_pool_thread.cpp | 4 -
sandbox/task/libs/task/examples/shutdown_now.cpp | 4 -
sandbox/task/libs/task/examples/smart.cpp | 8 --
sandbox/task/libs/task/examples/submit.cpp | 6 -
sandbox/task/libs/task/src/callable.cpp | 4 -
sandbox/task/libs/task/test/Jamfile.v2 | 6 +
sandbox/task/libs/task/test/test_as_sub_task.cpp | 3
sandbox/task/libs/task/test/test_new_thread.cpp | 1
sandbox/task/libs/task/test/test_own_thread.cpp | 1
sandbox/task/libs/task/test/test_task.cpp | 1
63 files changed, 432 insertions(+), 515 deletions(-)
Modified: sandbox/task/boost/task.hpp
==============================================================================
--- sandbox/task/boost/task.hpp (original)
+++ sandbox/task/boost/task.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -9,26 +9,30 @@
#include <boost/task/as_sub_task.hpp>
#include <boost/task/async.hpp>
-#include <boost/task/bounded_channel.hpp>
+#include <boost/task/bounded_twolock_fifo.hpp>
+#include <boost/task/bounded_onelock_fifo.hpp>
+#include <boost/task/bounded_onelock_prio_queue.hpp>
+#include <boost/task/bounded_onelock_smart_queue.hpp>
#include <boost/task/callable.hpp>
#include <boost/task/context.hpp>
#include <boost/task/exceptions.hpp>
-#include <boost/task/fifo.hpp>
#include <boost/task/future.hpp>
#include <boost/task/handle.hpp>
+#include <boost/task/local_rr_ums.hpp>
#include <boost/task/meta.hpp>
#include <boost/task/new_thread.hpp>
#include <boost/task/own_thread.hpp>
#include <boost/task/poolsize.hpp>
-#include <boost/task/priority.hpp>
#include <boost/task/scanns.hpp>
#include <boost/task/semaphore.hpp>
#include <boost/task/stacksize.hpp>
#include <boost/task/static_pool.hpp>
-#include <boost/task/smart.hpp>
#include <boost/task/task.hpp>
#include <boost/task/unbounded_buffer.hpp>
-#include <boost/task/unbounded_channel.hpp>
+#include <boost/task/unbounded_twolock_fifo.hpp>
+#include <boost/task/unbounded_onelock_fifo.hpp>
+#include <boost/task/unbounded_onelock_prio_queue.hpp>
+#include <boost/task/unbounded_onelock_smart_queue.hpp>
#include <boost/task/utility.hpp>
#include <boost/task/watermark.hpp>
Modified: sandbox/task/boost/task/as_sub_task.hpp
==============================================================================
--- sandbox/task/boost/task/as_sub_task.hpp (original)
+++ sandbox/task/boost/task/as_sub_task.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -12,6 +12,7 @@
#include <boost/function.hpp>
#include <boost/thread/detail/move.hpp>
+#include <boost/task/callable.hpp>
#include <boost/task/context.hpp>
#include <boost/task/detail/worker.hpp>
#include <boost/task/future.hpp>
@@ -43,8 +44,8 @@
w,
wcb) );
context ctx;
- handle< R > h( ctx.get_handle( f) );
- w->put( ctx.get_callable( boost::move( t) ) );
+ handle< R > h( f, ctx);
+ w->put( callable( boost::move( t), ctx) );
return h;
}
else
Modified: sandbox/task/boost/task/async.hpp
==============================================================================
--- sandbox/task/boost/task/async.hpp (original)
+++ sandbox/task/boost/task/async.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -27,12 +27,12 @@
handle< R > async( task< R > t, EP ep)
{ return ep( boost::move( t) ); }
-template< typename R, typename Channel >
-handle< R > async( task< R > t, static_pool< Channel > & pool)
+template< typename R, typename Queue >
+handle< R > async( task< R > t, static_pool< Queue > & pool)
{ return pool.submit( boost::move( t) ); }
-template< typename R, typename Channel, typename Attr >
-handle< R > async( task< R > t, Attr attr, static_pool< Channel > & pool)
+template< typename R, typename Queue, typename Attr >
+handle< R > async( task< R > t, Attr attr, static_pool< Queue > & pool)
{ return pool.submit( boost::move( t), attr); }
} }
Deleted: sandbox/task/boost/task/bounded_channel.hpp
==============================================================================
--- sandbox/task/boost/task/bounded_channel.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
+++ (empty file)
@@ -1,408 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_TASK_BOUNDED_CHANNEL_H
-#define BOOST_TASK_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/task/callable.hpp>
-#include <boost/task/exceptions.hpp>
-#include <boost/task/watermark.hpp>
-
-#include <boost/config/abi_prefix.hpp>
-
-namespace boost { namespace task
-{
-template< typename SchedulingPolicy >
-class bounded_channel
-{
-public:
- typedef SchedulingPolicy scheduler_type;
- typedef typename scheduler_type::impl::item item;
-
-private:
- typedef typename scheduler_type::impl queue;
-
- 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< callable > drain_()
- {
- BOOST_ASSERT( deactive_now_() );
- std::vector< callable > unprocessed;
- unprocessed.reserve( queue_.size() );
- BOOST_FOREACH( callable ca, queue_)
- { unprocessed.push_back( 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)
- {
- if ( full_() )
- {
- 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 ( full_() )
- {
- 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_(
- callable & ca,
- unique_lock< shared_mutex > & lk)
- {
- if ( deactive_now_() || ( deactive_() && empty_() ) )
- return false;
- if ( empty_() )
- {
- try
- {
- not_empty_cond_.wait(
- lk,
- bind(
- & bounded_channel::consumers_activate_,
- this) );
- }
- catch ( thread_interrupted const&)
- { return false; }
- }
- if ( deactive_now_() || ( deactive_() && empty_() ) )
- return false;
- queue_.pop( ca);
- 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_(
- callable & ca,
- Duration const& rel_time,
- unique_lock< shared_mutex > & lk)
- {
- if ( deactive_now_() || ( deactive_() && empty_() ) )
- return false;
- if ( empty_() )
- {
- try
- {
- if ( ! not_empty_cond_.timed_wait(
- lk,
- rel_time,
- bind(
- & bounded_channel::consumers_activate_,
- this) ) )
- return false;
- }
- catch ( thread_interrupted const&)
- { return false; }
- }
- if ( deactive_now_() || ( deactive_() && empty_() ) )
- return false;
- queue_.pop( ca);
- if ( size_() <= lwm_)
- {
- if ( lwm_ == hwm_)
- not_full_cond_.notify_one();
- else
- // more than one producer could be waiting
- // in order to submit an task
- not_full_cond_.notify_all();
- }
- return ! ca.empty();
- }
-
- bool try_take_( callable & ca)
- {
- if ( deactive_now_() || empty_() )
- return false;
- queue_.pop( ca);
- bool valid = ! ca.empty();
- if ( valid && size_() <= lwm_)
- {
- if ( lwm_ == hwm_)
- not_full_cond_.notify_one();
- else
- // more than one producer could be waiting
- // in order to submit an task
- not_full_cond_.notify_all();
- }
- return valid;
- }
-
- 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()
- {
- lock_guard< shared_mutex > lk( mtx_);
- return active_();
- }
-
- void activate()
- {
- lock_guard< shared_mutex > lk( mtx_);
- activate_();
- }
-
- void clear()
- {
- lock_guard< shared_mutex > lk( mtx_);
- clear_();
- }
-
- bool deactive()
- { return ! active(); }
-
- void deactivate()
- {
- lock_guard< shared_mutex > lk( mtx_);
- deactivate_();
- }
-
- void deactivate_now()
- {
- lock_guard< shared_mutex > lk( mtx_);
- deactivate_now_();
- }
-
- const std::vector< callable > drain()
- {
- lock_guard< shared_mutex > lk( mtx_);
- return drain_();
- }
-
- bool empty()
- {
- lock_guard< shared_mutex > lk( mtx_);
- return empty_();
- }
-
- bool full()
- {
- lock_guard< shared_mutex > lk( mtx_);
- return full_();
- }
-
- std::size_t upper_bound()
- {
- lock_guard< shared_mutex > lk( mtx_);
- return hwm_;
- }
-
- void upper_bound( std::size_t hwm)
- {
- lock_guard< shared_mutex > lk( mtx_);
- upper_bound_( hwm);
- }
-
- std::size_t lower_bound()
- {
- lock_guard< shared_mutex > lk( mtx_);
- return lwm_;
- }
-
- void lower_bound( std::size_t lwm)
- {
- lock_guard< shared_mutex > lk( mtx_);
- lower_bound_( lwm);
- }
-
- std::size_t size()
- {
- lock_guard< 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( callable & ca)
- {
- unique_lock< shared_mutex > lk( mtx_);
- return take_( ca, lk);
- }
-
- template< typename Duration >
- bool take(
- callable & ca,
- Duration const& rel_time)
- {
- unique_lock< shared_mutex > lk( mtx_);
- return take_( ca, rel_time, lk);
- }
-
- bool try_take( callable & ca)
- {
- lock_guard< shared_mutex > lk( mtx_);
- return try_take_( ca);
- }
-};
-} }
-
-#include <boost/config/abi_suffix.hpp>
-
-#endif // BOOST_TASK_BOUNDED_CHANNEL_H
Added: sandbox/task/boost/task/bounded_onelock_fifo.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/bounded_onelock_fifo.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,311 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_BOUNDED_ONELOCK_FIFO_H
+#define BOOST_TASK_BOUNDED_ONELOCK_FIFO_H
+
+#include <cstddef>
+#include <list>
+
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+
+#include <boost/task/callable.hpp>
+#include <boost/task/detail/atomic.hpp>
+#include <boost/task/detail/meta.hpp>
+#include <boost/task/exceptions.hpp>
+#include <boost/task/watermark.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost { namespace task
+{
+class bounded_onelock_fifo
+{
+public:
+ typedef detail::has_no_attribute attribute_tag_type;
+ typedef callable value_type;
+
+private:
+ typedef std::list< value_type > queue_type;
+
+ volatile uint32_t state_;
+ queue_type queue_;
+ shared_mutex mtx_;
+ condition not_empty_cond_;
+ condition not_full_cond_;
+ std::size_t hwm_;
+ std::size_t lwm_;
+
+ bool active_() const
+ { return 0 == state_; }
+
+ void deactivate_()
+ { detail::atomic_fetch_add( & state_, 1); }
+
+ 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_(
+ value_type const& va,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( full_() )
+ {
+ not_full_cond_.wait(
+ lk,
+ bind(
+ & bounded_onelock_fifo::producers_activate_,
+ this) );
+ }
+ if ( ! active_() )
+ throw task_rejected("queue is not active");
+ queue_.push_back( va);
+ not_empty_cond_.notify_one();
+ }
+
+ template< typename Duration >
+ void put_(
+ value_type const& va,
+ Duration const& rel_time,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( full_() )
+ {
+ if ( ! not_full_cond_.timed_wait(
+ lk,
+ rel_time,
+ bind(
+ & bounded_onelock_fifo::producers_activate_,
+ this) ) )
+ throw task_rejected("timed out");
+ }
+ if ( ! active_() )
+ throw task_rejected("queue is not active");
+ queue_.push_back( va);
+ not_empty_cond_.notify_one();
+ }
+
+ bool take_(
+ value_type & va,
+ unique_lock< shared_mutex > & lk)
+ {
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ not_empty_cond_.wait(
+ lk,
+ bind(
+ & bounded_onelock_fifo::consumers_activate_,
+ this) );
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ va.swap( queue_.front() );
+ queue_.pop_front();
+ 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 ! va.empty();
+ }
+
+ template< typename Duration >
+ bool take_(
+ value_type & va,
+ Duration const& rel_time,
+ unique_lock< shared_mutex > & lk)
+ {
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ if ( ! not_empty_cond_.timed_wait(
+ lk,
+ rel_time,
+ bind(
+ & bounded_onelock_fifo::consumers_activate_,
+ this) ) )
+ return false;
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ va.swap( queue_.front() );
+ queue_.pop_front();
+ if ( size_() <= lwm_)
+ {
+ if ( lwm_ == hwm_)
+ not_full_cond_.notify_one();
+ else
+ // more than one producer could be waiting
+ // in order to submit an task
+ not_full_cond_.notify_all();
+ }
+ return ! va.empty();
+ }
+
+ bool try_take_( value_type & va)
+ {
+ if ( empty_() )
+ return false;
+ va.swap( queue_.front() );
+ queue_.pop_front();
+ bool valid = ! va.empty();
+ if ( valid && size_() <= lwm_)
+ {
+ if ( lwm_ == hwm_)
+ not_full_cond_.notify_one();
+ else
+ // more than one producer could be waiting
+ // in order to submit an task
+ not_full_cond_.notify_all();
+ }
+ return valid;
+ }
+
+ bool producers_activate_() const
+ { return ! active_() || ! full_(); }
+
+ bool consumers_activate_() const
+ { return ! active_() || ! empty_(); }
+
+public:
+ bounded_onelock_fifo(
+ high_watermark const& hwm,
+ low_watermark const& lwm)
+ :
+ state_( 0),
+ 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");
+ }
+
+ void deactivate()
+ { deactivate_(); }
+
+ bool empty()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return empty_();
+ }
+
+ 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);
+ }
+
+ void put( value_type const& va)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( va, lk);
+ }
+
+ template< typename Duration >
+ void put(
+ value_type const& va,
+ Duration const& rel_time)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( va, rel_time, lk);
+ }
+
+ bool take( value_type & va)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( va, lk);
+ }
+
+ template< typename Duration >
+ bool take(
+ value_type & va,
+ Duration const& rel_time)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( va, rel_time, lk);
+ }
+
+ bool try_take( value_type & va)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return try_take_( va);
+ }
+};
+} }
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_TASK_BOUNDED_ONELOCK_FIFO_H
Added: sandbox/task/boost/task/bounded_onelock_prio_queue.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/bounded_onelock_prio_queue.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,348 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_BOUNDED_ONELOCK_PRIO_QUEUE_H
+#define BOOST_TASK_BOUNDED_ONELOCK_PRIO_QUEUE_H
+
+#include <algorithm>
+#include <cstddef>
+#include <functional>
+#include <queue>
+
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+
+#include <boost/task/callable.hpp>
+#include <boost/task/detail/atomic.hpp>
+#include <boost/task/detail/meta.hpp>
+#include <boost/task/exceptions.hpp>
+#include <boost/task/watermark.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost { namespace task
+{
+template<
+ typename Attr,
+ typename Comp = std::less< Attr >
+>
+class bounded_onelock_prio_queue
+{
+public:
+ typedef detail::has_attribute attribute_tag_type;
+ typedef Attr attribute_type;
+
+ struct value_type
+ {
+ callable ca;
+ attribute_type attr;
+
+ value_type(
+ callable const& ca_,
+ attribute_type const& attr_)
+ : ca( ca_), attr( attr_)
+ { BOOST_ASSERT( ! ca.empty() ); }
+
+ void swap( value_type & other)
+ {
+ ca.swap( other.ca);
+ std::swap( attr, other.attr);
+ }
+ };
+
+private:
+ struct compare : public std::binary_function< value_type, value_type, bool >
+ {
+ bool operator()( value_type const& va1, value_type const& va2)
+ { return Comp()( va1.attr, va2.attr); }
+ };
+
+ typedef std::priority_queue<
+ value_type,
+ std::deque< value_type >,
+ compare
+ > queue_type;
+
+ volatile uint32_t state_;
+ queue_type queue_;
+ shared_mutex mtx_;
+ condition not_empty_cond_;
+ condition not_full_cond_;
+ std::size_t hwm_;
+ std::size_t lwm_;
+
+ bool active_() const
+ { return 0 == state_; }
+
+ void deactivate_()
+ { detail::atomic_fetch_add( & state_, 1); }
+
+ 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_(
+ value_type const& va,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( full_() )
+ {
+ not_full_cond_.wait(
+ lk,
+ bind(
+ & bounded_onelock_prio_queue::producers_activate_,
+ this) );
+ }
+ if ( ! active_() )
+ throw task_rejected("queue is not active");
+ queue_.push( va);
+ not_empty_cond_.notify_one();
+ }
+
+ template< typename Duration >
+ void put_(
+ value_type const& va,
+ Duration const& rel_time,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( full_() )
+ {
+ if ( ! not_full_cond_.timed_wait(
+ lk,
+ rel_time,
+ bind(
+ & bounded_onelock_prio_queue::producers_activate_,
+ this) ) )
+ throw task_rejected("timed out");
+ }
+ if ( ! active_() )
+ throw task_rejected("queue is not active");
+ queue_.push( va);
+ not_empty_cond_.notify_one();
+ }
+
+ bool take_(
+ callable & ca,
+ unique_lock< shared_mutex > & lk)
+ {
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ not_empty_cond_.wait(
+ lk,
+ bind(
+ & bounded_onelock_prio_queue::consumers_activate_,
+ this) );
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ callable tmp( queue_.top().ca);
+ queue_.pop();
+ ca.swap( tmp);
+ 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_(
+ callable & ca,
+ Duration const& rel_time,
+ unique_lock< shared_mutex > & lk)
+ {
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ if ( ! not_empty_cond_.timed_wait(
+ lk,
+ rel_time,
+ bind(
+ & bounded_onelock_prio_queue::consumers_activate_,
+ this) ) )
+ return false;
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ callable tmp( queue_.top().ca);
+ queue_.pop();
+ ca.swap( tmp);
+ if ( size_() <= lwm_)
+ {
+ if ( lwm_ == hwm_)
+ not_full_cond_.notify_one();
+ else
+ // more than one producer could be waiting
+ // in order to submit an task
+ not_full_cond_.notify_all();
+ }
+ return ! ca.empty();
+ }
+
+ bool try_take_( callable & ca)
+ {
+ if ( empty_() )
+ return false;
+ callable tmp( queue_.top().ca);
+ queue_.pop();
+ ca.swap( tmp);
+ bool valid = ! ca.empty();
+ if ( valid && size_() <= lwm_)
+ {
+ if ( lwm_ == hwm_)
+ not_full_cond_.notify_one();
+ else
+ // more than one producer could be waiting
+ // in order to submit an task
+ not_full_cond_.notify_all();
+ }
+ return valid;
+ }
+
+ bool producers_activate_() const
+ { return ! active_() || ! full_(); }
+
+ bool consumers_activate_() const
+ { return ! active_() || ! empty_(); }
+
+public:
+ bounded_onelock_prio_queue(
+ high_watermark const& hwm,
+ low_watermark const& lwm)
+ :
+ state_( 0),
+ 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");
+ }
+
+ void deactivate()
+ { deactivate_(); }
+
+ bool empty()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return empty_();
+ }
+
+ 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);
+ }
+
+ void put( value_type const& va)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( va, lk);
+ }
+
+ template< typename Duration >
+ void put(
+ value_type const& va,
+ Duration const& rel_time)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( va, rel_time, lk);
+ }
+
+ bool take( callable & ca)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, lk);
+ }
+
+ template< typename Duration >
+ bool take(
+ callable & ca,
+ Duration const& rel_time)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, rel_time, lk);
+ }
+
+ bool try_take( callable & ca)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return try_take_( ca);
+ }
+};
+} }
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_TASK_BOUNDED_ONELOCK_PRIO_QUEUE_H
Added: sandbox/task/boost/task/bounded_onelock_smart_queue.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/bounded_onelock_smart_queue.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,355 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_BOUNDED_ONELOCK_SMART_QUEUE_H
+#define BOOST_TASK_BOUNDED_ONELOCK_SMART_QUEUE_H
+
+#include <algorithm>
+#include <cstddef>
+
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+
+#include <boost/task/callable.hpp>
+#include <boost/task/detail/atomic.hpp>
+#include <boost/task/detail/meta.hpp>
+#include <boost/task/detail/smart.hpp>
+#include <boost/task/exceptions.hpp>
+#include <boost/task/watermark.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost { namespace task
+{
+template<
+ typename Attr,
+ typename Comp,
+ typename Enq = detail::replace_oldest,
+ typename Deq = detail::take_oldest
+>
+class bounded_onelock_smart_queue
+{
+public:
+ typedef detail::has_attribute attribute_tag_type;
+ typedef Attr attribute_type;
+
+ struct value_type
+ {
+ callable ca;
+ attribute_type attr;
+
+ value_type(
+ callable const& ca_,
+ attribute_type const& attr_)
+ : ca( ca_), attr( attr_)
+ { BOOST_ASSERT( ! ca.empty() ); }
+
+ void swap( value_type & other)
+ {
+ ca.swap( other.ca);
+ std::swap( attr, other.attr);
+ }
+ };
+
+private:
+ typedef multi_index::multi_index_container<
+ value_type,
+ multi_index::indexed_by<
+ multi_index::ordered_non_unique<
+ multi_index::member<
+ value_type,
+ Attr,
+ & value_type::attr
+ >,
+ Comp
+ >
+ >
+ > queue_type;
+ typedef typename queue_type::template nth_index< 0 >::type queue_index;
+
+ volatile uint32_t state_;
+ queue_type queue_;
+ queue_index & idx_;
+ shared_mutex mtx_;
+ condition not_empty_cond_;
+ condition not_full_cond_;
+ Enq enq_op_;
+ Deq deq_op_;
+ std::size_t hwm_;
+ std::size_t lwm_;
+
+ bool active_() const
+ { return 0 == state_; }
+
+ void deactivate_()
+ { detail::atomic_fetch_add( & state_, 1); }
+
+ 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_(
+ value_type const& va,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( full_() )
+ {
+ not_full_cond_.wait(
+ lk,
+ bind(
+ & bounded_onelock_smart_queue::producers_activate_,
+ this) );
+ }
+ if ( ! active_() )
+ throw task_rejected("queue is not active");
+ enq_op_( idx_, va);
+ not_empty_cond_.notify_one();
+ }
+
+ template< typename Duration >
+ void put_(
+ value_type const& va,
+ Duration const& rel_time,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( full_() )
+ {
+ if ( ! not_full_cond_.timed_wait(
+ lk,
+ rel_time,
+ bind(
+ & bounded_onelock_smart_queue::producers_activate_,
+ this) ) )
+ throw task_rejected("timed out");
+ }
+ if ( ! active_() )
+ throw task_rejected("queue is not active");
+ enq_op_( idx_, va);
+ not_empty_cond_.notify_one();
+ }
+
+ bool take_(
+ callable & ca,
+ unique_lock< shared_mutex > & lk)
+ {
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ not_empty_cond_.wait(
+ lk,
+ bind(
+ & bounded_onelock_smart_queue::consumers_activate_,
+ this) );
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ deq_op_( idx_, ca);
+ 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_(
+ callable & ca,
+ Duration const& rel_time,
+ unique_lock< shared_mutex > & lk)
+ {
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ if ( ! not_empty_cond_.timed_wait(
+ lk,
+ rel_time,
+ bind(
+ & bounded_onelock_smart_queue::consumers_activate_,
+ this) ) )
+ return false;
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ deq_op_( idx_, ca);
+ if ( size_() <= lwm_)
+ {
+ if ( lwm_ == hwm_)
+ not_full_cond_.notify_one();
+ else
+ // more than one producer could be waiting
+ // in order to submit an task
+ not_full_cond_.notify_all();
+ }
+ return ! ca.empty();
+ }
+
+ bool try_take_( callable & ca)
+ {
+ if ( empty_() )
+ return false;
+ deq_op_( idx_, ca);
+ bool valid = ! ca.empty();
+ if ( valid && size_() <= lwm_)
+ {
+ if ( lwm_ == hwm_)
+ not_full_cond_.notify_one();
+ else
+ // more than one producer could be waiting
+ // in order to submit an task
+ not_full_cond_.notify_all();
+ }
+ return valid;
+ }
+
+ bool producers_activate_() const
+ { return ! active_() || ! full_(); }
+
+ bool consumers_activate_() const
+ { return ! active_() || ! empty_(); }
+
+public:
+ bounded_onelock_smart_queue(
+ high_watermark const& hwm,
+ low_watermark const& lwm)
+ :
+ state_( 0),
+ queue_(),
+ idx_( queue_.get< 0 >() ),
+ mtx_(),
+ not_empty_cond_(),
+ not_full_cond_(),
+ enq_op_(),
+ deq_op_(),
+ hwm_( hwm),
+ lwm_( lwm)
+ {
+ if ( lwm_ > hwm_ )
+ throw invalid_watermark("low watermark must be less than or equal to high watermark");
+ }
+
+ void deactivate()
+ { deactivate_(); }
+
+ bool empty()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return empty_();
+ }
+
+ 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);
+ }
+
+ void put( value_type const& va)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( va, lk);
+ }
+
+ template< typename Duration >
+ void put(
+ value_type const& va,
+ Duration const& rel_time)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( va, rel_time, lk);
+ }
+
+ bool take( callable & ca)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, lk);
+ }
+
+ template< typename Duration >
+ bool take(
+ callable & ca,
+ Duration const& rel_time)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, rel_time, lk);
+ }
+
+ bool try_take( callable & ca)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return try_take_( ca);
+ }
+};
+} }
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_TASK_BOUNDED_ONELOCK_SMART_QUEUE_H
Added: sandbox/task/boost/task/bounded_twolock_fifo.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/bounded_twolock_fifo.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,275 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_BOUNDED_TWOLOCK_FIFO_H
+#define BOOST_TASK_BOUNDED_TWOLOCK_FIFO_H
+
+#include <cstddef>
+
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+
+#include <boost/task/callable.hpp>
+#include <boost/task/detail/atomic.hpp>
+#include <boost/task/detail/meta.hpp>
+#include <boost/task/exceptions.hpp>
+#include <boost/task/watermark.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost { namespace task
+{
+class bounded_twolock_fifo
+{
+public:
+ typedef detail::has_no_attribute attribute_tag_type;
+ typedef callable value_type;
+
+private:
+ struct node
+ {
+ typedef shared_ptr< node > sptr_t;
+
+ value_type va;
+ sptr_t next;
+ };
+
+ volatile uint32_t state_;
+ volatile uint32_t count_;
+ node::sptr_t head_;
+ mutex head_mtx_;
+ node::sptr_t tail_;
+ mutex tail_mtx_;
+ condition not_empty_cond_;
+ condition not_full_cond_;
+ std::size_t hwm_;
+ std::size_t lwm_;
+
+ bool active_() const
+ { return 0 == state_; }
+
+ void deactivate_()
+ { detail::atomic_fetch_add( & state_, 1); }
+
+ uint32_t size_()
+ { return count_; }
+
+ bool empty_()
+ { return head_ == get_tail_(); }
+
+ bool full_()
+ { return size_() >= hwm_; }
+
+ node::sptr_t get_tail_()
+ {
+ lock_guard< mutex > lk( tail_mtx_);
+ node::sptr_t tmp = tail_;
+ return tmp;
+ }
+
+ node::sptr_t pop_head_()
+ {
+ node::sptr_t old_head = head_;
+ head_ = old_head->next;
+ detail::atomic_fetch_sub( & count_, 1);
+ return old_head;
+ }
+
+public:
+ bounded_twolock_fifo(
+ high_watermark const& hwm,
+ low_watermark const& lwm)
+ :
+ state_( 0),
+ count_( 0),
+ head_( new node),
+ head_mtx_(),
+ tail_( head_),
+ tail_mtx_(),
+ not_empty_cond_(),
+ not_full_cond_(),
+ hwm_( hwm),
+ lwm_( lwm)
+ {}
+
+ 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();
+ }
+
+ std::size_t upper_bound()
+ { return hwm_; }
+
+ 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();
+ }
+
+ std::size_t lower_bound()
+ { return lwm_; }
+
+ void deactivate()
+ { deactivate_(); }
+
+ bool empty()
+ {
+ unique_lock< mutex > lk( head_mtx_);
+ return empty_();
+ }
+
+ void put( value_type const& va)
+ {
+ node::sptr_t new_node( new node);
+ {
+ unique_lock< mutex > lk( tail_mtx_);
+
+ if ( full_() )
+ {
+ while ( active_() && full_() )
+ not_full_cond_.wait( lk);
+ }
+ if ( ! active_() )
+ throw task_rejected("queue is not active");
+
+ tail_->va = va;
+ tail_->next = new_node;
+ tail_ = new_node;
+ detail::atomic_fetch_add( & count_, 1);
+ }
+ not_empty_cond_.notify_one();
+ }
+
+ template< typename Duration >
+ void put(
+ value_type const& va,
+ Duration const& rel_time)
+ {
+ node::sptr_t new_node( new node);
+ {
+ unique_lock< mutex > lk( tail_mtx_);
+
+ if ( full_() )
+ {
+ while ( active_() && full_() )
+ if ( ! not_full_cond_.wait( lk, rel_time) )
+ throw task_rejected("timed out");
+ }
+ if ( ! active_() )
+ throw task_rejected("queue is not active");
+
+ tail_->va = va;
+ tail_->next = new_node;
+ tail_ = new_node;
+ detail::atomic_fetch_add( & count_, 1);
+ }
+ not_empty_cond_.notify_one();
+ }
+
+ bool take( value_type & va)
+ {
+ unique_lock< mutex > lk( head_mtx_);
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ while ( active_() && empty_() )
+ not_empty_cond_.wait( lk);
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ va.swap( head_->va);
+ pop_head_();
+ 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 ! va.empty();
+ }
+
+ template< typename Duration >
+ bool take(
+ value_type & va,
+ Duration const& rel_time)
+ {
+ unique_lock< mutex > lk( head_mtx_);
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ while ( active_() && empty_() )
+ if ( ! not_empty_cond_.timed_wait( lk, rel_time) )
+ return false;
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ va.swap( head_->va);
+ pop_head_();
+ 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 ! va.empty();
+ }
+
+ bool try_take( value_type & va)
+ {
+ unique_lock< mutex > lk( head_mtx_);
+ if ( empty_() )
+ return false;
+ va.swap( head_->va);
+ pop_head_();
+ bool valid = ! va.empty();
+ if ( valid && size_() <= lwm_)
+ {
+ if ( lwm_ == hwm_)
+ not_full_cond_.notify_one();
+ else
+ // more than one producer could be waiting
+ // in order to submit an task
+ not_full_cond_.notify_all();
+ }
+ return valid;
+ }
+};
+} }
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_TASK_BOUNDED_TWOLOCK_FIFO_H
Modified: sandbox/task/boost/task/callable.hpp
==============================================================================
--- sandbox/task/boost/task/callable.hpp (original)
+++ sandbox/task/boost/task/callable.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -11,8 +11,8 @@
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
+#include <boost/task/context.hpp>
#include <boost/task/detail/config.hpp>
-#include <boost/task/detail/interrupter.hpp>
#include <boost/task/task.hpp>
#include <boost/config/abi_prefix.hpp>
@@ -25,18 +25,13 @@
namespace boost { namespace task
{
-class context;
-
class BOOST_TASK_DECL callable
{
private:
- friend class context;
-
struct impl
{
virtual ~impl() {}
virtual void run() = 0;
- virtual void reset() = 0;
virtual void reset( shared_ptr< thread > const&) = 0;
};
@@ -44,46 +39,41 @@
class impl_wrapper : public impl
{
private:
- task< R > t_;
- detail::interrupter intr_;
+ task< R > t_;
+ context ctx_;
public:
impl_wrapper(
task< R > t,
- detail::interrupter const& intr)
- : t_( boost::move( t) ), intr_( intr)
+ context const& ctx)
+ : t_( boost::move( t) ), ctx_( ctx)
{}
void run()
{ t_(); }
- void reset()
- { intr_.reset(); }
-
void reset( shared_ptr< thread > const& thrd)
- { intr_.reset( thrd); }
+ { ctx_.reset( thrd); }
};
shared_ptr< impl > impl_;
+public:
+ callable();
+
template< typename R >
callable(
task< R > t,
- detail::interrupter const& intr)
- : impl_( new impl_wrapper< R >( boost::move( t), intr) )
+ context const& ctx)
+ : impl_( new impl_wrapper< R >( boost::move( t), ctx) )
{}
-public:
- callable();
-
void operator()();
bool empty() const;
void clear();
- void reset();
-
void reset( shared_ptr< thread > const&);
void swap( callable &);
@@ -100,7 +90,7 @@
{ ca_.reset( thrd); }
~context_guard()
- { ca_.reset(); }
+ { ca_.clear(); }
};
}}
Modified: sandbox/task/boost/task/context.hpp
==============================================================================
--- sandbox/task/boost/task/context.hpp (original)
+++ sandbox/task/boost/task/context.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -8,36 +8,67 @@
#define BOOST_TASK_CONTEXT_H
#include <boost/shared_ptr.hpp>
-#include <boost/thread/detail/move.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>
-#include <boost/task/callable.hpp>
-#include <boost/task/detail/interrupter.hpp>
-#include <boost/task/future.hpp>
-#include <boost/task/handle.hpp>
-#include <boost/task/task.hpp>
+#include <boost/task/detail/config.hpp>
#include <boost/config/abi_prefix.hpp>
+# if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable:4251 4275)
+# endif
+
namespace boost { namespace task
{
-
-class context
+class BOOST_TASK_DECL context
{
private:
- detail::interrupter intr_;
+ class impl : private noncopyable
+ {
+ private:
+ bool requested_;
+ mutex mtx_;
+ shared_ptr< thread > thrd_;
+
+ void reset_( shared_ptr< thread > const& thrd);
+
+ void interrupt_();
+
+ public:
+ impl();
+
+ void reset( shared_ptr< thread > const& thrd);
+
+ void interrupt();
+
+ bool interruption_requested();
+ };
+
+ shared_ptr< impl > impl_;
public:
- template< typename R >
- callable get_callable( task< R > t)
- { return callable( boost::move( t), intr_); }
-
- template< typename R >
- handle< R > get_handle( shared_future< R > f)
- { return handle< R >( f, intr_); }
-};
+ context();
+
+ void reset( shared_ptr< thread > const& thrd);
+
+ void interrupt();
+ bool interruption_requested();
+
+ void swap( context & other);
+};
}}
+# if defined(BOOST_MSVC)
+# pragma warning(pop)
+# endif
+
#include <boost/config/abi_suffix.hpp>
-#endif // BOOST_TASK_CONTEXT_H
+#endif // BOOST_TASK_DETAIL_context_H
Modified: sandbox/task/boost/task/detail/atomic_gcc_ppc.hpp
==============================================================================
--- sandbox/task/boost/task/detail/atomic_gcc_ppc.hpp (original)
+++ sandbox/task/boost/task/detail/atomic_gcc_ppc.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -51,7 +51,7 @@
: "memory", "cc"
);
- return ++r;
+ return r;
}
inline
@@ -73,7 +73,7 @@
: "memory", "cc"
);
- return --r;
+ return r;
}
} } }
Modified: sandbox/task/boost/task/detail/atomic_gcc_x86.hpp
==============================================================================
--- sandbox/task/boost/task/detail/atomic_gcc_x86.hpp (original)
+++ sandbox/task/boost/task/detail/atomic_gcc_x86.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -41,7 +41,7 @@
"memory", "cc"
);
- return ++r;
+ return r;
}
inline
@@ -59,7 +59,7 @@
"memory", "cc"
);
- return --r;
+ return r;
}
} } }
Modified: sandbox/task/boost/task/detail/atomic_interlocked.hpp
==============================================================================
--- sandbox/task/boost/task/detail/atomic_interlocked.hpp (original)
+++ sandbox/task/boost/task/detail/atomic_interlocked.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -25,14 +25,14 @@
uint32_t atomic_fetch_add( uint32_t volatile * object, uint32_t operand)
{
BOOST_ASSERT( operand == 1);
- return BOOST_INTERLOCKED_INCREMENT( reinterpret_cast< long volatile * >( object) );
+ return BOOST_INTERLOCKED_INCREMENT( reinterpret_cast< long volatile * >( object) ) - 1;
}
inline
uint32_t atomic_fetch_sub( uint32_t volatile * object, uint32_t operand)
{
BOOST_ASSERT( operand == 1);
- return BOOST_INTERLOCKED_DECREMENT( reinterpret_cast< long volatile * >( object) );
+ return BOOST_INTERLOCKED_DECREMENT( reinterpret_cast< long volatile * >( object) ) + 1;
}
} } }
Modified: sandbox/task/boost/task/detail/atomic_solaris.hpp
==============================================================================
--- sandbox/task/boost/task/detail/atomic_solaris.hpp (original)
+++ sandbox/task/boost/task/detail/atomic_solaris.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -29,14 +29,14 @@
uint32_t atomic_fetch_add( uint32_t volatile * object, uint32_t operand)
{
BOOST_ASSERT( operand == 1);
- return ::atomic_inc_32_nv( object);
+ return ::atomic_inc_32( object);
}
inline
uint32_t atomic_fetch_sub( uint32_t volatile * object, uint32_t operand)
{
BOOST_ASSERT( operand == 1);
- return ::atomic_dec_32_nv( object);
+ return ::atomic_dec_32( object);
}
} } }
Modified: sandbox/task/boost/task/detail/atomic_sync.hpp
==============================================================================
--- sandbox/task/boost/task/detail/atomic_sync.hpp (original)
+++ sandbox/task/boost/task/detail/atomic_sync.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -33,14 +33,14 @@
uint32_t atomic_fetch_add( uint32_t volatile * object, uint32_t operand)
{
BOOST_ASSERT( operand == 1);
- return __sync_add_and_fetch( object, 1);
+ return __sync_fetch_and_add( object, 1);
}
inline
uint32_t atomic_fetch_sub( uint32_t volatile * object, uint32_t operand)
{
BOOST_ASSERT( operand == 1);
- return __sync_add_and_fetch( object, -1);
+ return __sync_fetch_and_add( object, -1);
}
} } }
Modified: sandbox/task/boost/task/detail/fiber_posix.hpp
==============================================================================
--- sandbox/task/boost/task/detail/fiber_posix.hpp (original)
+++ sandbox/task/boost/task/detail/fiber_posix.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -80,33 +80,17 @@
{ return state_ == st_exited; }
void exit_()
- {
- if ( ::swapcontext( & callee_, & caller_) == -1)
- throw system::system_error(
- system::error_code(
- errno,
- system::system_category) );
- }
+ { BOOST_ASSERT( ::swapcontext( & callee_, & caller_) != -1); }
void switch_to_( fiber & to)
{
std::swap( caller_, to.caller_);
std::swap( state_, to.state_);
- if ( ::swapcontext( & callee_, & to.callee_) == -1)
- throw system::system_error(
- system::error_code(
- errno,
- system::system_category) );
+ BOOST_ASSERT( ::swapcontext( & callee_, & to.callee_) != -1);
}
void run_()
- {
- if ( ::swapcontext( & caller_, & callee_) == -1)
- throw system::system_error(
- system::error_code(
- errno,
- system::system_category) );
- }
+ { BOOST_ASSERT( ::swapcontext( & caller_, & callee_) != -1); }
void init_()
{
Modified: sandbox/task/boost/task/detail/fiber_windows.hpp
==============================================================================
--- sandbox/task/boost/task/detail/fiber_windows.hpp (original)
+++ sandbox/task/boost/task/detail/fiber_windows.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -147,6 +147,7 @@
void switch_to( sptr_t & to)
{
+ BOOST_ASSERT( to);
BOOST_ASSERT( running_() );
if ( to->uninitialized_() ) to->init_();
switch_to_( * to);
@@ -155,8 +156,8 @@
void run()
{
- BOOST_ASSERT( uninitialized_() || ready_() );
- if ( uninitialized_() ) init_();
+ BOOST_ASSERT( uninitialized_() );
+ init_();
BOOST_ASSERT( ready_() );
state_ = st_running;
run_();
@@ -165,7 +166,7 @@
void exit()
{
- BOOST_ASSERT( running_() || ready_() ) ;
+ BOOST_ASSERT( running_() ) ;
state_ = st_exited;
exit_();
BOOST_ASSERT(!"should never be reached");
Deleted: sandbox/task/boost/task/detail/interrupter.hpp
==============================================================================
--- sandbox/task/boost/task/detail/interrupter.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
+++ (empty file)
@@ -1,82 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_TASK_DETAIL_INTERRUPTER_H
-#define BOOST_TASK_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>
-
-#include <boost/task/detail/config.hpp>
-
-#include <boost/config/abi_prefix.hpp>
-
-# if defined(BOOST_MSVC)
-# pragma warning(push)
-# pragma warning(disable:4251 4275)
-# endif
-
-namespace boost { namespace task
-{
-namespace detail
-{
-class BOOST_TASK_DECL interrupter
-{
-private:
- class impl : private noncopyable
- {
- private:
- bool requested_;
- mutex mtx_;
- shared_ptr< thread > thrd_;
-
- void reset_();
-
- void reset_( shared_ptr< thread > const& thrd);
-
- void interrupt_();
-
- public:
- impl();
-
- void reset();
-
- void reset( shared_ptr< thread > const& thrd);
-
- void interrupt();
-
- bool interruption_requested();
- };
-
- shared_ptr< impl > impl_;
-
-public:
- interrupter();
-
- void reset();
-
- void reset( shared_ptr< thread > const& thrd);
-
- void interrupt();
-
- bool interruption_requested();
-
- void swap( interrupter & other);
-};
-}}}
-
-# if defined(BOOST_MSVC)
-# pragma warning(pop)
-# endif
-
-#include <boost/config/abi_suffix.hpp>
-
-#endif // BOOST_TASK_DETAIL_INTERRUPTER_H
Modified: sandbox/task/boost/task/detail/pool_base.hpp
==============================================================================
--- sandbox/task/boost/task/detail/pool_base.hpp (original)
+++ sandbox/task/boost/task/detail/pool_base.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -39,7 +39,7 @@
namespace detail
{
-template< typename Channel, typename UMS >
+template< typename Queue, typename UMS >
class pool_base
{
private:
@@ -48,15 +48,14 @@
template< typename T, typename X, typename Z >
friend class worker_object;
- typedef Channel channel;
- typedef typename channel::item channel_item;
+ typedef Queue queue_type;
+ typedef typename queue_type::value_type value_type;
UMS ums_;
worker_group wg_;
shared_mutex mtx_wg_;
volatile uint32_t state_;
- channel channel_;
- volatile uint32_t active_worker_;
+ queue_type queue_;
volatile uint32_t idle_worker_;
void worker_entry_()
@@ -118,12 +117,6 @@
}
# endif
- std::size_t active_() const
- { return active_worker_; }
-
- std::size_t idle_() const
- { return size_() - active_(); }
-
std::size_t size_() const
{ return wg_.size(); }
@@ -131,7 +124,7 @@
{ return state_ > 0; }
bool close_()
- { return atomic_fetch_add( & state_, 1) > 1; }
+ { return atomic_fetch_add( & state_, 1) > 0; }
public:
explicit pool_base(
@@ -144,13 +137,11 @@
wg_(),
mtx_wg_(),
state_( 0),
- channel_(),
- active_worker_( 0),
+ queue_(),
idle_worker_( 0)
{
if ( asleep.is_special() || asleep.is_negative() )
throw invalid_timeduration();
- channel_.activate();
lock_guard< shared_mutex > lk( mtx_wg_);
for ( std::size_t i( 0); i < psize; ++i)
create_worker_( psize, asleep, max_scns, stack_size);
@@ -167,15 +158,13 @@
wg_(),
mtx_wg_(),
state_( 0),
- channel_(
+ queue_(
hwm,
lwm),
- active_worker_( 0),
idle_worker_( 0)
{
if ( asleep.is_special() || asleep.is_negative() )
throw invalid_timeduration();
- channel_.activate();
lock_guard< shared_mutex > lk( mtx_wg_);
for ( std::size_t i( 0); i < psize; ++i)
create_worker_( psize, asleep, max_scns, stack_size);
@@ -190,15 +179,13 @@
wg_(),
mtx_wg_(),
state_( 0),
- channel_(),
- active_worker_( 0),
+ queue_(),
idle_worker_( 0)
{
if ( asleep.is_special() || asleep.is_negative() )
throw invalid_timeduration();
poolsize psize( thread::hardware_concurrency() );
BOOST_ASSERT( psize > 0);
- channel_.activate();
lock_guard< shared_mutex > lk( mtx_wg_);
for ( std::size_t i( 0); i < psize; ++i)
create_worker_( psize, asleep, max_scns, stack_size, i);
@@ -214,17 +201,15 @@
wg_(),
mtx_wg_(),
state_( 0),
- channel_(
+ queue_(
hwm,
lwm),
- active_worker_( 0),
idle_worker_( 0)
{
if ( asleep.is_special() || asleep.is_negative() )
throw invalid_timeduration();
poolsize psize( thread::hardware_concurrency() );
BOOST_ASSERT( psize > 0);
- channel_.activate();
lock_guard< shared_mutex > lk( mtx_wg_);
for ( std::size_t i( 0); i < psize; ++i)
create_worker_( psize, asleep, max_scns, stack_size, i);
@@ -234,18 +219,6 @@
~pool_base()
{ shutdown(); }
- std::size_t active()
- {
- shared_lock< shared_mutex > lk( mtx_wg_);
- return active_();
- }
-
- std::size_t idle()
- {
- shared_lock< shared_mutex > lk( mtx_wg_);
- return idle_();
- }
-
void interrupt_all_worker()
{
if ( closed_() ) return;
@@ -258,7 +231,7 @@
{
if ( closed_() || close_() ) return;
- channel_.deactivate();
+ queue_.deactivate();
shared_lock< shared_mutex > lk( mtx_wg_);
wg_.signal_shutdown_all();
wg_.join_all();
@@ -268,7 +241,7 @@
{
if ( closed_() || close_() ) return;
- channel_.deactivate_now();
+ queue_.deactivate();
shared_lock< shared_mutex > lk( mtx_wg_);
wg_.signal_shutdown_now_all();
wg_.interrupt_all();
@@ -284,26 +257,17 @@
bool closed()
{ return closed_(); }
- 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(); }
+ { return queue_.upper_bound(); }
void upper_bound( high_watermark const& hwm)
- { channel_.upper_bound( hwm); }
+ { queue_.upper_bound( hwm); }
std::size_t lower_bound()
- { return channel_.lower_bound(); }
+ { return queue_.lower_bound(); }
void lower_bound( low_watermark const lwm)
- { channel_.lower_bound( lwm); }
+ { queue_.lower_bound( lwm); }
template< typename R >
handle< R > submit( task< R > t)
@@ -313,9 +277,8 @@
shared_future< R > f( t.get_future() );
context ctx;
- handle< R > h( ctx.get_handle( f) );
- channel_.put(
- ctx.get_callable( boost::move( t) ) );
+ handle< R > h( f, ctx);
+ queue_.put( callable( boost::move( t), ctx) );
return h;
}
@@ -327,10 +290,10 @@
shared_future< R > f( t.get_future() );
context ctx;
- handle< R > h( ctx.get_handle( f) );
- channel_.put(
- channel_item(
- ctx.get_callable( boost::move( t) ),
+ handle< R > h( f, ctx);
+ queue_.put(
+ value_type(
+ callable( boost::move( t), ctx),
attr) );
return h;
}
Added: sandbox/task/boost/task/detail/smart.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/smart.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,65 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_DETAIL_SMART_H
+#define BOOST_DETAIL_SMART_H
+
+#include <boost/task/callable.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost { namespace task {
+namespace detail
+{
+struct replace_oldest
+{
+ template<
+ typename PrioIndex,
+ typename Value
+ >
+ void operator()( PrioIndex & idx, Value const& va)
+ {
+ typedef typename PrioIndex::iterator iterator;
+ iterator i( idx.find( va.attr) );
+ if ( i == idx.end() )
+ idx.insert( va);
+ else
+ idx.replace( i, va);
+ }
+};
+
+struct take_oldest
+{
+ class swapper
+ {
+ private:
+ callable & ca_;
+
+ public:
+ swapper( callable & ca)
+ : ca_( ca)
+ {}
+
+ template< typename Value >
+ void operator()( Value & va)
+ { ca_.swap( va.ca); }
+ };
+
+ template< typename PrioIndex >
+ void operator()( PrioIndex & idx, callable & ca)
+ {
+ typedef typename PrioIndex::iterator iterator;
+ iterator i( idx.begin() );
+ BOOST_ASSERT( i != idx.end() );
+ idx.modify( i, swapper( ca) );
+ idx.erase( i);
+ }
+};
+}}}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_TASK_DETAIL_SMART_H
Modified: sandbox/task/boost/task/detail/worker.hpp
==============================================================================
--- sandbox/task/boost/task/detail/worker.hpp (original)
+++ sandbox/task/boost/task/detail/worker.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -8,8 +8,6 @@
#define BOOST_TASK_DETAIL_WORKER_H
#include <cstddef>
-#include <list>
-#include <set>
#include <utility>
#include <boost/assert.hpp>
@@ -23,7 +21,6 @@
#include <boost/task/detail/config.hpp>
#include <boost/task/detail/fiber.hpp>
#include <boost/task/detail/guard.hpp>
-#include <boost/task/detail/interrupter.hpp>
#include <boost/task/detail/wsq.hpp>
#include <boost/task/poolsize.hpp>
#include <boost/task/scanns.hpp>
@@ -113,7 +110,6 @@
void execute_( callable & ca)
{
BOOST_ASSERT( ! ca.empty() );
- guard grd( pool_.active_worker_);
{
context_guard lk( ca, thrd_);
ca();
@@ -125,10 +121,10 @@
bool take_global_callable_(
callable & ca,
posix_time::time_duration const& asleep)
- { return pool_.channel_.take( ca, asleep); }
+ { return pool_.queue_.take( ca, asleep); }
bool try_take_global_callable_( callable & ca)
- { return pool_.channel_.try_take( ca); }
+ { return pool_.queue_.try_take( ca); }
bool try_take_local_callable_( callable & ca)
{ return wsq_.try_take( ca); }
@@ -207,15 +203,46 @@
void run_()
{
- BOOST_ASSERT( fib_->running() );
while ( ! shutdown_() )
- process_( true);
- BOOST_ASSERT( fib_->running() );
+ {
+ try_blocked_fibers_();
+ callable ca;
+ if ( try_take_local_callable_( ca) ||
+ try_steal_other_callable_( ca) ||
+ try_take_global_callable_( ca) )
+ {
+ execute_( ca);
+ scns_ = 0;
+ }
+ else
+ {
+ guard grd( pool_.idle_worker_);
+ ++scns_;
+ if ( scns_ >= max_scns_)
+ {
+ if ( pool_.size_() > pool_.idle_worker_)
+ {
+ if ( take_global_callable_( ca, asleep_) )
+ execute_( ca);
+ }
+ else if ( ! ums_.has_blocked() )
+ {
+ try
+ { this_thread::sleep( asleep_); }
+ catch ( thread_interrupted const&)
+ { return; }
+ }
+ scns_ = 0;
+ }
+ else
+ this_thread::yield();
+ }
+ }
}
bool shutdown_()
{
- if ( shutdown__() && pool_.channel_.empty() && ! ums_.has_blocked() )
+ if ( shutdown__() && pool_.queue_.empty() && ! ums_.has_blocked() )
return true;
else if ( shutdown_now__() )
return true;
Deleted: sandbox/task/boost/task/fifo.hpp
==============================================================================
--- sandbox/task/boost/task/fifo.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
+++ (empty file)
@@ -1,70 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_TASK_FIFO_H
-#define BOOST_TASK_FIFO_H
-
-#include <cstddef>
-#include <list>
-
-#include <boost/task/callable.hpp>
-#include <boost/task/detail/meta.hpp>
-
-#include <boost/config/abi_prefix.hpp>
-
-namespace boost { namespace task
-{
-struct fifo
-{
- typedef detail::has_no_attribute attribute_tag_type;
-
- class impl
- {
- public:
- typedef callable item;
- typedef std::list< item >::iterator iterator;
- typedef std::list< item >::const_iterator const_iterator;
-
- private:
- std::list< item > lst_;
-
- public:
- void push( item const& itm)
- { lst_.push_back( itm); }
-
- void pop( callable & ca)
- {
- ca.swap( lst_.front() );
- lst_.pop_front();
- }
-
- 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(); }
- };
-};
-} }
-
-#include <boost/config/abi_suffix.hpp>
-
-#endif // BOOST_TASK_FIFO_H
Modified: sandbox/task/boost/task/handle.hpp
==============================================================================
--- sandbox/task/boost/task/handle.hpp (original)
+++ sandbox/task/boost/task/handle.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -10,7 +10,7 @@
#include <boost/thread.hpp>
#include <boost/thread/thread_time.hpp>
-#include <boost/task/detail/interrupter.hpp>
+#include <boost/task/context.hpp>
#include <boost/task/future.hpp>
#include <boost/task/exceptions.hpp>
@@ -19,32 +19,28 @@
namespace boost { namespace task
{
-class context;
-
template< typename R >
class handle
{
private:
- friend class context;
+ shared_future< R > fut_;
+ context ctx_;
- shared_future< R > fut_;
- detail::interrupter intr_;
+public:
+ handle()
+ : fut_(), ctx_()
+ {}
handle(
shared_future< R > fut,
- detail::interrupter const& intr)
+ context const& ctx)
:
fut_( fut),
- intr_( intr)
- {}
-
-public:
- handle()
- : fut_(), intr_()
+ ctx_( ctx)
{}
void interrupt()
- { intr_.interrupt(); }
+ { ctx_.interrupt(); }
void interrupt_and_wait()
{
@@ -66,7 +62,7 @@
}
bool interruption_requested()
- { return intr_.interruption_requested(); }
+ { return ctx_.interruption_requested(); }
R get()
{
@@ -132,7 +128,7 @@
void swap( handle< R > & other)
{
fut_.swap( other.fut_);
-// intr_.swap( other.intr_);
+ ctx_.swap( other.ctx_);
}
};
Added: sandbox/task/boost/task/local_rr_ums.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/local_rr_ums.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,72 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_LOCAL_RR_UMS_H
+#define BOOST_TASK_LOCAL_RR_UMS_H
+
+#include <list>
+
+#include <boost/assert.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+
+#include <boost/task/detail/fiber.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost { namespace task
+{
+class local_rr_ums
+{
+private:
+ thread_specific_ptr< std::list< detail::fiber::sptr_t > > runnable_;
+ thread_specific_ptr< std::list< detail::fiber::sptr_t > > blocked_;
+
+public:
+ local_rr_ums()
+ : runnable_(), blocked_()
+ {}
+
+ void attach()
+ {
+ runnable_.reset( new std::list< detail::fiber::sptr_t >() );
+ blocked_.reset( new std::list< detail::fiber::sptr_t >() );
+ }
+
+ bool has_runnable() const
+ { return ! runnable_->empty(); }
+
+ bool has_blocked() const
+ { return ! blocked_->empty(); }
+
+ void put_runnable( detail::fiber::sptr_t const& fib)
+ { runnable_->push_back( fib); }
+
+ void put_blocked( detail::fiber::sptr_t const& fib)
+ { blocked_->push_back( fib); }
+
+ bool try_take_runnable( detail::fiber::sptr_t & fib)
+ {
+ if ( ! has_runnable() ) return false;
+ fib = runnable_->front();
+ runnable_->pop_front();
+ return true;
+ }
+
+ bool try_take_blocked( detail::fiber::sptr_t & fib)
+ {
+ if ( ! has_blocked() ) return false;
+ fib = blocked_->front();
+ blocked_->pop_front();
+ return true;
+ }
+};
+} }
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_TASK_LOCAL_RR_UMS_H
+
Modified: sandbox/task/boost/task/meta.hpp
==============================================================================
--- sandbox/task/boost/task/meta.hpp (original)
+++ sandbox/task/boost/task/meta.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -20,7 +20,7 @@
struct has_attribute : public mpl::bool_<
is_same<
detail::has_attribute,
- typename Pool::channel::scheduler_type::attribute_tag_type
+ typename Pool::queue_type::attribute_tag_type
>::value
>
{};
@@ -28,7 +28,7 @@
template< typename Pool >
struct attribute_type
{
- typedef typename Pool::channel::scheduler_type::attribute_type type;
+ typedef typename Pool::queue_type::attribute_type type;
};
} }
Modified: sandbox/task/boost/task/new_thread.hpp
==============================================================================
--- sandbox/task/boost/task/new_thread.hpp (original)
+++ sandbox/task/boost/task/new_thread.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -13,6 +13,7 @@
#include <boost/thread.hpp>
#include <boost/thread/detail/move.hpp>
+#include <boost/task/callable.hpp>
#include <boost/task/context.hpp>
#include <boost/task/future.hpp>
#include <boost/task/handle.hpp>
@@ -66,13 +67,13 @@
handle< R > operator()( task< R > t)
{
shared_future< R > f( t.get_future() );
- context ctx;
- handle< R > h( ctx.get_handle( f) );
- callable ca( ctx.get_callable( boost::move( t) ) );
+ context ctx1, ctx2;
+ handle< R > h( f, ctx1);
+ callable ca( boost::move( t), ctx2);
shared_ptr< thread > thrd(
new thread( wrapper( ca) ),
detail::joiner() );
- ca.reset( thrd);
+ ctx1.reset( thrd);
return h;
}
Modified: sandbox/task/boost/task/own_thread.hpp
==============================================================================
--- sandbox/task/boost/task/own_thread.hpp (original)
+++ sandbox/task/boost/task/own_thread.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -27,8 +27,8 @@
{
shared_future< R > f( t.get_future() );
context ctx;
- handle< R > h( ctx.get_handle( f) );
- callable ca( ctx.get_callable( boost::move( t) ) );
+ handle< R > h( f, ctx);
+ callable ca( boost::move( t), ctx);
ca();
return h;
}
Deleted: sandbox/task/boost/task/priority.hpp
==============================================================================
--- sandbox/task/boost/task/priority.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
+++ (empty file)
@@ -1,133 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_TASK_PRIORITY_H
-#define BOOST_TASK_PRIORITY_H
-
-#include <cstddef>
-#include <utility>
-
-#include <boost/assert.hpp>
-#include <boost/multi_index_container.hpp>
-#include <boost/multi_index/member.hpp>
-#include <boost/multi_index/ordered_index.hpp>
-
-#include <boost/task/callable.hpp>
-#include <boost/task/detail/meta.hpp>
-
-#include <boost/config/abi_prefix.hpp>
-
-namespace boost { namespace task
-{
-template<
- typename Attr,
- typename Ord = std::greater< Attr >
->
-struct priority
-{
- typedef detail::has_attribute attribute_tag_type;
- typedef Attr attribute_type;
-
- class impl
- {
- private:
- typedef Attr attribute;
- typedef Ord ordering;
-
- public:
- struct item
- {
- callable ca;
- attribute attr;
-
- item(
- callable const& ca_,
- attribute const& attr_)
- : ca( ca_), attr( attr_)
- { BOOST_ASSERT( ! ca.empty() ); }
- };
-
- private:
- typedef multi_index::multi_index_container<
- item,
- multi_index::indexed_by<
- multi_index::ordered_non_unique<
- multi_index::member<
- item,
- attribute,
- & item::attr
- >,
- ordering
- >
- >
- > list;
- typedef typename list::template nth_index< 0 >::type index;
-
- class swapper
- {
- private:
- callable & ca_;
-
- public:
- swapper( callable & ca)
- : ca_( ca)
- {}
-
- void operator()( item & itm)
- { ca_.swap( itm.ca); }
- };
-
- 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)
- { lst_.insert( itm); }
-
- void pop( callable & ca)
- {
- iterator i( lst_.begin() );
- BOOST_ASSERT( i != lst_.end() );
- lst_.modify( i, swapper( ca) );
- lst_.erase( i);
- }
-
- 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(); }
- };
-};
-} }
-
-#include <boost/config/abi_suffix.hpp>
-
-#endif // BOOST_TASK_PRIORITY_H
Deleted: sandbox/task/boost/task/smart.hpp
==============================================================================
--- sandbox/task/boost/task/smart.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
+++ (empty file)
@@ -1,185 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_TASK_SMART_H
-#define BOOST_TASK_SMART_H
-
-#include <cstddef>
-
-#include <boost/assert.hpp>
-#include <boost/multi_index_container.hpp>
-#include <boost/multi_index/member.hpp>
-#include <boost/multi_index/ordered_index.hpp>
-
-#include <boost/task/callable.hpp>
-#include <boost/task/detail/meta.hpp>
-
-#include <boost/config/abi_prefix.hpp>
-
-namespace boost { namespace task
-{
-template<
- typename Attr,
- typename Ord,
- typename Enq,
- typename Deq
->
-struct smart
-{
- typedef detail::has_attribute attribute_tag_type;
- typedef Attr attribute_type;
-
- class impl
- {
- private:
- typedef Attr attribute;
- typedef Deq dequeue_op;
- typedef Enq enqueue_op;
- typedef Ord ordering;
-
- public:
- struct item
- {
- callable ca;
- attribute attr;
-
- item()
- : ca(), attr()
- {}
-
- item(
- callable const& ca_,
- attribute const& attr_)
- : ca( ca_), attr( attr_)
- { BOOST_ASSERT( ! ca.empty() ); }
-
- void swap( item & other)
- {
- ca.swap( other.ca);
- std::swap( attr, other.attr);
- }
- };
-
- private:
- typedef multi_index::multi_index_container<
- item,
- multi_index::indexed_by<
- multi_index::ordered_non_unique<
- multi_index::member<
- item,
- 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); }
-
- void pop( callable & ca)
- {
- item itm;
- deq_op_( idx_, itm);
- ca.swap( itm.ca);
- }
-
- 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 Item >
- class swapper
- {
- private:
- Item & itm_;
-
- public:
- swapper( Item & itm)
- : itm_( itm)
- {}
-
- void operator()( Item & itm)
- { itm_.swap( itm); }
- };
-
- 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() );
- idx.modify( i, swapper< Item >( itm) );
- idx.erase( i);
- }
-};
-} }
-
-#include <boost/config/abi_suffix.hpp>
-
-#endif // BOOST_TASK_SMART_H
Modified: sandbox/task/boost/task/static_pool.hpp
==============================================================================
--- sandbox/task/boost/task/static_pool.hpp (original)
+++ sandbox/task/boost/task/static_pool.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -30,13 +30,16 @@
namespace boost { namespace task
{
-template< typename Channel, typename UMS = local_rr_ums >
+template< typename Queue, typename UMS = local_rr_ums >
class static_pool
{
public:
- typedef Channel channel;
+ typedef Queue queue_type;
+ typedef UMS ums_type;
private:
+ typedef detail::pool_base< queue_type, ums_type > base_type;
+
template< typename T, typename X, typename Z >
friend class detail::worker_object;
@@ -44,7 +47,7 @@
struct tag_bind_to_processors {};
# endif
- shared_ptr< detail::pool_base< Channel, UMS > > pool_;
+ shared_ptr< base_type > pool_;
static_pool( static_pool &);
static_pool & operator=( static_pool &);
@@ -59,7 +62,7 @@
posix_time::time_duration const& asleep = posix_time::microseconds( 10),
scanns const& max_scns = scanns( 20),
stacksize const& stack_size = stacksize( 64000) )
- : pool_( new detail::pool_base< Channel, UMS >( psize, asleep, max_scns, stack_size) )
+ : pool_( new base_type( psize, asleep, max_scns, stack_size) )
{}
explicit static_pool(
@@ -69,7 +72,7 @@
posix_time::time_duration const& asleep = posix_time::microseconds( 100),
scanns const& max_scns = scanns( 20),
stacksize const& stack_size = stacksize( 64000) )
- : pool_( new detail::pool_base< Channel, UMS >( psize, hwm, lwm, asleep, max_scns, stack_size) )
+ : pool_( new base_type( psize, hwm, lwm, asleep, max_scns, stack_size) )
{}
# if defined(BOOST_HAS_PROCESSOR_BINDINGS)
@@ -78,7 +81,7 @@
posix_time::time_duration const& asleep = posix_time::microseconds( 10),
scanns const& max_scns = scanns( 20),
stacksize const& stack_size = stacksize( 64000) )
- : pool_( new detail::pool_base< Channel, UMS >( asleep, max_scns, stack_size) )
+ : pool_( new base_type( asleep, max_scns, stack_size) )
{}
explicit static_pool(
@@ -88,7 +91,7 @@
posix_time::time_duration const& asleep = posix_time::microseconds( 100),
scanns const& max_scns = scanns( 20),
stacksize const& stack_size = stacksize( 64000) )
- : pool_( new detail::pool_base< Channel, UMS >( hwm, lwm, asleep, max_scns, stack_size) )
+ : pool_( new base_type( hwm, lwm, asleep, max_scns, stack_size) )
{}
static tag_bind_to_processors bind_to_processors()
@@ -131,20 +134,6 @@
}
# endif
- std::size_t active()
- {
- if ( ! pool_)
- throw pool_moved();
- return pool_->active();
- }
-
- std::size_t idle()
- {
- if ( ! pool_)
- throw pool_moved();
- return pool_->idle();
- }
-
void interrupt_all_worker()
{
if ( ! pool_)
@@ -180,27 +169,6 @@
return pool_->closed();
}
- void clear()
- {
- if ( ! pool_)
- throw pool_moved();
- pool_->clear();
- }
-
- bool empty()
- {
- if ( ! pool_)
- throw pool_moved();
- return pool_->empty();
- }
-
- std::size_t pending()
- {
- if ( ! pool_)
- throw pool_moved();
- return pool_->pending();
- }
-
std::size_t upper_bound()
{
if ( ! pool_)
@@ -245,7 +213,7 @@
return pool_->submit( boost::move( t), attr);
}
- typedef typename shared_ptr< detail::pool_base< Channel, UMS > >::unspecified_bool_type unspecified_bool_type;
+ typedef typename shared_ptr< base_type >::unspecified_bool_type unspecified_bool_type;
operator unspecified_bool_type() const // throw()
{ return pool_; }
@@ -258,18 +226,18 @@
};
}
-template< typename Channel, typename UMS >
-void swap( task::static_pool< Channel, UMS > & l, task::static_pool< Channel, UMS > & r)
+template< typename Queue, typename UMS >
+void swap( task::static_pool< Queue, UMS > & l, task::static_pool< Queue, UMS > & r)
{ return l.swap( r); }
# if defined(BOOST_HAS_RVALUE_REFS)
-template< typename Channel, typename UMS >
-task::static_pool< Channel, UMS > && move( task::static_pool< Channel, UMS > && t)
+template< typename Queue, typename UMS >
+task::static_pool< Queue, UMS > && move( task::static_pool< Queue, UMS > && t)
{ return t; }
# else
-template< typename Channel, typename UMS >
-task::static_pool< Channel, UMS > move( boost::detail::thread_move_t< task::static_pool< Channel, UMS > > t)
-{ return task::static_pool< Channel, UMS >( t); }
+template< typename Queue, typename UMS >
+task::static_pool< Queue, UMS > move( boost::detail::thread_move_t< task::static_pool< Queue, UMS > > t)
+{ return task::static_pool< Queue, UMS >( t); }
# endif
}
Deleted: sandbox/task/boost/task/unbounded_channel.hpp
==============================================================================
--- sandbox/task/boost/task/unbounded_channel.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
+++ (empty file)
@@ -1,276 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_TASK_UNBOUNDED_CHANNEL_H
-#define BOOST_TASK_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/thread/condition.hpp>
-#include <boost/thread/locks.hpp>
-#include <boost/thread/shared_mutex.hpp>
-
-#include <boost/task/callable.hpp>
-#include <boost/task/exceptions.hpp>
-
-#include <boost/config/abi_prefix.hpp>
-
-namespace boost { namespace task
-{
-template< typename SchedulingPolicy >
-class unbounded_channel
-{
-public:
- typedef SchedulingPolicy scheduler_type;
- typedef typename scheduler_type::impl::item item;
-
-private:
- typedef typename scheduler_type::impl queue;
-
- 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< callable > drain_()
- {
- BOOST_ASSERT( deactive_now_() );
- std::vector< callable > unprocessed;
- unprocessed.reserve( queue_.size() );
- BOOST_FOREACH( callable ca, queue_)
- { unprocessed.push_back( 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)
- {
- if ( ! active_() )
- throw task_rejected("channel is not active");
- queue_.push( itm);
- not_empty_cond_.notify_one();
- }
-
- bool take_(
- callable & ca,
- unique_lock< shared_mutex > & lk)
- {
- if ( deactive_now_() || ( deactive_() && empty_() ) )
- return false;
- if ( empty_() )
- {
- try
- {
- not_empty_cond_.wait(
- lk,
- bind(
- & unbounded_channel::consumers_activate_,
- this) );
- }
- catch ( thread_interrupted const&)
- { return false; }
- }
- if ( deactive_now_() || ( deactive_() && empty_() ) )
- return false;
- queue_.pop( ca);
- return ! ca.empty();
- }
-
- template< typename Duration >
- bool take_(
- callable & ca,
- Duration const& rel_time,
- unique_lock< shared_mutex > & lk)
- {
- if ( deactive_now_() || ( deactive_() && empty_() ) )
- return false;
- if ( empty_() )
- {
- try
- {
- if ( ! not_empty_cond_.timed_wait(
- lk,
- rel_time,
- bind(
- & unbounded_channel::consumers_activate_,
- this) ) )
- return false;
- }
- catch ( thread_interrupted const&)
- { return false; }
- }
- if ( deactive_now_() || ( deactive_() && empty_() ) )
- return false;
- queue_.pop( ca);
- return ! ca.empty();
- }
-
- bool try_take_( callable & ca)
- {
- if ( deactive_now_() || empty_() )
- return false;
- queue_.pop( ca);
- 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()
- {
- lock_guard< shared_mutex > lk( mtx_);
- activate_();
- }
-
- void clear()
- {
- lock_guard< shared_mutex > lk( mtx_);
- clear_();
- }
-
- bool deactive()
- { return ! active(); }
-
- void deactivate()
- {
- lock_guard< shared_mutex > lk( mtx_);
- deactivate_();
- }
-
- void deactivate_now()
- {
- lock_guard< shared_mutex > lk( mtx_);
- deactivate_now_();
- }
-
- const std::vector< callable > drain()
- {
- lock_guard< shared_mutex > lk( mtx_);
- return drain_();
- }
-
- bool empty()
- {
- lock_guard< shared_mutex > lk( mtx_);
- return empty_();
- }
-
- bool full()
- { return false; }
-
- std::size_t size()
- {
- lock_guard< shared_mutex > lk( mtx_);
- return size_();
- }
-
- void put( item const& itm)
- {
- lock_guard< shared_mutex > lk( mtx_);
- put_( itm);
- }
-
- bool take( callable & ca)
- {
- unique_lock< shared_mutex > lk( mtx_);
- return take_( ca, lk);
- }
-
- template< typename Duration >
- bool take(
- callable & ca,
- Duration const& rel_time)
- {
- unique_lock< shared_mutex > lk( mtx_);
- return take_( ca, rel_time, lk);
- }
-
- bool try_take( callable & ca)
- {
- lock_guard< shared_mutex > lk( mtx_);
- return try_take_( ca);
- }
-};
-} }
-
-#include <boost/config/abi_suffix.hpp>
-
-#endif // BOOST_TASK_UNBOUNDED_CHANNEL_H
Added: sandbox/task/boost/task/unbounded_onelock_fifo.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/unbounded_onelock_fifo.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,179 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_UNBOUNDED_ONELOCK_FIFO_H
+#define BOOST_TASK_UNBOUNDED_ONELOCK_FIFO_H
+
+#include <cstddef>
+#include <list>
+
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+
+#include <boost/task/callable.hpp>
+#include <boost/task/detail/atomic.hpp>
+#include <boost/task/detail/meta.hpp>
+#include <boost/task/exceptions.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost { namespace task
+{
+class unbounded_onelock_fifo
+{
+public:
+ typedef detail::has_no_attribute attribute_tag_type;
+ typedef callable value_type;
+
+private:
+ typedef std::list< value_type > queue_type;
+
+ volatile uint32_t state_;
+ queue_type queue_;
+ shared_mutex mtx_;
+ condition not_empty_cond_;
+
+ bool active_() const
+ { return 0 == state_; }
+
+ void deactivate_()
+ { detail::atomic_fetch_add( & state_, 1); }
+
+ bool empty_() const
+ { return queue_.empty(); }
+
+ void put_( value_type const& va)
+ {
+ if ( ! active_() )
+ throw task_rejected("queue is not active");
+ queue_.push_back( va);
+ not_empty_cond_.notify_one();
+ }
+
+ bool take_(
+ value_type & va,
+ unique_lock< shared_mutex > & lk)
+ {
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ not_empty_cond_.wait(
+ lk,
+ bind(
+ & unbounded_onelock_fifo::consumers_activate_,
+ this) );
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ va.swap( queue_.front() );
+ queue_.pop_front();
+ return ! va.empty();
+ }
+
+ template< typename Duration >
+ bool take_(
+ value_type & va,
+ Duration const& rel_time,
+ unique_lock< shared_mutex > & lk)
+ {
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ if ( ! not_empty_cond_.timed_wait(
+ lk,
+ rel_time,
+ bind(
+ & unbounded_onelock_fifo::consumers_activate_,
+ this) ) )
+ return false;
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ va.swap( queue_.front() );
+ queue_.pop_front();
+ return ! va.empty();
+ }
+
+ bool try_take_( value_type & va)
+ {
+ if ( empty_() )
+ return false;
+ va.swap( queue_.front() );
+ queue_.pop_front();
+ return ! va.empty();
+ }
+
+ bool consumers_activate_() const
+ { return ! active_() || ! empty_(); }
+
+public:
+ unbounded_onelock_fifo()
+ :
+ state_( 0),
+ queue_(),
+ mtx_(),
+ not_empty_cond_()
+ {}
+
+ void deactivate()
+ { deactivate_(); }
+
+ bool empty()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return empty_();
+ }
+
+ void put( value_type const& va)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( va);
+ }
+
+ bool take( value_type & va)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( va, lk);
+ }
+
+ template< typename Duration >
+ bool take(
+ value_type & va,
+ Duration const& rel_time)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( va, rel_time, lk);
+ }
+
+ bool try_take( value_type & va)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return try_take_( va);
+ }
+};
+} }
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_TASK_UNBOUNDED_ONELOCK_FIFO_H
Added: sandbox/task/boost/task/unbounded_onelock_prio_queue.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/unbounded_onelock_prio_queue.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,216 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_UNBOUNDED_ONELOCK_PRIO_QUEUE_H
+#define BOOST_TASK_UNBOUNDED_ONELOCK_PRIO_QUEUE_H
+
+#include <algorithm>
+#include <cstddef>
+#include <functional>
+#include <queue>
+
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+
+#include <boost/task/callable.hpp>
+#include <boost/task/detail/atomic.hpp>
+#include <boost/task/detail/meta.hpp>
+#include <boost/task/exceptions.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost { namespace task
+{
+template<
+ typename Attr,
+ typename Comp = std::less< Attr >
+>
+class unbounded_onelock_prio_queue
+{
+public:
+ typedef detail::has_attribute attribute_tag_type;
+ typedef Attr attribute_type;
+
+ struct value_type
+ {
+ callable ca;
+ attribute_type attr;
+
+ value_type(
+ callable const& ca_,
+ attribute_type const& attr_)
+ : ca( ca_), attr( attr_)
+ { BOOST_ASSERT( ! ca.empty() ); }
+
+ void swap( value_type & other)
+ {
+ ca.swap( other.ca);
+ std::swap( attr, other.attr);
+ }
+ };
+
+private:
+ struct compare : public std::binary_function< value_type, value_type, bool >
+ {
+ bool operator()( value_type const& va1, value_type const& va2)
+ { return Comp()( va1.attr, va2.attr); }
+ };
+
+ typedef std::priority_queue<
+ value_type,
+ std::deque< value_type >,
+ compare
+ > queue_type;
+
+ volatile uint32_t state_;
+ queue_type queue_;
+ shared_mutex mtx_;
+ condition not_empty_cond_;
+
+ bool active_() const
+ { return 0 == state_; }
+
+ void deactivate_()
+ { detail::atomic_fetch_add( & state_, 1); }
+
+ bool empty_() const
+ { return queue_.empty(); }
+
+ void put_( value_type const& va)
+ {
+ if ( ! active_() )
+ throw task_rejected("queue is not active");
+ queue_.push( va);
+ not_empty_cond_.notify_one();
+ }
+
+ bool take_(
+ callable & ca,
+ unique_lock< shared_mutex > & lk)
+ {
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ not_empty_cond_.wait(
+ lk,
+ bind(
+ & unbounded_onelock_prio_queue::consumers_activate_,
+ this) );
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ callable tmp( queue_.top().ca);
+ queue_.pop();
+ ca.swap( tmp);
+ return ! ca.empty();
+ }
+
+ template< typename Duration >
+ bool take_(
+ callable & ca,
+ Duration const& rel_time,
+ unique_lock< shared_mutex > & lk)
+ {
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ if ( ! not_empty_cond_.timed_wait(
+ lk,
+ rel_time,
+ bind(
+ & unbounded_onelock_prio_queue::consumers_activate_,
+ this) ) )
+ return false;
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ callable tmp( queue_.top().ca);
+ queue_.pop();
+ ca.swap( tmp);
+ return ! ca.empty();
+ }
+
+ bool try_take_( callable & ca)
+ {
+ if ( empty_() )
+ return false;
+ callable tmp( queue_.top().ca);
+ queue_.pop();
+ ca.swap( tmp);
+ return ! ca.empty();
+ }
+
+ bool consumers_activate_() const
+ { return ! active_() || ! empty_(); }
+
+public:
+ unbounded_onelock_prio_queue()
+ :
+ state_( 0),
+ queue_(),
+ mtx_(),
+ not_empty_cond_()
+ {}
+
+ void deactivate()
+ { deactivate_(); }
+
+ bool empty()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return empty_();
+ }
+
+ void put( value_type const& va)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( va);
+ }
+
+ bool take( callable & ca)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, lk);
+ }
+
+ template< typename Duration >
+ bool take(
+ callable & ca,
+ Duration const& rel_time)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, rel_time, lk);
+ }
+
+ bool try_take( callable & ca)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return try_take_( ca);
+ }
+};
+} }
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_TASK_UNBOUNDED_ONELOCK_PRIO_QUEUE_H
Added: sandbox/task/boost/task/unbounded_onelock_smart_queue.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/unbounded_onelock_smart_queue.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,223 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_UNBOUNDED_ONELOCK_SMART_QUEUE_H
+#define BOOST_TASK_UNBOUNDED_ONELOCK_SMART_QUEUE_H
+
+#include <algorithm>
+#include <cstddef>
+
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+
+#include <boost/task/callable.hpp>
+#include <boost/task/detail/atomic.hpp>
+#include <boost/task/detail/meta.hpp>
+#include <boost/task/detail/smart.hpp>
+#include <boost/task/exceptions.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost { namespace task
+{
+template<
+ typename Attr,
+ typename Comp,
+ typename Enq = detail::replace_oldest,
+ typename Deq = detail::take_oldest
+>
+class unbounded_onelock_smart_queue
+{
+public:
+ typedef detail::has_attribute attribute_tag_type;
+ typedef Attr attribute_type;
+
+ struct value_type
+ {
+ callable ca;
+ attribute_type attr;
+
+ value_type(
+ callable const& ca_,
+ attribute_type const& attr_)
+ : ca( ca_), attr( attr_)
+ { BOOST_ASSERT( ! ca.empty() ); }
+
+ void swap( value_type & other)
+ {
+ ca.swap( other.ca);
+ std::swap( attr, other.attr);
+ }
+ };
+
+private:
+ typedef multi_index::multi_index_container<
+ value_type,
+ multi_index::indexed_by<
+ multi_index::ordered_non_unique<
+ multi_index::member<
+ value_type,
+ Attr,
+ & value_type::attr
+ >,
+ Comp
+ >
+ >
+ > queue_type;
+ typedef typename queue_type::template nth_index< 0 >::type queue_index;
+
+ volatile uint32_t state_;
+ queue_type queue_;
+ queue_index & idx_;
+ shared_mutex mtx_;
+ condition not_empty_cond_;
+ Enq enq_op_;
+ Deq deq_op_;
+
+ bool active_() const
+ { return 0 == state_; }
+
+ void deactivate_()
+ { detail::atomic_fetch_add( & state_, 1); }
+
+ bool empty_() const
+ { return queue_.empty(); }
+
+ void put_( value_type const& va)
+ {
+ if ( ! active_() )
+ throw task_rejected("queue is not active");
+ enq_op_( idx_, va);
+ not_empty_cond_.notify_one();
+ }
+
+ bool take_(
+ callable & ca,
+ unique_lock< shared_mutex > & lk)
+ {
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ not_empty_cond_.wait(
+ lk,
+ bind(
+ & unbounded_onelock_smart_queue::consumers_activate_,
+ this) );
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ deq_op_( idx_, ca);
+ return ! ca.empty();
+ }
+
+ template< typename Duration >
+ bool take_(
+ callable & ca,
+ Duration const& rel_time,
+ unique_lock< shared_mutex > & lk)
+ {
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ if ( ! not_empty_cond_.timed_wait(
+ lk,
+ rel_time,
+ bind(
+ & unbounded_onelock_smart_queue::consumers_activate_,
+ this) ) )
+ return false;
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ deq_op_( idx_, ca);
+ return ! ca.empty();
+ }
+
+ bool try_take_( callable & ca)
+ {
+ if ( empty_() )
+ return false;
+ deq_op_( idx_, ca);
+ return ! ca.empty();
+ }
+
+ bool consumers_activate_() const
+ { return ! active_() || ! empty_(); }
+
+public:
+ unbounded_onelock_smart_queue()
+ :
+ state_( 0),
+ queue_(),
+ idx_( queue_.get< 0 >() ),
+ mtx_(),
+ not_empty_cond_(),
+ enq_op_(),
+ deq_op_()
+ {}
+
+ void deactivate()
+ { detail::atomic_fetch_add( & state_, 1); }
+
+ bool empty()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return empty_();
+ }
+
+ void put( value_type const& va)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( va);
+ }
+
+ bool take( callable & ca)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, lk);
+ }
+
+ template< typename Duration >
+ bool take(
+ callable & ca,
+ Duration const& rel_time)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, rel_time, lk);
+ }
+
+ bool try_take( callable & ca)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return try_take_( ca);
+ }
+};
+} }
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_TASK_UNBOUNDED_ONELOCK_SMART_QUEUE_H
Added: sandbox/task/boost/task/unbounded_twolock_fifo.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/unbounded_twolock_fifo.hpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,169 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_UNBOUNDED_TWOLOCK_FIFO_H
+#define BOOST_TASK_UNBOUNDED_TWOLOCK_FIFO_H
+
+#include <cstddef>
+
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+
+#include <boost/task/callable.hpp>
+#include <boost/task/detail/atomic.hpp>
+#include <boost/task/detail/meta.hpp>
+#include <boost/task/exceptions.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost { namespace task
+{
+class unbounded_twolock_fifo
+{
+public:
+ typedef detail::has_no_attribute attribute_tag_type;
+ typedef callable value_type;
+
+private:
+ struct node
+ {
+ typedef shared_ptr< node > sptr_t;
+
+ value_type va;
+ sptr_t next;
+ };
+
+ volatile uint32_t state_;
+ node::sptr_t head_;
+ mutex head_mtx_;
+ node::sptr_t tail_;
+ mutex tail_mtx_;
+ condition not_empty_cond_;
+
+ bool active_() const
+ { return 0 == state_; }
+
+ void deactivate_()
+ { detail::atomic_fetch_add( & state_, 1); }
+
+ bool empty_()
+ { return head_ == get_tail_(); }
+
+ node::sptr_t get_tail_()
+ {
+ lock_guard< mutex > lk( tail_mtx_);
+ node::sptr_t tmp = tail_;
+ return tmp;
+ }
+
+ node::sptr_t pop_head_()
+ {
+ node::sptr_t old_head = head_;
+ head_ = old_head->next;
+ return old_head;
+ }
+
+public:
+ unbounded_twolock_fifo()
+ :
+ state_( 0),
+ head_( new node),
+ head_mtx_(),
+ tail_( head_),
+ tail_mtx_(),
+ not_empty_cond_()
+ {}
+
+ void deactivate()
+ { deactivate_(); }
+
+ bool empty()
+ {
+ unique_lock< mutex > lk( head_mtx_);
+ return empty_();
+ }
+
+ void put( value_type const& va)
+ {
+ node::sptr_t new_node( new node);
+ {
+ unique_lock< mutex > lk( tail_mtx_);
+ tail_->va = va;
+ tail_->next = new_node;
+ tail_ = new_node;
+ }
+ not_empty_cond_.notify_one();
+ }
+
+ bool take( value_type & va)
+ {
+ unique_lock< mutex > lk( head_mtx_);
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ while ( active_() && empty_() )
+ not_empty_cond_.wait( lk);
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ va.swap( head_->va);
+ pop_head_();
+ return ! va.empty();
+ }
+
+ template< typename Duration >
+ bool take(
+ value_type & va,
+ Duration const& rel_time)
+ {
+ unique_lock< mutex > lk( head_mtx_);
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ while ( active_() && empty_() )
+ if ( ! not_empty_cond_.timed_wait( lk, rel_time) )
+ return false;
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ va.swap( head_->va);
+ pop_head_();
+ return ! va.empty();
+ }
+
+ bool try_take( value_type & va)
+ {
+ unique_lock< mutex > lk( head_mtx_);
+ if ( empty_() )
+ return false;
+ va.swap( head_->va);
+ pop_head_();
+ return ! va.empty();
+ }
+};
+} }
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_TASK_UNBOUNDED_TWOLOCK_FIFO_H
Modified: sandbox/task/libs/task/build/Jamfile.v2
==============================================================================
--- sandbox/task/libs/task/build/Jamfile.v2 (original)
+++ sandbox/task/libs/task/build/Jamfile.v2 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -35,9 +35,9 @@
alias task_sources
: ## win32 sources ##
- guard.cpp
- interrupter.cpp
callable.cpp
+ context.cpp
+ guard.cpp
poolsize.cpp
scanns.cpp
semaphore_windows.cpp
@@ -52,9 +52,9 @@
alias task_sources
: ## posix sources ##
- guard.cpp
- interrupter.cpp
callable.cpp
+ context.cpp
+ guard.cpp
poolsize.cpp
scanns.cpp
semaphore_posix.cpp
Modified: sandbox/task/libs/task/doc/acknowledgements.qbk
==============================================================================
--- sandbox/task/libs/task/doc/acknowledgements.qbk (original)
+++ sandbox/task/libs/task/doc/acknowledgements.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -8,7 +8,7 @@
[section:acknowledgements Appendix B: Acknowledgments]
-I'd like to thank Vicente J. Botet Escriba for his comments and contributions (this_task::delay, this_task::yield) as well Anthony Williams and Braddock Gaskill for their future libraries.
+I'd like to thank Vicente J. Botet Escriba for his comments and contributions (this_task::reschedule_until, this_task::delay, this_task::yield) as well Anthony Williams and Braddock Gaskill for their future libraries.
[endsect]
Modified: sandbox/task/libs/task/doc/boost_task.qbk
==============================================================================
--- sandbox/task/libs/task/doc/boost_task.qbk (original)
+++ sandbox/task/libs/task/doc/boost_task.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -26,7 +26,7 @@
[def __boost_future__ [@http://www.justsoftwaresolutions.co.uk/threading/updated-implementation-of-c++-futures-3.html [*Boost.Future]]]
[template link_async[link_text] [link boost_task.async [link_text]]]
-[template link_channel[link_text] [link boost_task.execution_policy.pool.channel [link_text]]]
+[template link_queue[link_text] [link boost_task.execution_policy.pool.queue [link_text]]]
[template link_forkjoin[link_text] [link boost_task.execution_policy.pool.forkjoin [link_text]]]
[template link_handle[link_text] [link boost_task.async_completion_token.handle [link_text]]]
[template link_own_thread[link_text] [link boost_task.own_thread [link_text]]]
@@ -42,7 +42,7 @@
[def __as_sub_task__ `boost::task::as_sub_task`]
[def __attribute_type__ `boost::task::attribute_type`]
-[def __bounded_channel__ `boost::task::bounded_channel`]
+[def __bounded_queue__ `boost::task::bounded_queue`]
[def __dynamic_pool__ `boost::task::dynamic_pool`]
[def __handle__ `boost::task::handle`]
[def __has_attribute__ `boost::task::has_attribute`]
@@ -58,7 +58,7 @@
[def __take_oldest__ `boost::task::take_oldest`]
[def __task__ `boost::task::task`]
[def __task_interrupted__ `boost::task::task_interrupted`]
-[def __unbounded_channel__ `boost::task::unbounded_channel`]
+[def __unbounded_queue__ `boost::task::unbounded_queue`]
[def __make_task__ `boost::task::make_task()`]
[def __waitfor_all__ `boost::task::waitfor_all()`]
@@ -77,16 +77,12 @@
[def __fn_async__ `boost::task::async()`]
[def __fn_make_task__ `boost::task::make_task()`]
-[def __fn_active__ `active()`]
[def __fn_bind_to_processors__ `bind_to_processors()`]
[def __fn_closed__ `close()`]
-[def __fn_clear__ `clear()`]
-[def __fn_empty__ `empty()`]
[def __fn_get__ `get()`]
[def __fn_get_future__ `get_future()`]
[def __fn_has_value__ `has_value()`]
[def __fn_has_exception__ `has_exception()`]
-[def __fn_idle__ `idle()`]
[def __fn_interrupt__ `interrupt()`]
[def __fn_interrupt_and_wait__ `interrupt_and_wait()`]
[def __fn_interrupt_and_wait_for__ `interrupt_and_wait_for()`]
@@ -94,7 +90,6 @@
[def __fn_interruption_requested__ `interruption_requested()`]
[def __fn_is_ready__ `is_ready()`]
[def __fn_operator__ `operator()()`]
-[def __fn_pending__ `pending()`]
[def __fn_size__ `size()`]
[def __fn_shutdown__ `shutdown()`]
[def __fn_shutdown_now__ `shutdown_now()`]
@@ -108,12 +103,12 @@
[def __eps__ ['execution-policies]]
[def __blocked__ ['blocked]]
[def __callable__ ['callable]]
-[def __channel__ ['channel]]
[def __coop_task__ ['cooperative task]]
[def __duration__ ['Duration]]
[def __fork_join__ ['fork/join]]
[def __interruption_point__ ['interruption-point]]
[def __interruption_points__ ['interruption-points]]
+[def __queue__ ['queue]]
[def __task_id__ ['task-id]]
[def __thread_pool__ ['thread-pool]]
[def __thread_pools__ ['thread-pools]]
Deleted: sandbox/task/libs/task/doc/channel.qbk
==============================================================================
--- sandbox/task/libs/task/doc/channel.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
+++ (empty file)
@@ -1,31 +0,0 @@
-[/
- Copyright Oliver Kowalke 2009.
- Distributed under the Boost Software License, Version 1.0.
- (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt
-]
-
-
-[section:channel Channel]
-
-The channel synchronizes the access between non-pool threads (application threads) and __worker_threads__ and implements
-a queuing policy (limitation of queued tasks).
-
-
-[heading __bounded_channel__]
-
-__bounded_channel__ contains a single lock in order to synchronize access to the queue. The number of pending tasks is limited in order to prevent resource exhaustion.
-For this purpose a high- and low-watermark has to be passed at construction.
-__hwm__ sets the maximum of pending tasks. If this limited is reached all threads which submit a task will be set to sleep (blocked). If it 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.
-__lwm__ sets the threshold when blocked threads get woken up. If it is less than __hwm__ all sleeping producer threads will be woken up if
-the amount of pending tasks reaches __lwm__.
-
-
-[heading __unbounded_channel__]
-
-__unbounded_channel__ contains a single lock in order to synchronize access to the queue. An unlimited number of tasks can be queued into this channel.
-The insertion of an __task__ will never block. If the channel becomes empty __worker_threads__ will be set to sleep until new tasks are enqueued.
-
-
-[endsect]
Modified: sandbox/task/libs/task/doc/fork_join.qbk
==============================================================================
--- sandbox/task/libs/task/doc/fork_join.qbk (original)
+++ sandbox/task/libs/task/doc/fork_join.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -54,11 +54,7 @@
void main()
{
- boost::task::static_pool<
- boost::task::unbounded_channel<
- boost::task::fifo
- >
- > pool( boost::task::poolsize( 5) );
+ boost::task::static_pool< boost::task::unbounded_twolock_fifo > pool( boost::task::poolsize( 5) );
// compute fibonacci-number 10
// for numbers < 5 do inline calculation
Modified: sandbox/task/libs/task/doc/introduction.qbk
==============================================================================
--- sandbox/task/libs/task/doc/introduction.qbk (original)
+++ sandbox/task/libs/task/doc/introduction.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -129,11 +129,7 @@
void main()
{
// create a thread-pool with five worker-threads
- boost::task::static_pool<
- boost::task::unbounded_channel<
- boost::task::fifo
- >
- > pool( boost::task::poolsize( 5) );
+ boost::task::static_pool< boost::task::unbounded_onelock_fifo > pool( boost::task::poolsize( 5) );
// execute task in a thread-pool
// move task ownership to executor
Modified: sandbox/task/libs/task/doc/meta_functions.qbk
==============================================================================
--- sandbox/task/libs/task/doc/meta_functions.qbk (original)
+++ sandbox/task/libs/task/doc/meta_functions.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -15,11 +15,7 @@
``
// thread-pool with priority scheduling
// type of priority is int
- typdef boost::task::static_pool<
- boost::task::unbounded_channel<
- boost::task::priority< int >
- >
- > pool_type;
+ typdef boost::task::static_pool< boost::task::unbounded_onelock_priority< int > > pool_type;
// test if thread-pool supports priorities at compile time
std::cout << std::boolalpha << boost::task::has_attribute< pool_type >::value << "\n";
Modified: sandbox/task/libs/task/doc/overview.qbk
==============================================================================
--- sandbox/task/libs/task/doc/overview.qbk (original)
+++ sandbox/task/libs/task/doc/overview.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -76,11 +76,7 @@
void main()
{
// create a thread-pool
- boost::task::static_pool<
- boost::task::unbounded_channel<
- boost::task::fifo
- >
- > pool( boost::task::poolsize( 5) );
+ boost::task::static_pool< boost::task::unbounded_twolock_fifo > > pool( boost::task::poolsize( 5) );
// execute tasks in thread-pool
// move tasks ownership to executor
Modified: sandbox/task/libs/task/doc/pool.qbk
==============================================================================
--- sandbox/task/libs/task/doc/pool.qbk (original)
+++ sandbox/task/libs/task/doc/pool.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -12,7 +12,7 @@
creation and destruction can be avoided by running the __work_items__ on a __thread_pool__ (reusing an existing
__worker_thread__ instead).
-A __thread_pool__ maintains a queue (or queues) of __work_items__ to be done, and a pool of __worker_threads__ which execute __work_items__ from the queue(s).
+A __thread_pool__ maintains a global queue of __work_items__ to be processed, and a pool of __worker_threads__ which execute __work_items__ from the global queue.
__boost_task__ provides __fn_async__ with support of executing an __task__ in __thread_pool__:
@@ -27,11 +27,7 @@
// five worker-threads
// FIFO schduling of queued tasks
// and unlimited size of internal queue
- boost::task::static_pool<
- boost::task::unbounded_channel<
- boost::task::fifo
- >
- > pool( boost::task::poolsize( 5) );
+ boost::task::static_pool< boost::task::unbounded_twolock_fifo > pool( boost::task::poolsize( 5) );
// create task
boost::task::task< std::string > t( echo, "Hello World!");
@@ -55,8 +51,7 @@
[include static_pool.qbk]
-[include channel.qbk]
-[include scheduler.qbk]
+[include queue.qbk]
[include shutdown.qbk]
[include processor_binding.qbk]
[include work_stealing.qbk]
Modified: sandbox/task/libs/task/doc/processor_binding.qbk
==============================================================================
--- sandbox/task/libs/task/doc/processor_binding.qbk (original)
+++ sandbox/task/libs/task/doc/processor_binding.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -13,7 +13,7 @@
``
typedef boost::task::static_pool<
- boost::task::unbounded_channel< boost::tp::fifo >
+ boost::task::unbounded_queue< boost::tp::fifo >
> pool_type;
// constructs thread-pool with worker-threads as
@@ -21,7 +21,7 @@
pool_type pool( pool_type::bind_to_processors() );
``
-The constructor takes additional arguments for the [link_work_stealing work-stealing algorithm] and [link_channel high-] and [link_channel low-watermark] too.
+The constructor takes additional arguments for the [link_work_stealing work-stealing algorithm] and [link_queue high-] and [link_queue low-watermark] too.
[note __boost_task__ does provide this feature only for Windows, Linux, AIX, HP-UX, Solaris and FreeBSD.]
Added: sandbox/task/libs/task/doc/queue.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/queue.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,136 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:queue Queues]
+
+A __queue__ synchronizes the access between application threads and __worker_threads__ and implements policies for limitating the amount of queued tasks and how those tasks are scheduled ( first-in-first-out, priority ordering etc.
+
+
+[heading Bounded queues]
+
+__bounded_queue__ limits the number of queued (pending) tasks in order to prevent resource exhaustion.
+For this purpose a high- and low-watermark has to be passed at construction.
+__hwm__ sets the maximum of pending tasks. If this limited is reached all threads which submit a task will be set to sleep (blocked). If it 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 queue.
+__lwm__ sets the threshold when blocked threads get woken up. If it is less than __hwm__ all sleeping producer threads will be woken up if
+the amount of pending tasks reaches __lwm__.
+
+
+[heading Unbounded queues]
+
+__unbounded_queue__ allows ann unlimited number of tasks to be queued.
+The insertion of an __task__ will never block. If the queue becomes empty __worker_threads__ will be set to sleep until new tasks are enqueued.
+
+
+[heading Onelock queues]
+
+All operation on this queue are protected by one lock (one mutex).
+
+
+[heading Twolock queues]
+
+This kind of queue uses two different locks (mutexes) for put- and take-operations gaining a better performance._
+
+
+[heading Scheduling]
+
+For scheduling of tasks inside the queue following strategies are available:
+
+* fifo: first enqueued task is dequeued first
+
+* priority: the next item dequeued from the queue depends on its associated priority attribute and sorting criterion applied to the queue (template arguments)
+
+``
+ // thread-pool with priority scheduling
+ // tasks with higher priority are
+ // scheduled first
+ boost::task::static_pool< boost::task::unbounded_onelock_priority_queue< int > > pool( boost::task::poolsize( 5) );
+
+ boost::task::task< void > t1( some_fn);
+ boost::task::task< void > t2( another_fn);
+
+ // move task t1 with priority 5 to thread-pool
+ boost::task::async(
+ boost::move( t1),
+ 5,
+ pool);
+
+ // move task t2 with priority 3 to thread-pool
+ boost::task::async(
+ boost::move( t2),
+ 3,
+ pool);
+``
+
+* smart: enqueue- and dequeue-operations are determined by the template arguments und the task-attribute. The library provides an default let only one kind of task stored inside the queue (gets replaced by new one)
+
+``
+ long fibonacci_fn( long n)
+ {
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ long k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ long tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ return k1;
+ }
+
+ typedef boost::task::static_pool< boost::task::unbounded_onelock_smart_queue< int > > pool_type;
+
+ void main()
+ {
+ pool_type pool( boost::task::poolsize( 1) );
+
+ ...
+
+ boost::task::task< long > t1(
+ boost::bind( fibonacci_fn, 10) );
+ boost::task::task< long > t2(
+ boost::bind( fibonacci_fn, 5) );
+
+ // replaced by later task with same attribute == 2
+ // if still pending in pool
+ boost::task::async(
+ boost::move( t1),
+ 2,
+ pool);
+
+ // will replace previous pending task with attribute == 2
+ boost::task::async(
+ boost::move( t2),
+ 2,
+ pool);
+ }
+``
+
+
+__boost_task__ provides following queues:
+
+* bounded_onelock_fifo
+
+* bounded_onelock_priority_queue< Attr, Comp = std::less< Attr > >
+
+* bounded_onelock_smart_queue< Attr, Comp, Enq = detail::replace_oldest, Deq = detail::take_oldest >
+
+* bounded_twolock_fifo
+
+
+* unbounded_onelock_fifo
+
+* unbounded_onelock_priority_queue< Attr, Comp = std::less< Attr > >
+
+* unbounded_onelock_smart_queue< Attr, Comp, Enq = detail::replace_oldest, Deq = detail::take_oldest >
+
+* unbounded_twolock_fifo
+
+
+[endsect]
Modified: sandbox/task/libs/task/doc/ref_callable.qbk
==============================================================================
--- sandbox/task/libs/task/doc/ref_callable.qbk (original)
+++ sandbox/task/libs/task/doc/ref_callable.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -16,15 +16,18 @@
public:
callable();
+ template< typename R >
+ callable( task< R > t, context const& ctx);
+
void operator()();
bool empty() const;
void clear();
- void reset();
-
void reset( shared_ptr< thread > const& thrd);
+
+ void swap( callable &);
};
``
@@ -39,6 +42,17 @@
]
+[heading Constructor `callable( task< R >, context const&)`]
+
+ template< typename R >
+ callable( task< R > t, context const& ctx)
+
+[variablelist
+[[Effects:] [constructs an callable associated with an task and a specific context]]
+[[Throws:] [Nothing]]
+]
+
+
[heading Member function `operator()()`]
void operator()()
@@ -69,22 +83,22 @@
]
-[heading Member function `reset()`]
+[heading Member function `reset( shared_ptr< thread> const&)`]
- void reset()
+ void reset( shared_ptr< thread > const& thrd)
[variablelist
-[[Effects:] [clears internal thrread-context]]
+[[Effects:] [sets internal thread-context]]
[[Throws:] [Nothing]]
]
-[heading Member function `reset( shared_ptr< thread> const& thrd)`]
+[heading Member function `swap( callable &)`]
- void reset( shared_ptr< thread > const& thrd)
+ void swap( callable & ca)
[variablelist
-[[Effects:] [sets internal thread-context]]
+[[Effects:] [swaps content of both callable instances]]
[[Throws:] [Nothing]]
]
Modified: sandbox/task/libs/task/doc/ref_context.qbk
==============================================================================
--- sandbox/task/libs/task/doc/ref_context.qbk (original)
+++ sandbox/task/libs/task/doc/ref_context.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -14,33 +14,65 @@
class context
{
public:
- template< typename R >
- callable get_callable( task< R > t);
+ context();
- template< typename R >
- handle< R > get_handle( shared_future< R > f);
+ void reset( shared_ptr< thread > const& thrd);
+
+ void interrupt();
+
+ bool interruption_requested();
+
+ void swap( context & other);
};
``
-[heading Templated member function `get_callable( task< R > t)`]
+[heading Constructor `callable()`]
+
+ callable()
+
+[variablelist
+[[Effects:] [creates an context object]
+[[Throws:] [Nothing]]
+]
+
+
+[heading Member function `reset( shared_ptr< thread> const&)`]
+
+ void reset( shared_ptr< thread > const& thrd)
+
+[variablelist
+[[Effects:] [sets internal thread-context]]
+[[Throws:] [Nothing]]
+]
+
+
+[heading Member function `interrupt()`]
+
+ void interrupt()
+
+[variablelist
+[[Effects:] [request interruption of associated task]]
+[[Throws:] [Nothing]]
+]
+
+
+[heading Member function `interruption_requested()`]
- template< typename R >
- callable get_callable( task< R > t);
+ bool interruption_requested()
[variablelist
-[[Effects:] [returns a callable containing the moved task< R >]]
+[[Effects:] [retuns true if interruption of associated task is requested]]
[[Throws:] [Nothing]]
]
-[heading Templated member function `get_handle( shared_future< R > f)`]
+[heading Member function `swap( context &)`]
- template< typename R >
- handle< R > get_handle( shared_future< R > f);
+ void swap( context & ctx)
[variablelist
-[[Effects:] [returns a handle associated to the moved task< R >]]
+[[Effects:] [swaps content of both context instances]]
[[Throws:] [Nothing]]
]
Modified: sandbox/task/libs/task/doc/ref_handle.qbk
==============================================================================
--- sandbox/task/libs/task/doc/ref_handle.qbk (original)
+++ sandbox/task/libs/task/doc/ref_handle.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -14,6 +14,7 @@
class handle
{
handle();
+ handle( shared_future< R >, context const&);
void interrupt();
void interrupt_and_wait();
@@ -52,7 +53,7 @@
friend unsigned int waitfor_any( handle< T1 > & t1, handle< T2 > & t2, handle< T3 > & t3, handle< T4 > & t4, handle< T5 > & t5);
``
-[heading Constructor]
+[heading Constructor `handle()`]
handle()
@@ -62,6 +63,16 @@
]
+[heading Constructor `handle( shared_future< R >, context const&)`]
+
+ handle( shared_future< R >, context const&);
+
+[variablelist
+[[Effects:] [constructs an handle associated with anfuture and an context]]
+[[Throws:] [Nothing]]
+]
+
+
[heading Member function `interruption_requested()`]
bool interruption_requested()
Modified: sandbox/task/libs/task/doc/ref_static_pool.qbk
==============================================================================
--- sandbox/task/libs/task/doc/ref_static_pool.qbk (original)
+++ sandbox/task/libs/task/doc/ref_static_pool.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -52,18 +52,13 @@
~static_pool();
std::size_t size();
- std::size_t active();
- std::size_t idle();
void shutdown();
void shutdown_now();
- void interrupt_all_worker();
-
bool closed();
- void clear();
- bool empty();
- std::size_t pending();
+
+ void interrupt_all_worker();
const std::size_t upper_bound();
void upper_bound( high_watermark const& hwm);
@@ -93,7 +88,7 @@
]
-[heading Constructor (unbounded channel)]
+[heading Constructor (unbounded queue)]
explicit static_pool(
<<unspec-type>>,
@@ -104,11 +99,11 @@
[[Preconditions:] [operating system provides functionality for processor binding]]
[[Effects:] [constructs a pool - for each processor a worker-thread is created and bound to one processor - global-queue can queue an unlimited number of tasks]]
[[Throws:] [`boost::thread_resource_error`, `boost::task::invalid_scanns`, `boost::task::invalid_timeduration`]]
-[[Notes:] [constructor has to be called if a unbounded-channel is used and `bind_to_processors()` must be set as first argument]]
+[[Notes:] [constructor has to be called if a unbounded-queue is used and `bind_to_processors()` must be set as first argument]]
]
-[heading Constructor (unbounded channel/poolsize)]
+[heading Constructor (unbounded queue/poolsize)]
explicit static_pool(
poolsize const& psize,
@@ -118,11 +113,11 @@
[variablelist
[[Effects:] [constructs a pool containing psize worker-threads - global-queue can queue an unlimited number of tasks]]
[[Throws:] [`boost::thread_resource_error`, `boost::task::invalid_scanns`, `boost::task::invalid_timeduration`]]
-[[Notes:] [constructor has to be called if a unbounded-channel is used]]
+[[Notes:] [constructor has to be called if a unbounded-queue is used]]
]
-[heading Constructor (bounded channel)]
+[heading Constructor (bounded queue)]
explicit static_pool(
<<unspec-type>>,
@@ -135,11 +130,11 @@
[[Preconditions:] [operating system provides functionality for processor binding]]
[[Effects:] [constructs a pool - for each processor a worker-thread is created and bound to one processor - global-queue can only queue a limited number of tasks]]
[[Throws:] [`boost::thread_resource_error`, `boost::task::invalid_scanns`, `boost::task::invalid_timeduration`, `boost::task::invalid_watermark`]]
-[[Notes:] [constructor has to be called if a bounded-channel is used and `bind_to_processors()` must be set as first argument]]
+[[Notes:] [constructor has to be called if a bounded-queue is used and `bind_to_processors()` must be set as first argument]]
]
-[heading Constructor (bounded channel/poolsize)]
+[heading Constructor (bounded queue/poolsize)]
explicit static_pool(
poolsize const& psize,
@@ -151,7 +146,7 @@
[variablelist
[[Effects:] [constructs a pool containing psize worker-threads - global-queue can only queue a limited number of tasks]]
[[Throws:] [`boost::thread_resource_error`, `boost::task::invalid_scanns`, `boost::task::invalid_timeduration`, `boost::task::invalid_watermark`]]
-[[Notes:] [constructor has to be called if a bounded-channel is used]]
+[[Notes:] [constructor has to be called if a bounded-queue is used]]
]
@@ -205,33 +200,12 @@
]
-[heading Member function `active()`]
-
- std::size_t active()
-
-[variablelist
-[[Effects:] [returns how many worker-threads are active (executing an task)]]
-[[Throws:] [`boost::task::pool_moved`]]
-]
-
-
-[heading Member function `idle()`]
-
- std::size_t idle()
-
-[variablelist
-[[Effects:] [returns how many worker-threads are idle (not executing an task).]]
-[[Throws:] [`boost::task::pool_moved`]]
-[[Notes:] [the value is the difference of `size()` and `active()`]]
-]
-
-
[heading Member function `shutdown()`]
void shutdown()
[variablelist
-[[Effects:] [deactivates the channel and joins all worker-threads - the pool is closed]]
+[[Effects:] [deactivates the queue and joins all worker-threads - the pool is closed]]
[[Throws:] [`boost::thread_interrupted`, `boost::system::system_error`, `boost::task::pool_moved`]]
[[Notes:] [all pending tasks are processed]]
]
@@ -242,7 +216,7 @@
void shutdown_now()
[variablelist
-[[Effects:] [deactivates the channel, send interruption request to all worker-threads and joins them - the pool is closed]]
+[[Effects:] [deactivates the queue, send interruption request to all worker-threads and joins them - the pool is closed]]
[[Throws:] [`boost::thread_interrupted`, `boost::system::system_error`, `boost::task::pool_moved`]]
[[Notes:] [pending tasks are not processed but returned]]
]
@@ -268,45 +242,15 @@
]
-[heading Member function `clear()`]
-
- void clear()
-
-[variablelist
-[[Effects:] [removes all pending tasks from the channel]]
-[[Throws:] [`boost::task::pool_moved`]]
-]
-
-
-[heading Member function `empty()`]
-
- bool empty()
-
-[variablelist
-[[Effects:] [queries if the channel is empty]]
-[[Throws:] [`boost::task::pool_moved`]]
-]
-
-
-[heading Member function `pending()`]
-
- std::size_t pending()
-
-[variablelist
-[[Effects:] [queries how many tasks are pending (still unprocessed) in the global-queue (channel)]]
-[[Throws:] [`boost::task::pool_moved`]]
-]
-
-
[heading 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]]
+[[Preconditions:] [queue is of type bounded-queue]]
+[[Effects:] [returns the upper bound of the bounded-queue]]
[[Throws:] [`boost::task::pool_moved`]]
-[[Notes:] [can only be used if a bounded-channel is used]]
+[[Notes:] [can only be used if a bounded-queue is used]]
]
@@ -315,11 +259,11 @@
void upper_bound( high_watermark const& hwm)
[variablelist
-[[Preconditions:] [channel is of type bounded-channel]]
-[[Effects:] [sets the upper bound of the bounded-channel]]
+[[Preconditions:] [queue is of type bounded-queue]]
+[[Effects:] [sets the upper bound of the bounded-queue]]
[[Postconditions:] [`this->upper_bound() == hwm`]]
[[Throws:] [`boost::task::invalid_watermark`, `boost::task::pool_moved`]]
-[[Notes:] [can only be used if a bounded-channel is used]]
+[[Notes:] [can only be used if a bounded-queue is used]]
]
@@ -328,10 +272,10 @@
std::size_t lower_bound();
[variablelist
-[[Preconditions:] [channel is of type bounded-channel]]
-[[Effects:] [returns the lower bound of the bounded-channel]]
+[[Preconditions:] [queue is of type bounded-queue]]
+[[Effects:] [returns the lower bound of the bounded-queue]]
[[Throws:] [`boost::task::pool_moved`]]
-[[Notes:] [can only be used if a bounded-channel is used]]
+[[Notes:] [can only be used if a bounded-queue is used]]
]
@@ -340,11 +284,11 @@
void lower_bound( low_watermark const& lwm)
[variablelist
-[[Preconditions:] [channel is of type bounded-channel]]
-[[Effects:] [sets the lower bound of the bounded-channel]]
+[[Preconditions:] [queue is of type bounded-queue]]
+[[Effects:] [sets the lower bound of the bounded-queue]]
[[Postconditions:] [`this->lower_bound() == lwm`]]
[[Throws:] [`boost::task::invalid_watermark`, `boost::task::pool_moved`]]
-[[Notes:] [can only be used if a bounded-channel is used]]
+[[Notes:] [can only be used if a bounded-queue is used]]
]
Modified: sandbox/task/libs/task/doc/ref_utility.qbk
==============================================================================
--- sandbox/task/libs/task/doc/ref_utility.qbk (original)
+++ sandbox/task/libs/task/doc/ref_utility.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -6,6 +6,24 @@
]
+[section:reschedule_until Non-member function `reschedule_until()`]
+
+``
+ #include <boost/task/utility.hpp>
+
+ template< typename Pred >
+ void reschedule_until( Pred const&)
+``
+
+[variablelist
+[[Effects:] [reschedules current task until passed callable predicate becomes ready]]
+[[Throws:] [`boost::thread_interrupted`,`boost::system::system_error`]]
+[[Note:] [this function resides in namespace `boost::this_task`]]
+]
+
+[endsect]
+
+
[section:get_pool Non-member function `get_pool()`]
``
@@ -50,22 +68,61 @@
``
[variablelist
-[[Effects:] [returns the thread-id of the worker-thread]]
+[[Effects:] [returns returns the thread-id of the worker-thread]]
+[[Throws:] [nothing]]
+[[Note:] [this function resides in namespace `boost::this_task`]]
+]
+
+[endsect]
+
+
+[section:delay Non-member function `delay()`]
+
+``
+ #include <boost/task/utility.hpp>
+
+ void delay( system_time abs_time)
+
+ template< typename Duration >
+ void delay( Duration const& rel_time)
+``
+
+[variablelist
+[[Effects:] [delays the execution of the current task so that the worker-thread can process another task in the meantime]]
+[[Throws:] [nothing]]
+[[Note:] [this function resides in namespace `boost::this_task`]]
+]
+
+[endsect]
+
+
+[section:yield Non-member function `yield()`]
+
+``
+ #include <boost/task/utility.hpp>
+
+ void yield()
+``
+
+[variablelist
+[[Effects:] [yields the current task so that the worker-threadcan process another task in the meantime]]
[[Throws:] [nothing]]
[[Note:] [this function resides in namespace `boost::this_task`]]
]
+[endsect]
+
-[section:worker_id Non-member function `block()`]
+[section:interrupt Non-member function `interrupt()`]
``
#include <boost/task/utility.hpp>
- bool block()
+ void interrupt()
``
[variablelist
-[[Effects:] [blocks current context of execution and returns true if threadpool was shutdown]]
+[[Effects:] [task can request interruption for itself]]
[[Throws:] [nothing]]
[[Note:] [this function resides in namespace `boost::this_task`]]
]
Modified: sandbox/task/libs/task/doc/scheduler.qbk
==============================================================================
--- sandbox/task/libs/task/doc/scheduler.qbk (original)
+++ sandbox/task/libs/task/doc/scheduler.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -8,7 +8,7 @@
[section:scheduling Scheduling]
-The scheduling policy determines how tasks are scheduled inside the __channel__.
+The scheduling policy determines how tasks are scheduled inside the __queue__.
[heading fifo]
@@ -25,7 +25,7 @@
// tasks with higher priority are
// scheduled first
boost::task::static_pool<
- boost::task::unbounded_channel<
+ boost::task::unbounded_queue<
boost::task::priority< int > >
> pool( boost::task::poolsize( 5) );
@@ -54,7 +54,7 @@
// tasks with lower priority are
// scheduled first
boost::task::static_pool<
- boost::task::unbounded_channel<
+ boost::task::unbounded_queue<
boost::task::priority< int, std::less< int > >
>
> pool( boost::task::poolsize( 5) );
@@ -85,7 +85,7 @@
}
typedef boost::task::static_pool<
- boost::task::unbounded_channel<
+ boost::task::unbounded_queue<
boost::task::smart<
int,
std::less< int >,
Modified: sandbox/task/libs/task/doc/shutdown.qbk
==============================================================================
--- sandbox/task/libs/task/doc/shutdown.qbk (original)
+++ sandbox/task/libs/task/doc/shutdown.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -33,11 +33,7 @@
return k1;
}
- typedef boost::task::static_pool<
- boost::task::unbounded_channel<
- boost::task::fifo
- >
- > pool_type;
+ typedef boost::task::static_pool< boost::task::unbounded_onelock_fifo > pool_type;
void main()
{
@@ -88,11 +84,7 @@
return k1;
}
- typedef boost::task::static_pool<
- boost::task::unbounded_channel<
- boost::task::fifo
- >
- > pool_type;
+ typedef boost::task::static_pool< boost::task::unbounded_twolock_fifo > pool_type;
void main()
{
Modified: sandbox/task/libs/task/doc/static_pool.qbk
==============================================================================
--- sandbox/task/libs/task/doc/static_pool.qbk (original)
+++ sandbox/task/libs/task/doc/static_pool.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -13,10 +13,8 @@
``
- boost::task::_static_pool< // pool type
- boost::task::unbounded_channel< // queuing policy (unbounded_channel, bounded_channel)
- boost::task::fifo // scheduling policy (fifo, priority, smart)
- >
+ boost::task::_static_pool< // pool type
+ boost::task::unbounded_twolock_fifo // queue where application threads enqueue tasks
> pool(
boost::task::poolsize( 6), // pool with 6 pre-forked worker-threads
boost::posix_time::posix_time::milliseconds( 50), // time to sleep if no work-item available
@@ -27,17 +25,10 @@
The first argument of the constructor specifies how many __worker_threads__ the pool will contain. The second
and third argument are used by the [link_work_stealing __work_stealing__] algorithm.
-[note If __bounded_channel__ is used as queuing policy the constructor has two additional arguments . ]
+[note If __bounded_queue__ is used as queuing policy the constructor has two additional arguments . ]
__static_pool__ provides functionality to check the status of the pool - __fn_closed__ returns true when the pool was
-shutdown and __fn_active__ as well as __fn_idle__ returning how many __worker_threads__ are active (executing a task) or idle.
-The size of the pool can be accessed over __fn_size__.
-
-For informational pruposes __fn_empty__ and __fn_pending__ can be used in order to know if the global task-queue is empty or
-how many tasks are waiting for execution. With __fn_clear__ all tasks are removed from the global-queue.
-
-[note __fn_pending__ does not count tasks in the local-queues of the __worker_threads__.]
-
+shutdown and __fn_size__returns the number of __worker_threads__.
[endsect]
Modified: sandbox/task/libs/task/doc/task.qbk
==============================================================================
--- sandbox/task/libs/task/doc/task.qbk (original)
+++ sandbox/task/libs/task/doc/task.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -251,11 +251,7 @@
void main()
{
// create thread-pool with five worker-threads
- boost::task::static_pool<
- boost::task::unbounded_channel<
- boost::task::fifo
- >
- > pool( boost::task::poolsize( 5) );
+ boost::task::static_pool< boost::task::unbounded_twolock_fifo > pool( boost::task::poolsize( 5) );
// create task computing fibonacci-number for 10
boost::task::task< long > t(
Modified: sandbox/task/libs/task/doc/todo.qbk
==============================================================================
--- sandbox/task/libs/task/doc/todo.qbk (original)
+++ sandbox/task/libs/task/doc/todo.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -10,9 +10,7 @@
[heading Optimizations]
-* finer-grained locking for bounded_channel and unbounded_channel using two-lock-queue
-
-* lock-free-queue with fifo ordering as channel
+* lock-free-queue with fifo ordering as queue
[heading Dynamic thread-pool]
Modified: sandbox/task/libs/task/doc/user_defined_executor.qbk
==============================================================================
--- sandbox/task/libs/task/doc/user_defined_executor.qbk (original)
+++ sandbox/task/libs/task/doc/user_defined_executor.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -15,64 +15,14 @@
* create an context (link between handle and task)
-* create an handle< R > via context and shared_future< R >
+* create an handle< R > passing shared_future< R > and context
-* create a callable via context an the moved task< R >
+* create a callable apply task< R > (move) and context to the ctor
* pass the callable to the executor
* return the handle
-In the sample code below the task is executed in a fiber (__boost_fiber__).
-
-
-``
- class new_fiber
- {
- private:
- fiber::scheduler & sched_;
-
- public:
- new_fiber( fiber::scheduler & sched)
- : sched_( sched)
- {}
-
- template< typename R >
- handle< R > operator()( task< R > t)
- {
- // get shared_future< R > from task< R >
- shared_future< R > f( t.get_future() );
-
- // create an context
- context ctx;
-
- // create an handle< R > out of the context and the future
- handle< R > h( ctx.get_handle( f) );
-
- // create an callable containing the moved task< R >
- callable ca( ctx.get_callable( boost::move( t) ) );
-
- // apply the callable to the executor == fiber-scheduler
- sched_.submit( ca);
-
- // return the handle
- return h;
- }
- };
-
-
- void main()
- {
- boost::fiber::scheduler sched;
-
- boost::task::handle< long > h1(
- boost::task::async(
- boost::make_task( ... ),
- sched);
-
- sched.run();
- }
-``
[endsect]
Modified: sandbox/task/libs/task/doc/utilities.qbk
==============================================================================
--- sandbox/task/libs/task/doc/utilities.qbk (original)
+++ sandbox/task/libs/task/doc/utilities.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -12,6 +12,13 @@
runs in a __thread_pool__).
+[heading reschedule_until]
+
+In the function `boost::this_task::reschedule_until( Pred const&)` allows to synchronize the task with other asynchronous events
+without blocking the __worker_threads__ (bool Pred::operator()() must not block). The current task will be rescheduled until the
+passed predicate becomes true.
+
+
[heading get_pool]
The pool in which the current code (__task__) is executed can be accessed via __fn_get_pool__. If hte code is not executed by a
@@ -28,4 +35,20 @@
__fn_worker_id__ returns the __thread_id__ of the __worker_thread__ executing the current __task__.
+[heading delay]
+
+The execution of a __task__ can be delayed for a time-duration or until a specific time-point with __fn_delay__.
+
+
+[heading yield]
+
+If a __task__ detects that it would bould block it can yield itself with __fn_yield__ so that the __worker_thread__ can execute
+another __task__ in the meantime.
+
+
+[heading interrupt]
+
+A __task__ can interrupt itself via __fn_tt_interrupt__.
+
+
[endsect]
Modified: sandbox/task/libs/task/doc/work_stealing.qbk
==============================================================================
--- sandbox/task/libs/task/doc/work_stealing.qbk (original)
+++ sandbox/task/libs/task/doc/work_stealing.qbk 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -21,7 +21,7 @@
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__
+The pool contains one global-queue (__bounded_queue__ or __unbounded_queue__) protected by a global-lock and each __worker_thread__
has its own private local worker-queue. If work is enqueued by a __worker_thread__ the __task__ 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:
Modified: sandbox/task/libs/task/examples/Jamfile.v2
==============================================================================
--- sandbox/task/libs/task/examples/Jamfile.v2 (original)
+++ sandbox/task/libs/task/examples/Jamfile.v2 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -35,7 +35,6 @@
exe no_deadlock_pool : no_deadlock_pool.cpp ;
exe no_deadlock_pool2 : no_deadlock_pool2.cpp ;
exe no_deadlock_pool3 : no_deadlock_pool3.cpp ;
-exe pending : pending.cpp ;
exe priority : priority.cpp ;
exe semaphore_thread : semaphore_thread.cpp ;
exe semaphore_pool : semaphore_pool.cpp ;
Modified: sandbox/task/libs/task/examples/bind_to_processors.cpp
==============================================================================
--- sandbox/task/libs/task/examples/bind_to_processors.cpp (original)
+++ sandbox/task/libs/task/examples/bind_to_processors.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -18,7 +18,7 @@
namespace pt = boost::posix_time;
namespace tsk = boost::task;
-typedef tsk::static_pool< tsk::unbounded_channel< tsk::fifo > > pool_type;
+typedef tsk::static_pool< tsk::unbounded_onelock_fifo > pool_type;
int serial_fib( int n)
{
Modified: sandbox/task/libs/task/examples/buffer_multi.cpp
==============================================================================
--- sandbox/task/libs/task/examples/buffer_multi.cpp (original)
+++ sandbox/task/libs/task/examples/buffer_multi.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -18,7 +18,7 @@
namespace tsk = boost::task;
-typedef tsk::static_pool< tsk::unbounded_channel< tsk::fifo > > pool_type;
+typedef tsk::static_pool< tsk::unbounded_twolock_fifo > pool_type;
int serial_fib( int n)
{
Modified: sandbox/task/libs/task/examples/buffer_multi2.cpp
==============================================================================
--- sandbox/task/libs/task/examples/buffer_multi2.cpp (original)
+++ sandbox/task/libs/task/examples/buffer_multi2.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -18,7 +18,7 @@
namespace tsk = boost::task;
-typedef tsk::static_pool< tsk::unbounded_channel< tsk::fifo > > pool_type;
+typedef tsk::static_pool< tsk::unbounded_twolock_fifo > pool_type;
int serial_fib( int n)
{
Modified: sandbox/task/libs/task/examples/buffer_pool.cpp
==============================================================================
--- sandbox/task/libs/task/examples/buffer_pool.cpp (original)
+++ sandbox/task/libs/task/examples/buffer_pool.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -18,9 +18,7 @@
{
try
{
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 1) );
+ tsk::static_pool< tsk::unbounded_twolock_fifo > pool( tsk::poolsize( 1) );
int n = 5;
tsk::unbounded_buffer< std::string > buf_ping, buf_pong;
Modified: sandbox/task/libs/task/examples/buffer_pool_thread.cpp
==============================================================================
--- sandbox/task/libs/task/examples/buffer_pool_thread.cpp (original)
+++ sandbox/task/libs/task/examples/buffer_pool_thread.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -18,9 +18,7 @@
{
try
{
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 1) );
+ tsk::static_pool< tsk::unbounded_twolock_fifo > pool( tsk::poolsize( 1) );
int n = 10;
tsk::unbounded_buffer< std::string > buf_ping, buf_pong;
Modified: sandbox/task/libs/task/examples/fork_join.cpp
==============================================================================
--- sandbox/task/libs/task/examples/fork_join.cpp (original)
+++ sandbox/task/libs/task/examples/fork_join.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -17,7 +17,7 @@
namespace pt = boost::posix_time;
namespace tsk = boost::task;
-typedef tsk::static_pool< tsk::unbounded_channel< tsk::fifo > > pool_type;
+typedef tsk::static_pool< tsk::unbounded_twolock_fifo > pool_type;
int serial_fib( int n)
{
Modified: sandbox/task/libs/task/examples/interrupt.cpp
==============================================================================
--- sandbox/task/libs/task/examples/interrupt.cpp (original)
+++ sandbox/task/libs/task/examples/interrupt.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -17,7 +17,7 @@
namespace pt = boost::posix_time;
namespace tsk = boost::task;
-typedef tsk::static_pool< tsk::unbounded_channel< tsk::fifo > > pool_type;
+typedef tsk::static_pool< tsk::unbounded_twolock_fifo > pool_type;
inline
int fibonacci_fn( int n)
@@ -50,8 +50,6 @@
tsk::make_task( long_running_fn),
pool);
std::cout << "poolsize == " << pool.size() << std::endl;
- std::cout << "idle threads == " << pool.idle() << std::endl;
- std::cout << "active threads == " << pool.active() << std::endl;
tsk::handle< int > h(
tsk::async(
tsk::make_task( fibonacci_fn, 10),
Modified: sandbox/task/libs/task/examples/no_deadlock_pool.cpp
==============================================================================
--- sandbox/task/libs/task/examples/no_deadlock_pool.cpp (original)
+++ sandbox/task/libs/task/examples/no_deadlock_pool.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -18,9 +18,7 @@
namespace tsk = boost::task;
-typedef tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
-> pool_type;
+typedef tsk::static_pool< tsk::unbounded_twolock_fifo > pool_type;
class event
{
Modified: sandbox/task/libs/task/examples/no_deadlock_pool3.cpp
==============================================================================
--- sandbox/task/libs/task/examples/no_deadlock_pool3.cpp (original)
+++ sandbox/task/libs/task/examples/no_deadlock_pool3.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -18,9 +18,7 @@
namespace tsk = boost::task;
-typedef tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
-> pool_type;
+typedef tsk::static_pool< tsk::unbounded_twolock_fifo > pool_type;
class event
{
Deleted: sandbox/task/libs/task/examples/pending.cpp
==============================================================================
--- sandbox/task/libs/task/examples/pending.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
+++ (empty file)
@@ -1,68 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#include <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/task.hpp"
-
-namespace pt = boost::posix_time;
-namespace tsk = boost::task;
-
-typedef tsk::static_pool< tsk::unbounded_channel< tsk::fifo > > pool_type;
-
-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
- {
- pool_type pool( tsk::poolsize( 5) );
-
- tsk::async(
- tsk::make_task( long_running_fn),
- pool);
- tsk::handle< int > h(
- tsk::async(
- tsk::make_task( fibonacci_fn, 10),
- pool) );
- std::cout << "pending tasks == " << pool.pending() << std::endl;
- std::cout << h.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;
-}
Modified: sandbox/task/libs/task/examples/priority.cpp
==============================================================================
--- sandbox/task/libs/task/examples/priority.cpp (original)
+++ sandbox/task/libs/task/examples/priority.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -29,9 +29,7 @@
{
try
{
- tsk::static_pool<
- tsk::unbounded_channel< tsk::priority< int > >
- > pool( tsk::poolsize( 1) );
+ tsk::static_pool< tsk::unbounded_onelock_prio_queue< int > > pool( tsk::poolsize( 1) );
tsk::task< void > t1( long_running_fn);
tsk::task< void > t2( print_fn, "a text.\n");
Modified: sandbox/task/libs/task/examples/semaphore_pool.cpp
==============================================================================
--- sandbox/task/libs/task/examples/semaphore_pool.cpp (original)
+++ sandbox/task/libs/task/examples/semaphore_pool.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -21,9 +21,7 @@
{
try
{
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 1) );
+ tsk::static_pool< tsk::unbounded_twolock_fifo > pool( tsk::poolsize( 1) );
int n = 10;
tsk::semaphore sem_a( 0), sem_b( 0);
Modified: sandbox/task/libs/task/examples/semaphore_pool_thread.cpp
==============================================================================
--- sandbox/task/libs/task/examples/semaphore_pool_thread.cpp (original)
+++ sandbox/task/libs/task/examples/semaphore_pool_thread.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -21,9 +21,7 @@
{
try
{
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 1) );
+ tsk::static_pool< tsk::unbounded_twolock_fifo > pool( tsk::poolsize( 1) );
int n = 10;
tsk::semaphore sem_a( 0), sem_b( 0);
Modified: sandbox/task/libs/task/examples/shutdown_now.cpp
==============================================================================
--- sandbox/task/libs/task/examples/shutdown_now.cpp (original)
+++ sandbox/task/libs/task/examples/shutdown_now.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -40,9 +40,7 @@
{
try
{
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 1) );
+ tsk::static_pool< tsk::unbounded_onelock_fifo > pool( tsk::poolsize( 1) );
tsk::task< int > t( fibonacci_fn, 10);
Modified: sandbox/task/libs/task/examples/smart.cpp
==============================================================================
--- sandbox/task/libs/task/examples/smart.cpp (original)
+++ sandbox/task/libs/task/examples/smart.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -49,13 +49,9 @@
try
{
tsk::static_pool<
- tsk::unbounded_channel<
- tsk::smart<
+ tsk::unbounded_onelock_smart_queue<
int,
- std::less< int >,
- tsk::replace_oldest,
- tsk::take_oldest
- >
+ std::less< int >
>
> pool( tsk::poolsize( 1) );
Modified: sandbox/task/libs/task/examples/submit.cpp
==============================================================================
--- sandbox/task/libs/task/examples/submit.cpp (original)
+++ sandbox/task/libs/task/examples/submit.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -35,10 +35,8 @@
{
try
{
- tsk::static_pool<
- tsk::unbounded_channel< tsk::priority< int > >
- > pool( tsk::poolsize( 3) );
-
+ tsk::static_pool< tsk::unbounded_onelock_prio_queue< int > > pool( tsk::poolsize( 3) );
+
tsk::task< int > t1( fibonacci_fn, 10);
tsk::task< int > t2( fibonacci_fn, 10);
tsk::task< int > t3( fibonacci_fn, 10);
Modified: sandbox/task/libs/task/src/callable.cpp
==============================================================================
--- sandbox/task/libs/task/src/callable.cpp (original)
+++ sandbox/task/libs/task/src/callable.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -26,10 +26,6 @@
{ impl_.reset(); }
void
-callable::reset()
-{ impl_->reset(); }
-
-void
callable::reset( shared_ptr< thread > const& thrd)
{ impl_->reset( thrd); }
Added: sandbox/task/libs/task/src/context.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/src/context.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,81 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "boost/task/context.hpp"
+
+#include <boost/assert.hpp>
+
+namespace boost { namespace task
+{
+
+void
+context::impl::reset_( shared_ptr< thread > const& thrd)
+{
+ thrd_ = thrd;
+ BOOST_ASSERT( thrd_);
+ if ( requested_)
+ if ( thrd_) thrd_->interrupt();
+}
+
+void
+context::impl::interrupt_()
+{
+ if ( ! requested_)
+ {
+ requested_ = true;
+ if ( thrd_) thrd_->interrupt();
+ }
+}
+
+context::impl::impl()
+:
+requested_( false),
+mtx_(),
+thrd_()
+{}
+
+void
+context::impl::reset( shared_ptr< thread > const& thrd)
+{
+ lock_guard< mutex > lk( mtx_);
+ reset_( thrd);
+}
+
+void
+context::impl::interrupt()
+{
+ lock_guard< mutex > lk( mtx_);
+ interrupt_();
+}
+
+bool
+context::impl::interruption_requested()
+{
+ lock_guard< mutex > lk( mtx_);
+ return requested_;
+}
+
+context::context()
+: impl_( new impl() )
+{}
+
+void
+context::reset( shared_ptr< thread > const& thrd)
+{ impl_->reset( thrd); }
+
+void
+context::interrupt()
+{ impl_->interrupt(); }
+
+bool
+context::interruption_requested()
+{ return impl_->interruption_requested(); }
+
+void
+context::swap( context & other)
+{ impl_.swap( other.impl_); }
+
+}}
Deleted: sandbox/task/libs/task/src/interrupter.cpp
==============================================================================
--- sandbox/task/libs/task/src/interrupter.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
+++ (empty file)
@@ -1,104 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#include "boost/task/detail/interrupter.hpp"
-
-#include <boost/assert.hpp>
-
-namespace boost { namespace task {
-namespace detail
-{
-
-void
-interrupter::impl::reset_( shared_ptr< thread > const& thrd)
-{
- thrd_ = thrd;
- BOOST_ASSERT( thrd_);
- if ( requested_)
- if ( thrd_) thrd_->interrupt();
-}
-
-void
-interrupter::impl::reset_()
-{
- thrd_.reset();
- try
- { this_thread::interruption_point(); }
- catch ( thread_interrupted const&)
- {}
- BOOST_ASSERT( ! this_thread::interruption_requested() );
-}
-
-void
-interrupter::impl::interrupt_()
-{
- if ( ! requested_)
- {
- requested_ = true;
- if ( thrd_) thrd_->interrupt();
- }
-}
-
-interrupter::impl::impl()
-:
-requested_( false),
-mtx_(),
-thrd_()
-{}
-
-void
-interrupter::impl::reset( shared_ptr< thread > const& thrd)
-{
- lock_guard< mutex > lk( mtx_);
- reset_( thrd);
-}
-
-void
-interrupter::impl::reset()
-{
- lock_guard< mutex > lk( mtx_);
- reset_();
-}
-
-void
-interrupter::impl::interrupt()
-{
- lock_guard< mutex > lk( mtx_);
- interrupt_();
-}
-
-bool
-interrupter::impl::interruption_requested()
-{
- lock_guard< mutex > lk( mtx_);
- return requested_;
-}
-
-interrupter::interrupter()
-: impl_( new impl() )
-{}
-
-void
-interrupter::reset( shared_ptr< thread > const& thrd)
-{ impl_->reset( thrd); }
-
-void
-interrupter::reset()
-{ impl_->reset(); }
-
-void
-interrupter::interrupt()
-{ impl_->interrupt(); }
-
-bool
-interrupter::interruption_requested()
-{ return impl_->interruption_requested(); }
-
-void
-interrupter::swap( interrupter & other)
-{ impl_.swap( other.impl_); }
-
-}}}
Modified: sandbox/task/libs/task/test/Jamfile.v2
==============================================================================
--- sandbox/task/libs/task/test/Jamfile.v2 (original)
+++ sandbox/task/libs/task/test/Jamfile.v2 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -29,7 +29,9 @@
[ task-test test_task ]
[ task-test test_own_thread ]
[ task-test test_new_thread ]
- [ task-test test_unbounded_pool ]
- [ task-test test_bounded_pool ]
+ [ task-test test_unbounded_twolock_pool ]
+ [ task-test test_unbounded_onelock_pool ]
+ [ task-test test_bounded_twolock_pool ]
+ [ task-test test_bounded_onelock_pool ]
[ task-test test_as_sub_task ]
;
Modified: sandbox/task/libs/task/test/test_as_sub_task.cpp
==============================================================================
--- sandbox/task/libs/task/test/test_as_sub_task.cpp (original)
+++ sandbox/task/libs/task/test/test_as_sub_task.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -16,7 +16,6 @@
#include <boost/ref.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>
-#include <boost/thread/barrier.hpp>
#include <boost/utility.hpp>
#include <boost/task.hpp>
@@ -54,7 +53,7 @@
void test_case_2()
{
tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
+ tsk::unbounded_onelock_fifo
> pool( tsk::poolsize( 1) );
tsk::handle< bool > h(
tsk::async(
Added: sandbox/task/libs/task/test/test_bounded_onelock_pool.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/test/test_bounded_onelock_pool.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,592 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/function.hpp>
+#include <boost/ref.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/barrier.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/task.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tsk = boost::task;
+
+class test_bounded_onelock_pool
+{
+public:
+ // check size and move op
+ void test_case_1()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool1(
+ tsk::poolsize( 3),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 5) );
+ BOOST_CHECK( pool1);
+ BOOST_CHECK_EQUAL( pool1.size(), std::size_t( 3) );
+ BOOST_CHECK_EQUAL( pool1.upper_bound(), std::size_t( 10) );
+ BOOST_CHECK_EQUAL( pool1.lower_bound(), std::size_t( 5) );
+
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool2;
+ BOOST_CHECK( ! pool2);
+ BOOST_CHECK_THROW( pool2.size(), tsk::pool_moved);
+ BOOST_CHECK_THROW( pool2.upper_bound(), tsk::pool_moved);
+ BOOST_CHECK_THROW( pool2.lower_bound(), tsk::pool_moved);
+
+ pool2 = boost::move( pool1);
+
+ BOOST_CHECK( ! pool1);
+ BOOST_CHECK_THROW( pool1.size(), tsk::pool_moved);
+ BOOST_CHECK_THROW( pool1.upper_bound(), tsk::pool_moved);
+ BOOST_CHECK_THROW( pool1.lower_bound(), tsk::pool_moved);
+
+ BOOST_CHECK( pool2);
+ BOOST_CHECK_EQUAL( pool2.size(), std::size_t( 3) );
+ BOOST_CHECK_EQUAL( pool2.upper_bound(), std::size_t( 10) );
+ BOOST_CHECK_EQUAL( pool2.lower_bound(), std::size_t( 5) );
+
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool2) );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check submit
+ void test_case_2()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check assignment
+ void test_case_3()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h1;
+ tsk::handle< int > h2(
+ tsk::async( boost::move( t), pool) );
+ h1 = h2;
+ BOOST_CHECK_EQUAL( h1.get(), 55);
+ BOOST_CHECK_EQUAL( h2.get(), 55);
+ }
+
+ // check swap
+ void test_case_4()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< int > t1( fibonacci_fn, 5);
+ tsk::task< int > t2( fibonacci_fn, 10);
+ tsk::handle< int > h1(
+ tsk::async( boost::move( t1), pool) );
+ tsk::handle< int > h2(
+ tsk::async( boost::move( t2), pool) );
+ BOOST_CHECK_EQUAL( h1.get(), 5);
+ BOOST_CHECK_EQUAL( h2.get(), 55);
+ BOOST_CHECK_NO_THROW( h1.swap( h2) );
+ BOOST_CHECK_EQUAL( h1.get(), 55);
+ BOOST_CHECK_EQUAL( h2.get(), 5);
+ }
+
+ // check runs in pool
+ void test_case_5()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< bool > t( runs_in_pool_fn);
+ tsk::handle< bool > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK_EQUAL( h.get(), true);
+ }
+
+ // check shutdown
+ void test_case_6()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool) );
+ pool.shutdown();
+ BOOST_CHECK( pool.closed() );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check runtime_error throw inside task
+ void test_case_7()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< void > t( throwing_fn);
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ pool.shutdown();
+ BOOST_CHECK_THROW( h.get(), std::runtime_error);
+ }
+
+ // check shutdown with task_rejected exception
+ void test_case_8()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ pool.shutdown();
+ BOOST_CHECK( pool.closed() );
+ BOOST_CHECK_THROW(
+ tsk::async( boost::move( t), pool),
+ tsk::task_rejected);
+ }
+
+ // check shutdown_now with thread_interrupted exception
+ void test_case_9()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 1),
+ tsk::low_watermark( 1) );
+ tsk::task< void > t( delay_fn, pt::millisec( 500) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 1) );
+ pool.shutdown_now();
+ BOOST_CHECK( pool.closed() );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 0) );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check wait
+ void test_case_10()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 1),
+ tsk::low_watermark( 1) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool) );
+ h.wait();
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check wait_for
+ void test_case_11()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 1),
+ tsk::low_watermark( 1) );
+ tsk::task< void > t( delay_fn, pt::seconds( 1) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.wait_for( pt::seconds( 3) ) );
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check wait_for
+ void test_case_12()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 1),
+ tsk::low_watermark( 1) );
+ tsk::task< void > t( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.wait_for( pt::seconds( 1) ) );
+ BOOST_CHECK( ! h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check wait_for
+ void test_case_13()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 1),
+ tsk::low_watermark( 1) );
+ tsk::task< void > t( delay_fn, pt::seconds( 1) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.wait_until( boost::get_system_time() + pt::seconds( 3) ) );
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check wait_for
+ void test_case_14()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 1),
+ tsk::low_watermark( 1) );
+ tsk::task< void > t( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.wait_until( boost::get_system_time() + pt::seconds( 1) ) );
+ BOOST_CHECK( ! h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check interrupt
+ void test_case_15()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< void > t( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ h.interrupt();
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_all_worker
+ void test_case_16()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< void > t1( delay_fn, pt::seconds( 3) );
+ tsk::task< void > t2( delay_fn, pt::seconds( 3) );
+ tsk::task< void > t3( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h1(
+ tsk::async( boost::move( t1), pool) );
+ tsk::handle< void > h2(
+ tsk::async( boost::move( t2), pool) );
+ tsk::handle< void > h3(
+ tsk::async( boost::move( t3), pool) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ pool.interrupt_all_worker();
+ BOOST_CHECK( ! h1.interruption_requested() );
+ BOOST_CHECK( ! h2.interruption_requested() );
+ BOOST_CHECK( ! h3.interruption_requested() );
+ BOOST_CHECK_THROW( h1.get(), tsk::task_interrupted);
+ BOOST_CHECK_THROW( h2.get(), tsk::task_interrupted);
+ BOOST_CHECK_THROW( h3.get(), tsk::task_interrupted);
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 5) );
+ }
+
+ // check interrupt_and_wait
+ void test_case_17()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ bool finished( false);
+ tsk::task< void > t( interrupt_fn, pt::seconds( 1), boost::ref( finished) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ h.interrupt_and_wait();
+ BOOST_CHECK( finished);
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( h.has_exception() );
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_and_wait_for
+ void test_case_18()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ bool finished( false);
+ tsk::task< void > t( interrupt_fn, pt::seconds( 1), boost::ref( finished) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.interrupt_and_wait_for( pt::seconds( 3) ) );
+ BOOST_CHECK( finished);
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( h.has_exception() );
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_and_wait_for
+ void test_case_19()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< void > t( non_interrupt_fn, 3);
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.interrupt_and_wait_for( pt::seconds( 1) ) );
+ }
+
+ // check interrupt_and_wait_until
+ void test_case_20()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ bool finished( false);
+ tsk::task< void > t(
+ interrupt_fn,
+ pt::seconds( 1),
+ boost::ref( finished) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.interrupt_and_wait_until( boost::get_system_time() + pt::seconds( 3) ) );
+ BOOST_CHECK( finished);
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( h.has_exception() );
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_and_wait_until
+ void test_case_21()
+ {
+ tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< void > t( non_interrupt_fn, 3);
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.interrupt_and_wait_until( boost::get_system_time() + pt::seconds( 1) ) );
+ }
+
+ // check fifo scheduling
+ void test_case_22()
+ {
+ typedef tsk::static_pool<
+ tsk::bounded_onelock_fifo
+ > pool_type;
+ BOOST_CHECK( ! tsk::has_attribute< pool_type >::value);
+ pool_type pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ boost::barrier b( 2);
+ std::vector< int > buffer;
+ tsk::task< void > t1( barrier_fn, boost::ref( b) );
+ tsk::task< void > t2(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10);
+ tsk::task< void > t3(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0);
+ tsk::async( boost::move( t1), pool);
+ boost::this_thread::sleep( pt::millisec( 250) );
+ tsk::async( boost::move( t2), pool);
+ tsk::async( boost::move( t3), pool);
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 55);
+ BOOST_CHECK_EQUAL( buffer[1], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
+ }
+
+ // check priority scheduling
+ void test_case_23()
+ {
+ typedef tsk::static_pool<
+ tsk::bounded_onelock_prio_queue< int >
+ > pool_type;
+ BOOST_CHECK( tsk::has_attribute< pool_type >::value);
+ typedef boost::is_same< tsk::attribute_type< pool_type >::type, int > type;
+ BOOST_CHECK( type::value);
+ pool_type pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ boost::barrier b( 2);
+ std::vector< int > buffer;
+ tsk::task< void > t1( barrier_fn, boost::ref( b) );
+ tsk::task< void > t2(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10);
+ tsk::task< void > t3(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0);
+ tsk::async( boost::move( t1), 0, pool);
+ boost::this_thread::sleep( pt::millisec( 250) );
+ tsk::async( boost::move( t2), 1, pool);
+ tsk::async( boost::move( t3), 0, pool);
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 55);
+ BOOST_CHECK_EQUAL( buffer[1], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
+ }
+
+ // check smart scheduling
+ void test_case_24()
+ {
+ typedef tsk::static_pool<
+ tsk::bounded_onelock_smart_queue< int, std::less< int > >
+ > pool_type;
+ BOOST_CHECK( tsk::has_attribute< pool_type >::value);
+ typedef boost::is_same< tsk::attribute_type< pool_type >::type, int > type;
+ BOOST_CHECK( type::value);
+ pool_type pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ boost::barrier b( 2);
+ std::vector< int > buffer;
+ tsk::task< void > t1(
+ barrier_fn,
+ boost::ref( b) );
+ tsk::task< void > t2(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10);
+ tsk::task< void > t3(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0);
+ tsk::task< void > t4(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 1);
+ pool.submit( boost::move( t1), 0);
+ boost::this_thread::sleep( pt::millisec( 250) );
+ tsk::async( boost::move( t2), 2, pool);
+ tsk::async( boost::move( t3), 1, pool);
+ tsk::async( boost::move( t4), 2, pool);
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer[1], 1);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
+ }
+};
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test( BOOST_TEST_SUITE("Boost.Task: test suite") );
+
+ boost::shared_ptr< test_bounded_onelock_pool > instance( new test_bounded_onelock_pool() );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_3, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_5, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_6, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_7, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_8, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_9, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_10, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_11, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_12, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_13, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_14, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_15, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_16, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_17, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_18, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_19, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_20, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_21, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_22, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_23, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_onelock_pool::test_case_24, instance) );
+
+ return test;
+}
+
Deleted: sandbox/task/libs/task/test/test_bounded_pool.cpp
==============================================================================
--- sandbox/task/libs/task/test/test_bounded_pool.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
+++ (empty file)
@@ -1,639 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#include <cstdlib>
-#include <iostream>
-#include <map>
-#include <stdexcept>
-#include <vector>
-
-#include <boost/bind.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/function.hpp>
-#include <boost/ref.hpp>
-#include <boost/test/unit_test.hpp>
-#include <boost/thread.hpp>
-#include <boost/thread/barrier.hpp>
-#include <boost/type_traits/is_same.hpp>
-#include <boost/utility.hpp>
-
-#include <boost/task.hpp>
-
-#include "test_functions.hpp"
-
-namespace pt = boost::posix_time;
-namespace tsk = boost::task;
-
-class test_bounded_pool
-{
-public:
- // check size, active, idle
- void test_case_1()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool1(
- tsk::poolsize( 3),
- tsk::high_watermark( 10),
- tsk::low_watermark( 5) );
- BOOST_CHECK( pool1);
- BOOST_CHECK_EQUAL( pool1.size(), std::size_t( 3) );
- BOOST_CHECK_EQUAL( pool1.idle(), std::size_t( 3) );
- BOOST_CHECK_EQUAL( pool1.active(), std::size_t( 0) );
- BOOST_CHECK_EQUAL( pool1.upper_bound(), std::size_t( 10) );
- BOOST_CHECK_EQUAL( pool1.lower_bound(), std::size_t( 5) );
-
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool2;
- BOOST_CHECK( ! pool2);
- BOOST_CHECK_THROW( pool2.size(), tsk::pool_moved);
- BOOST_CHECK_THROW( pool2.idle(), tsk::pool_moved);
- BOOST_CHECK_THROW( pool2.active(), tsk::pool_moved);
- BOOST_CHECK_THROW( pool2.upper_bound(), tsk::pool_moved);
- BOOST_CHECK_THROW( pool2.lower_bound(), tsk::pool_moved);
-
- pool2 = boost::move( pool1);
-
- BOOST_CHECK( ! pool1);
- BOOST_CHECK_THROW( pool1.size(), tsk::pool_moved);
- BOOST_CHECK_THROW( pool1.idle(), tsk::pool_moved);
- BOOST_CHECK_THROW( pool1.active(), tsk::pool_moved);
- BOOST_CHECK_THROW( pool1.upper_bound(), tsk::pool_moved);
- BOOST_CHECK_THROW( pool1.lower_bound(), tsk::pool_moved);
-
- BOOST_CHECK( pool2);
- BOOST_CHECK_EQUAL( pool2.size(), std::size_t( 3) );
- BOOST_CHECK_EQUAL( pool2.idle(), std::size_t( 3) );
- BOOST_CHECK_EQUAL( pool2.active(), std::size_t( 0) );
- BOOST_CHECK_EQUAL( pool2.upper_bound(), std::size_t( 10) );
- BOOST_CHECK_EQUAL( pool2.lower_bound(), std::size_t( 5) );
-
- tsk::task< int > t( fibonacci_fn, 10);
- tsk::handle< int > h(
- tsk::async( boost::move( t), pool2) );
- BOOST_CHECK_EQUAL( h.get(), 55);
- }
-
- // check submit
- void test_case_2()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 1),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- tsk::task< int > t( fibonacci_fn, 10);
- tsk::handle< int > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK_EQUAL( h.get(), 55);
- }
-
- // check assignment
- void test_case_3()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 5),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- tsk::task< int > t( fibonacci_fn, 10);
- tsk::handle< int > h1;
- tsk::handle< int > h2(
- tsk::async( boost::move( t), pool) );
- h1 = h2;
- BOOST_CHECK_EQUAL( h1.get(), 55);
- BOOST_CHECK_EQUAL( h2.get(), 55);
- }
-
- // check swap
- void test_case_4()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 5),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- tsk::task< int > t1( fibonacci_fn, 5);
- tsk::task< int > t2( fibonacci_fn, 10);
- tsk::handle< int > h1(
- tsk::async( boost::move( t1), pool) );
- tsk::handle< int > h2(
- tsk::async( boost::move( t2), pool) );
- BOOST_CHECK_EQUAL( h1.get(), 5);
- BOOST_CHECK_EQUAL( h2.get(), 55);
- BOOST_CHECK_NO_THROW( h1.swap( h2) );
- BOOST_CHECK_EQUAL( h1.get(), 55);
- BOOST_CHECK_EQUAL( h2.get(), 5);
- }
-
- // check runs in pool
- void test_case_5()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 1),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- tsk::task< bool > t( runs_in_pool_fn);
- tsk::handle< bool > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK_EQUAL( h.get(), true);
- }
-
- // check shutdown
- void test_case_6()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 1),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- tsk::task< int > t( fibonacci_fn, 10);
- tsk::handle< int > h(
- tsk::async( boost::move( t), pool) );
- pool.shutdown();
- BOOST_CHECK( pool.closed() );
- BOOST_CHECK_EQUAL( h.get(), 55);
- }
-
- // check runtime_error throw inside task
- void test_case_7()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 1),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- tsk::task< void > t( throwing_fn);
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- pool.shutdown();
- BOOST_CHECK_THROW( h.get(), std::runtime_error);
- }
-
- // check shutdown with task_rejected exception
- void test_case_8()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 1),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- tsk::task< int > t( fibonacci_fn, 10);
- pool.shutdown();
- BOOST_CHECK( pool.closed() );
- BOOST_CHECK_THROW(
- tsk::async( boost::move( t), pool),
- tsk::task_rejected);
- }
-
- // check shutdown_now with thread_interrupted exception
- void test_case_9()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 1),
- tsk::high_watermark( 1),
- tsk::low_watermark( 1) );
- tsk::task< void > t( delay_fn, pt::millisec( 500) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- boost::this_thread::sleep( pt::millisec( 250) );
- BOOST_CHECK_EQUAL( pool.size(), std::size_t( 1) );
- pool.shutdown_now();
- BOOST_CHECK( pool.closed() );
- BOOST_CHECK_EQUAL( pool.size(), std::size_t( 0) );
- BOOST_CHECK_EQUAL( pool.idle(), std::size_t( 0) );
- BOOST_CHECK_EQUAL( pool.active(), std::size_t( 0) );
- BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
- }
-
- // check pending
- void test_case_10()
- {
- typedef tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool_type;
- pool_type pool(
- tsk::poolsize( 1),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- boost::barrier b( 2);
- tsk::task< void > t1(
- barrier_fn,
- boost::ref( b) );
- tsk::task< int > t2(
- fibonacci_fn,
- 10);
- tsk::task< int > t3(
- fibonacci_fn,
- 10);
- tsk::handle< void > h1(
- tsk::async( boost::move( t1), pool) );
- boost::this_thread::sleep( pt::millisec( 250) );
- BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
- tsk::handle< int > h2(
- tsk::async( boost::move( t2), pool) );
- boost::this_thread::sleep( pt::millisec(250) );
- BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 1) );
- tsk::handle< int > h3(
- tsk::async( boost::move( t3), pool) );
- boost::this_thread::sleep( pt::millisec(250) );
- BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 2) );
- b.wait();
- h1.get();
- BOOST_CHECK_EQUAL( h2.get(), 55);
- BOOST_CHECK_EQUAL( h3.get(), 55);
- BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
- }
-
- // check wait
- void test_case_11()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 5),
- tsk::high_watermark( 1),
- tsk::low_watermark( 1) );
- tsk::task< int > t( fibonacci_fn, 10);
- tsk::handle< int > h(
- tsk::async( boost::move( t), pool) );
- h.wait();
- BOOST_CHECK( h.is_ready() );
- BOOST_CHECK( h.has_value() );
- BOOST_CHECK( ! h.has_exception() );
- BOOST_CHECK_EQUAL( h.get(), 55);
- }
-
- // check wait_for
- void test_case_12()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 5),
- tsk::high_watermark( 1),
- tsk::low_watermark( 1) );
- tsk::task< void > t( delay_fn, pt::seconds( 1) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( h.wait_for( pt::seconds( 3) ) );
- BOOST_CHECK( h.is_ready() );
- BOOST_CHECK( h.has_value() );
- BOOST_CHECK( ! h.has_exception() );
- }
-
- // check wait_for
- void test_case_13()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 5),
- tsk::high_watermark( 1),
- tsk::low_watermark( 1) );
- tsk::task< void > t( delay_fn, pt::seconds( 3) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( ! h.wait_for( pt::seconds( 1) ) );
- BOOST_CHECK( ! h.is_ready() );
- BOOST_CHECK( ! h.has_value() );
- BOOST_CHECK( ! h.has_exception() );
- }
-
- // check wait_for
- void test_case_14()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 5),
- tsk::high_watermark( 1),
- tsk::low_watermark( 1) );
- tsk::task< void > t( delay_fn, pt::seconds( 1) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( h.wait_until( boost::get_system_time() + pt::seconds( 3) ) );
- BOOST_CHECK( h.is_ready() );
- BOOST_CHECK( h.has_value() );
- BOOST_CHECK( ! h.has_exception() );
- }
-
- // check wait_for
- void test_case_15()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 5),
- tsk::high_watermark( 1),
- tsk::low_watermark( 1) );
- tsk::task< void > t( delay_fn, pt::seconds( 3) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( ! h.wait_until( boost::get_system_time() + pt::seconds( 1) ) );
- BOOST_CHECK( ! h.is_ready() );
- BOOST_CHECK( ! h.has_value() );
- BOOST_CHECK( ! h.has_exception() );
- }
-
- // check interrupt
- void test_case_16()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 5),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- tsk::task< void > t( delay_fn, pt::seconds( 3) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- h.interrupt();
- BOOST_CHECK( h.interruption_requested() );
- BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
- }
-
- // check interrupt_all_worker
- void test_case_17()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 5),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- tsk::task< void > t1( delay_fn, pt::seconds( 3) );
- tsk::task< void > t2( delay_fn, pt::seconds( 3) );
- tsk::task< void > t3( delay_fn, pt::seconds( 3) );
- tsk::handle< void > h1(
- tsk::async( boost::move( t1), pool) );
- tsk::handle< void > h2(
- tsk::async( boost::move( t2), pool) );
- tsk::handle< void > h3(
- tsk::async( boost::move( t3), pool) );
- boost::this_thread::sleep( pt::millisec( 250) );
- pool.interrupt_all_worker();
- BOOST_CHECK( ! h1.interruption_requested() );
- BOOST_CHECK( ! h2.interruption_requested() );
- BOOST_CHECK( ! h3.interruption_requested() );
- BOOST_CHECK_THROW( h1.get(), tsk::task_interrupted);
- BOOST_CHECK_THROW( h2.get(), tsk::task_interrupted);
- BOOST_CHECK_THROW( h3.get(), tsk::task_interrupted);
- BOOST_CHECK_EQUAL( pool.size(), std::size_t( 5) );
- }
-
- // check interrupt_and_wait
- void test_case_18()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 5),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- bool finished( false);
- tsk::task< void > t( interrupt_fn, pt::seconds( 1), boost::ref( finished) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- h.interrupt_and_wait();
- BOOST_CHECK( finished);
- BOOST_CHECK( h.is_ready() );
- BOOST_CHECK( ! h.has_value() );
- BOOST_CHECK( h.has_exception() );
- BOOST_CHECK( h.interruption_requested() );
- BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
- }
-
- // check interrupt_and_wait_for
- void test_case_19()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 5),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- bool finished( false);
- tsk::task< void > t( interrupt_fn, pt::seconds( 1), boost::ref( finished) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( h.interrupt_and_wait_for( pt::seconds( 3) ) );
- BOOST_CHECK( finished);
- BOOST_CHECK( h.is_ready() );
- BOOST_CHECK( ! h.has_value() );
- BOOST_CHECK( h.has_exception() );
- BOOST_CHECK( h.interruption_requested() );
- BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
- }
-
- // check interrupt_and_wait_for
- void test_case_20()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 5),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- tsk::task< void > t( non_interrupt_fn, 3);
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( ! h.interrupt_and_wait_for( pt::seconds( 1) ) );
- }
-
- // check interrupt_and_wait_until
- void test_case_21()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 5),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- bool finished( false);
- tsk::task< void > t(
- interrupt_fn,
- pt::seconds( 1),
- boost::ref( finished) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( h.interrupt_and_wait_until( boost::get_system_time() + pt::seconds( 3) ) );
- BOOST_CHECK( finished);
- BOOST_CHECK( h.is_ready() );
- BOOST_CHECK( ! h.has_value() );
- BOOST_CHECK( h.has_exception() );
- BOOST_CHECK( h.interruption_requested() );
- BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
- }
-
- // check interrupt_and_wait_until
- void test_case_22()
- {
- tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool(
- tsk::poolsize( 5),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- tsk::task< void > t( non_interrupt_fn, 3);
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( ! h.interrupt_and_wait_until( boost::get_system_time() + pt::seconds( 1) ) );
- }
-
- // check fifo scheduling
- void test_case_23()
- {
- typedef tsk::static_pool<
- tsk::bounded_channel< tsk::fifo >
- > pool_type;
- BOOST_CHECK( ! tsk::has_attribute< pool_type >::value);
- pool_type pool(
- tsk::poolsize( 1),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- boost::barrier b( 2);
- std::vector< int > buffer;
- tsk::task< void > t1( barrier_fn, boost::ref( b) );
- tsk::task< void > t2(
- buffer_fibonacci_fn,
- boost::ref( buffer),
- 10);
- tsk::task< void > t3(
- buffer_fibonacci_fn,
- boost::ref( buffer),
- 0);
- tsk::async( boost::move( t1), pool);
- tsk::async( boost::move( t2), pool);
- tsk::async( boost::move( t3), pool);
- b.wait();
- pool.shutdown();
- BOOST_CHECK_EQUAL( buffer[0], 55);
- BOOST_CHECK_EQUAL( buffer[1], 0);
- BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
- }
-
- // check priority scheduling
- void test_case_24()
- {
- typedef tsk::static_pool<
- tsk::bounded_channel< tsk::priority< int > >
- > pool_type;
- BOOST_CHECK( tsk::has_attribute< pool_type >::value);
- typedef boost::is_same< tsk::attribute_type< pool_type >::type, int > type;
- BOOST_CHECK( type::value);
- pool_type pool(
- tsk::poolsize( 1),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- boost::barrier b( 2);
- std::vector< int > buffer;
- tsk::task< void > t1( barrier_fn, boost::ref( b) );
- tsk::task< void > t2(
- buffer_fibonacci_fn,
- boost::ref( buffer),
- 10);
- tsk::task< void > t3(
- buffer_fibonacci_fn,
- boost::ref( buffer),
- 0);
- tsk::async( boost::move( t1), 0, pool);
- tsk::async( boost::move( t2), 1, pool);
- tsk::async( boost::move( t3), 0, pool);
- b.wait();
- pool.shutdown();
- BOOST_CHECK_EQUAL( buffer[0], 55);
- BOOST_CHECK_EQUAL( buffer[1], 0);
- BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
- }
-
- // check smart scheduling
- void test_case_25()
- {
- typedef tsk::static_pool<
- tsk::bounded_channel< tsk::smart< int, std::less< int >, tsk::replace_oldest, tsk::take_oldest > >
- > pool_type;
- BOOST_CHECK( tsk::has_attribute< pool_type >::value);
- typedef boost::is_same< tsk::attribute_type< pool_type >::type, int > type;
- BOOST_CHECK( type::value);
- pool_type pool(
- tsk::poolsize( 1),
- tsk::high_watermark( 10),
- tsk::low_watermark( 10) );
- boost::barrier b( 2);
- std::vector< int > buffer;
- tsk::task< void > t1(
- barrier_fn,
- boost::ref( b) );
- tsk::task< void > t2(
- buffer_fibonacci_fn,
- boost::ref( buffer),
- 10);
- tsk::task< void > t3(
- buffer_fibonacci_fn,
- boost::ref( buffer),
- 0);
- tsk::task< void > t4(
- buffer_fibonacci_fn,
- boost::ref( buffer),
- 1);
- tsk::async( boost::move( t1), 0, pool);
- tsk::async( boost::move( t2), 2, pool);
- tsk::async( boost::move( t3), 1, pool);
- tsk::async( boost::move( t4), 2, pool);
- b.wait();
- pool.shutdown();
- BOOST_CHECK_EQUAL( buffer[0], 0);
- BOOST_CHECK_EQUAL( buffer[1], 1);
- BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
- }
-};
-
-boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
-{
- boost::unit_test::test_suite * test( BOOST_TEST_SUITE("Boost.Task: test suite") );
-
- boost::shared_ptr< test_bounded_pool > instance( new test_bounded_pool() );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_1, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_2, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_3, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_4, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_5, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_6, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_7, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_8, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_9, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_10, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_11, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_12, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_13, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_14, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_15, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_16, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_17, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_18, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_19, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_20, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_21, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_22, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_23, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_24, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_bounded_pool::test_case_25, instance) );
-
- return test;
-}
-
Added: sandbox/task/libs/task/test/test_bounded_twolock_pool.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/test/test_bounded_twolock_pool.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,513 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/function.hpp>
+#include <boost/ref.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/barrier.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/task.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tsk = boost::task;
+
+class test_bounded_twolock_pool
+{
+public:
+ // check size and move op
+ void test_case_1()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool1(
+ tsk::poolsize( 3),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 5) );
+ BOOST_CHECK( pool1);
+ BOOST_CHECK_EQUAL( pool1.size(), std::size_t( 3) );
+ BOOST_CHECK_EQUAL( pool1.upper_bound(), std::size_t( 10) );
+ BOOST_CHECK_EQUAL( pool1.lower_bound(), std::size_t( 5) );
+
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool2;
+ BOOST_CHECK( ! pool2);
+ BOOST_CHECK_THROW( pool2.size(), tsk::pool_moved);
+ BOOST_CHECK_THROW( pool2.upper_bound(), tsk::pool_moved);
+ BOOST_CHECK_THROW( pool2.lower_bound(), tsk::pool_moved);
+
+ pool2 = boost::move( pool1);
+
+ BOOST_CHECK( ! pool1);
+ BOOST_CHECK_THROW( pool1.size(), tsk::pool_moved);
+ BOOST_CHECK_THROW( pool1.upper_bound(), tsk::pool_moved);
+ BOOST_CHECK_THROW( pool1.lower_bound(), tsk::pool_moved);
+
+ BOOST_CHECK( pool2);
+ BOOST_CHECK_EQUAL( pool2.size(), std::size_t( 3) );
+ BOOST_CHECK_EQUAL( pool2.upper_bound(), std::size_t( 10) );
+ BOOST_CHECK_EQUAL( pool2.lower_bound(), std::size_t( 5) );
+
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool2) );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check submit
+ void test_case_2()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check assignment
+ void test_case_3()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h1;
+ tsk::handle< int > h2(
+ tsk::async( boost::move( t), pool) );
+ h1 = h2;
+ BOOST_CHECK_EQUAL( h1.get(), 55);
+ BOOST_CHECK_EQUAL( h2.get(), 55);
+ }
+
+ // check swap
+ void test_case_4()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< int > t1( fibonacci_fn, 5);
+ tsk::task< int > t2( fibonacci_fn, 10);
+ tsk::handle< int > h1(
+ tsk::async( boost::move( t1), pool) );
+ tsk::handle< int > h2(
+ tsk::async( boost::move( t2), pool) );
+ BOOST_CHECK_EQUAL( h1.get(), 5);
+ BOOST_CHECK_EQUAL( h2.get(), 55);
+ BOOST_CHECK_NO_THROW( h1.swap( h2) );
+ BOOST_CHECK_EQUAL( h1.get(), 55);
+ BOOST_CHECK_EQUAL( h2.get(), 5);
+ }
+
+ // check runs in pool
+ void test_case_5()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< bool > t( runs_in_pool_fn);
+ tsk::handle< bool > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK_EQUAL( h.get(), true);
+ }
+
+ // check shutdown
+ void test_case_6()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool) );
+ pool.shutdown();
+ BOOST_CHECK( pool.closed() );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check runtime_error throw inside task
+ void test_case_7()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< void > t( throwing_fn);
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ pool.shutdown();
+ BOOST_CHECK_THROW( h.get(), std::runtime_error);
+ }
+
+ // check shutdown with task_rejected exception
+ void test_case_8()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ pool.shutdown();
+ BOOST_CHECK( pool.closed() );
+ BOOST_CHECK_THROW(
+ tsk::async( boost::move( t), pool),
+ tsk::task_rejected);
+ }
+
+ // check shutdown_now with thread_interrupted exception
+ void test_case_9()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 1),
+ tsk::low_watermark( 1) );
+ tsk::task< void > t( delay_fn, pt::millisec( 500) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 1) );
+ pool.shutdown_now();
+ BOOST_CHECK( pool.closed() );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 0) );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check wait
+ void test_case_10()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 1),
+ tsk::low_watermark( 1) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool) );
+ h.wait();
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check wait_for
+ void test_case_11()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 1),
+ tsk::low_watermark( 1) );
+ tsk::task< void > t( delay_fn, pt::seconds( 1) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.wait_for( pt::seconds( 3) ) );
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check wait_for
+ void test_case_12()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 1),
+ tsk::low_watermark( 1) );
+ tsk::task< void > t( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.wait_for( pt::seconds( 1) ) );
+ BOOST_CHECK( ! h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check wait_for
+ void test_case_13()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 1),
+ tsk::low_watermark( 1) );
+ tsk::task< void > t( delay_fn, pt::seconds( 1) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.wait_until( boost::get_system_time() + pt::seconds( 3) ) );
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check wait_for
+ void test_case_14()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 1),
+ tsk::low_watermark( 1) );
+ tsk::task< void > t( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.wait_until( boost::get_system_time() + pt::seconds( 1) ) );
+ BOOST_CHECK( ! h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check interrupt
+ void test_case_15()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< void > t( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ h.interrupt();
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_all_worker
+ void test_case_16()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< void > t1( delay_fn, pt::seconds( 3) );
+ tsk::task< void > t2( delay_fn, pt::seconds( 3) );
+ tsk::task< void > t3( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h1(
+ tsk::async( boost::move( t1), pool) );
+ tsk::handle< void > h2(
+ tsk::async( boost::move( t2), pool) );
+ tsk::handle< void > h3(
+ tsk::async( boost::move( t3), pool) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ pool.interrupt_all_worker();
+ BOOST_CHECK( ! h1.interruption_requested() );
+ BOOST_CHECK( ! h2.interruption_requested() );
+ BOOST_CHECK( ! h3.interruption_requested() );
+ BOOST_CHECK_THROW( h1.get(), tsk::task_interrupted);
+ BOOST_CHECK_THROW( h2.get(), tsk::task_interrupted);
+ BOOST_CHECK_THROW( h3.get(), tsk::task_interrupted);
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 5) );
+ }
+
+ // check interrupt_and_wait
+ void test_case_17()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ bool finished( false);
+ tsk::task< void > t( interrupt_fn, pt::seconds( 1), boost::ref( finished) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ h.interrupt_and_wait();
+ BOOST_CHECK( finished);
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( h.has_exception() );
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_and_wait_for
+ void test_case_18()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ bool finished( false);
+ tsk::task< void > t( interrupt_fn, pt::seconds( 1), boost::ref( finished) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.interrupt_and_wait_for( pt::seconds( 3) ) );
+ BOOST_CHECK( finished);
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( h.has_exception() );
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_and_wait_for
+ void test_case_19()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< void > t( non_interrupt_fn, 3);
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.interrupt_and_wait_for( pt::seconds( 1) ) );
+ }
+
+ // check interrupt_and_wait_until
+ void test_case_20()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ bool finished( false);
+ tsk::task< void > t(
+ interrupt_fn,
+ pt::seconds( 1),
+ boost::ref( finished) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.interrupt_and_wait_until( boost::get_system_time() + pt::seconds( 3) ) );
+ BOOST_CHECK( finished);
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( h.has_exception() );
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_and_wait_until
+ void test_case_21()
+ {
+ tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool(
+ tsk::poolsize( 5),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ tsk::task< void > t( non_interrupt_fn, 3);
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.interrupt_and_wait_until( boost::get_system_time() + pt::seconds( 1) ) );
+ }
+
+ // check fifo scheduling
+ void test_case_22()
+ {
+ typedef tsk::static_pool<
+ tsk::bounded_twolock_fifo
+ > pool_type;
+ BOOST_CHECK( ! tsk::has_attribute< pool_type >::value);
+ pool_type pool(
+ tsk::poolsize( 1),
+ tsk::high_watermark( 10),
+ tsk::low_watermark( 10) );
+ boost::barrier b( 2);
+ std::vector< int > buffer;
+ tsk::task< void > t1( barrier_fn, boost::ref( b) );
+ tsk::task< void > t2(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10);
+ tsk::task< void > t3(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0);
+ tsk::async( boost::move( t1), pool);
+ boost::this_thread::sleep( pt::millisec( 250) );
+ tsk::async( boost::move( t2), pool);
+ tsk::async( boost::move( t3), pool);
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 55);
+ BOOST_CHECK_EQUAL( buffer[1], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
+ }
+};
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test( BOOST_TEST_SUITE("Boost.Task: test suite") );
+
+ boost::shared_ptr< test_bounded_twolock_pool > instance( new test_bounded_twolock_pool() );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_3, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_5, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_6, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_7, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_8, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_9, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_10, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_11, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_12, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_13, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_14, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_15, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_16, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_17, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_18, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_19, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_20, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_21, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_bounded_twolock_pool::test_case_22, instance) );
+
+ return test;
+}
+
Modified: sandbox/task/libs/task/test/test_new_thread.cpp
==============================================================================
--- sandbox/task/libs/task/test/test_new_thread.cpp (original)
+++ sandbox/task/libs/task/test/test_new_thread.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -16,7 +16,6 @@
#include <boost/ref.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>
-#include <boost/thread/barrier.hpp>
#include <boost/utility.hpp>
#include <boost/task.hpp>
Modified: sandbox/task/libs/task/test/test_own_thread.cpp
==============================================================================
--- sandbox/task/libs/task/test/test_own_thread.cpp (original)
+++ sandbox/task/libs/task/test/test_own_thread.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -16,7 +16,6 @@
#include <boost/ref.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>
-#include <boost/thread/barrier.hpp>
#include <boost/utility.hpp>
#include <boost/task.hpp>
Modified: sandbox/task/libs/task/test/test_task.cpp
==============================================================================
--- sandbox/task/libs/task/test/test_task.cpp (original)
+++ sandbox/task/libs/task/test/test_task.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -16,7 +16,6 @@
#include <boost/ref.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>
-#include <boost/thread/barrier.hpp>
#include <boost/utility.hpp>
#include <boost/task.hpp>
Added: sandbox/task/libs/task/test/test_unbounded_onelock_pool.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/test/test_unbounded_onelock_pool.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,515 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/function.hpp>
+#include <boost/ref.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/barrier.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/task.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tsk = boost::task;
+
+class test_unbounded_onelock_pool
+{
+public:
+ // check size and move op
+ void test_case_1()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool1( tsk::poolsize( 3) );
+ BOOST_CHECK( pool1);
+ BOOST_CHECK_EQUAL( pool1.size(), std::size_t( 3) );
+
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool2;
+ BOOST_CHECK( ! pool2);
+ BOOST_CHECK_THROW( pool2.size(), tsk::pool_moved);
+
+ pool2 = boost::move( pool1);
+
+ BOOST_CHECK( ! pool1);
+ BOOST_CHECK_THROW( pool1.size(), tsk::pool_moved);
+
+ BOOST_CHECK( pool2);
+ BOOST_CHECK_EQUAL( pool2.size(), std::size_t( 3) );
+
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool2) );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check submit
+ void test_case_2()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check assignment
+ void test_case_3()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h1;
+ tsk::handle< int > h2(
+ tsk::async( boost::move( t), pool) );
+ h1 = h2;
+ BOOST_CHECK_EQUAL( h1.get(), 55);
+ BOOST_CHECK_EQUAL( h2.get(), 55);
+ }
+
+ // check swap
+ void test_case_4()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< int > t1( fibonacci_fn, 5);
+ tsk::task< int > t2( fibonacci_fn, 10);
+ tsk::handle< int > h1(
+ tsk::async( boost::move( t1), pool) );
+ tsk::handle< int > h2(
+ tsk::async( boost::move( t2), pool) );
+ BOOST_CHECK_EQUAL( h1.get(), 5);
+ BOOST_CHECK_EQUAL( h2.get(), 55);
+ BOOST_CHECK_NO_THROW( h1.swap( h2) );
+ BOOST_CHECK_EQUAL( h1.get(), 55);
+ BOOST_CHECK_EQUAL( h2.get(), 5);
+ }
+
+ // check runs in pool
+ void test_case_5()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 1) );
+ tsk::task< bool > t( runs_in_pool_fn);
+ tsk::handle< bool > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK_EQUAL( h.get(), true);
+ }
+
+ // check shutdown
+ void test_case_6()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 1) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool) );
+ pool.shutdown();
+ BOOST_CHECK( pool.closed() );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check runtime_error throw inside task
+ void test_case_7()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 1) );
+ tsk::task< void > t( throwing_fn);
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ pool.shutdown();
+ BOOST_CHECK_THROW( h.get(), std::runtime_error);
+ }
+
+ // check shutdown with task_rejected exception
+ void test_case_8()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 1) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ pool.shutdown();
+ BOOST_CHECK( pool.closed() );
+ BOOST_CHECK_THROW(
+ tsk::async( boost::move( t), pool),
+ tsk::task_rejected);
+ }
+
+ // check shutdown_now with thread_interrupted exception
+ void test_case_9()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 1) );
+ tsk::task< void > t( delay_fn, pt::millisec( 500) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 1) );
+ pool.shutdown_now();
+ BOOST_CHECK( pool.closed() );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 0) );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check wait
+ void test_case_10()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool) );
+ h.wait();
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check wait_for
+ void test_case_11()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< void > t( delay_fn, pt::seconds( 1) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.wait_for( pt::seconds( 3) ) );
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check wait_for
+ void test_case_12()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< void > t( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.wait_for( pt::seconds( 1) ) );
+ BOOST_CHECK( ! h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check wait_until
+ void test_case_13()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< void > t( delay_fn, pt::seconds( 1) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.wait_until( boost::get_system_time() + pt::seconds( 3) ) );
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check wait_until
+ void test_case_14()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< void > t( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.wait_until( boost::get_system_time() + pt::seconds( 1) ) );
+ BOOST_CHECK( ! h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check interrupt
+ void test_case_15()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< void > t( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ h.interrupt();
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_all_worker
+ void test_case_16()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 5) );
+ tsk::task< void > t1( delay_fn, pt::seconds( 3) );
+ tsk::task< void > t2( delay_fn, pt::seconds( 3) );
+ tsk::task< void > t3( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h1(
+ tsk::async( boost::move( t1), pool) );
+ tsk::handle< void > h2(
+ tsk::async( boost::move( t2), pool) );
+ tsk::handle< void > h3(
+ tsk::async( boost::move( t3), pool) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ pool.interrupt_all_worker();
+ BOOST_CHECK( ! h1.interruption_requested() );
+ BOOST_CHECK( ! h2.interruption_requested() );
+ BOOST_CHECK( ! h3.interruption_requested() );
+ BOOST_CHECK_THROW( h1.get(), tsk::task_interrupted);
+ BOOST_CHECK_THROW( h2.get(), tsk::task_interrupted);
+ BOOST_CHECK_THROW( h3.get(), tsk::task_interrupted);
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 5) );
+ }
+
+ // check interrupt_and_wait
+ void test_case_17()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 3) );
+ bool finished( false);
+ tsk::task< void > t(
+ interrupt_fn,
+ pt::seconds( 1),
+ boost::ref( finished) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ h.interrupt_and_wait();
+ BOOST_CHECK( finished);
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( h.has_exception() );
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_and_wait_for
+ void test_case_18()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 3) );
+ bool finished( false);
+ tsk::task< void > t(
+ interrupt_fn,
+ pt::seconds( 1),
+ boost::ref( finished) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.interrupt_and_wait_for( pt::seconds( 3) ) );
+ BOOST_CHECK( finished);
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( h.has_exception() );
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_and_wait_for
+ void test_case_19()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< void > t( non_interrupt_fn, 3);
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.interrupt_and_wait_for( pt::seconds( 1) ) );
+ }
+
+ // check interrupt_and_wait_until
+ void test_case_20()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 3) );
+ bool finished( false);
+ tsk::task< void > t(
+ interrupt_fn,
+ pt::seconds( 1),
+ boost::ref( finished) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.interrupt_and_wait_until( boost::get_system_time() + pt::seconds( 3) ) );
+ BOOST_CHECK( finished);
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( h.has_exception() );
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_and_wait_until
+ void test_case_21()
+ {
+ tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< void > t( non_interrupt_fn, 3);
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.interrupt_and_wait_until( boost::get_system_time() + pt::seconds( 1) ) );
+ }
+
+ // check fifo scheduling
+ void test_case_22()
+ {
+ typedef tsk::static_pool<
+ tsk::unbounded_onelock_fifo
+ > pool_type;
+ BOOST_CHECK( ! tsk::has_attribute< pool_type >::value);
+ pool_type pool( tsk::poolsize( 1) );
+ boost::barrier b( 2);
+ std::vector< int > buffer;
+ tsk::task< void > t1( barrier_fn, boost::ref( b) );
+ tsk::task< void > t2(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10);
+ tsk::task< void > t3(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0);
+ tsk::async( boost::move( t1), pool);
+ boost::this_thread::sleep( pt::millisec( 250) );
+ tsk::async( boost::move( t2), pool);
+ tsk::async( boost::move( t3), pool);
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 55);
+ BOOST_CHECK_EQUAL( buffer[1], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
+ }
+
+ // check priority scheduling
+ void test_case_23()
+ {
+ typedef tsk::static_pool<
+ tsk::unbounded_onelock_prio_queue< int >
+ > pool_type;
+ BOOST_CHECK( tsk::has_attribute< pool_type >::value);
+ typedef boost::is_same< tsk::attribute_type< pool_type >::type, int > type;
+ BOOST_CHECK( type::value);
+ pool_type pool( tsk::poolsize( 1) );
+ boost::barrier b( 2);
+ std::vector< int > buffer;
+ tsk::task< void > t1( barrier_fn, boost::ref( b) );
+ tsk::task< void > t2(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10) ;
+ tsk::task< void > t3(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0);
+ tsk::async( boost::move( t1), 0, pool);
+ boost::this_thread::sleep( pt::millisec( 250) );
+ tsk::async( boost::move( t2), 1, pool);
+ tsk::async( boost::move( t3), 0, pool);
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 55);
+ BOOST_CHECK_EQUAL( buffer[1], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
+ }
+
+ // check smart scheduling
+ void test_case_24()
+ {
+ typedef tsk::static_pool<
+ tsk::unbounded_onelock_smart_queue< int, std::less< int > >
+ > pool_type;
+ BOOST_CHECK( tsk::has_attribute< pool_type >::value);
+ typedef boost::is_same< tsk::attribute_type< pool_type >::type, int > type;
+ BOOST_CHECK( type::value);
+ pool_type pool( tsk::poolsize( 1) );
+ boost::barrier b( 2);
+ std::vector< int > buffer;
+ tsk::task< void > t1( barrier_fn, boost::ref( b) );
+ tsk::task< void > t2(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10);
+ tsk::task< void > t3(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0);
+ tsk::task< void > t4(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 1);
+ pool.submit( boost::move( t1), 0);
+ boost::this_thread::sleep( pt::millisec( 250) );
+ tsk::async( boost::move( t2), 2, pool);
+ tsk::async( boost::move( t3), 1, pool);
+ tsk::async( boost::move( t4), 2, pool);
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer[1], 1);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
+ }
+};
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test( BOOST_TEST_SUITE("Boost.Task: test suite") );
+
+ boost::shared_ptr< test_unbounded_onelock_pool > instance( new test_unbounded_onelock_pool() );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_3, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_5, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_6, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_7, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_8, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_9, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_10, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_11, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_12, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_13, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_14, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_15, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_16, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_17, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_18, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_19, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_20, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_21, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_22, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_23, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_onelock_pool::test_case_24, instance) );
+
+ return test;
+}
Deleted: sandbox/task/libs/task/test/test_unbounded_pool.cpp
==============================================================================
--- sandbox/task/libs/task/test/test_unbounded_pool.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
+++ (empty file)
@@ -1,553 +0,0 @@
-
-// Copyright Oliver Kowalke 2009.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#include <cstdlib>
-#include <iostream>
-#include <map>
-#include <stdexcept>
-#include <vector>
-
-#include <boost/bind.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/function.hpp>
-#include <boost/ref.hpp>
-#include <boost/test/unit_test.hpp>
-#include <boost/thread.hpp>
-#include <boost/thread/barrier.hpp>
-#include <boost/type_traits/is_same.hpp>
-#include <boost/utility.hpp>
-
-#include <boost/task.hpp>
-
-#include "test_functions.hpp"
-
-namespace pt = boost::posix_time;
-namespace tsk = boost::task;
-
-class test_unbounded_pool
-{
-public:
- // check size, active, idle
- void test_case_1()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool1( tsk::poolsize( 3) );
- BOOST_CHECK( pool1);
- BOOST_CHECK_EQUAL( pool1.size(), std::size_t( 3) );
- BOOST_CHECK_EQUAL( pool1.idle(), std::size_t( 3) );
- BOOST_CHECK_EQUAL( pool1.active(), std::size_t( 0) );
-
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool2;
- BOOST_CHECK( ! pool2);
- BOOST_CHECK_THROW( pool2.size(), tsk::pool_moved);
- BOOST_CHECK_THROW( pool2.idle(), tsk::pool_moved);
- BOOST_CHECK_THROW( pool2.active(), tsk::pool_moved);
-
- pool2 = boost::move( pool1);
-
- BOOST_CHECK( ! pool1);
- BOOST_CHECK_THROW( pool1.size(), tsk::pool_moved);
- BOOST_CHECK_THROW( pool1.idle(), tsk::pool_moved);
- BOOST_CHECK_THROW( pool1.active(), tsk::pool_moved);
-
- BOOST_CHECK( pool2);
- BOOST_CHECK_EQUAL( pool2.size(), std::size_t( 3) );
- BOOST_CHECK_EQUAL( pool2.idle(), std::size_t( 3) );
- BOOST_CHECK_EQUAL( pool2.active(), std::size_t( 0) );
-
- tsk::task< int > t( fibonacci_fn, 10);
- tsk::handle< int > h(
- tsk::async( boost::move( t), pool2) );
- BOOST_CHECK_EQUAL( h.get(), 55);
- }
-
- // check submit
- void test_case_2()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 3) );
- tsk::task< int > t( fibonacci_fn, 10);
- tsk::handle< int > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK_EQUAL( h.get(), 55);
- }
-
- // check assignment
- void test_case_3()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 3) );
- tsk::task< int > t( fibonacci_fn, 10);
- tsk::handle< int > h1;
- tsk::handle< int > h2(
- tsk::async( boost::move( t), pool) );
- h1 = h2;
- BOOST_CHECK_EQUAL( h1.get(), 55);
- BOOST_CHECK_EQUAL( h2.get(), 55);
- }
-
- // check swap
- void test_case_4()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 3) );
- tsk::task< int > t1( fibonacci_fn, 5);
- tsk::task< int > t2( fibonacci_fn, 10);
- tsk::handle< int > h1(
- tsk::async( boost::move( t1), pool) );
- tsk::handle< int > h2(
- tsk::async( boost::move( t2), pool) );
- BOOST_CHECK_EQUAL( h1.get(), 5);
- BOOST_CHECK_EQUAL( h2.get(), 55);
- BOOST_CHECK_NO_THROW( h1.swap( h2) );
- BOOST_CHECK_EQUAL( h1.get(), 55);
- BOOST_CHECK_EQUAL( h2.get(), 5);
- }
-
- // check runs in pool
- void test_case_5()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 1) );
- tsk::task< bool > t( runs_in_pool_fn);
- tsk::handle< bool > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK_EQUAL( h.get(), true);
- }
-
- // check shutdown
- void test_case_6()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 1) );
- tsk::task< int > t( fibonacci_fn, 10);
- tsk::handle< int > h(
- tsk::async( boost::move( t), pool) );
- pool.shutdown();
- BOOST_CHECK( pool.closed() );
- BOOST_CHECK_EQUAL( h.get(), 55);
- }
-
- // check runtime_error throw inside task
- void test_case_7()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 1) );
- tsk::task< void > t( throwing_fn);
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- pool.shutdown();
- BOOST_CHECK_THROW( h.get(), std::runtime_error);
- }
-
- // check shutdown with task_rejected exception
- void test_case_8()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 1) );
- tsk::task< int > t( fibonacci_fn, 10);
- pool.shutdown();
- BOOST_CHECK( pool.closed() );
- BOOST_CHECK_THROW(
- tsk::async( boost::move( t), pool),
- tsk::task_rejected);
- }
-
- // check shutdown_now with thread_interrupted exception
- void test_case_9()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 1) );
- tsk::task< void > t( delay_fn, pt::millisec( 500) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- boost::this_thread::sleep( pt::millisec( 250) );
- BOOST_CHECK_EQUAL( pool.size(), std::size_t( 1) );
- pool.shutdown_now();
- BOOST_CHECK( pool.closed() );
- BOOST_CHECK_EQUAL( pool.size(), std::size_t( 0) );
- BOOST_CHECK_EQUAL( pool.idle(), std::size_t( 0) );
- BOOST_CHECK_EQUAL( pool.active(), std::size_t( 0) );
- BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
- }
-
- // check pending
- void test_case_10()
- {
- typedef tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool_type;
- pool_type pool( tsk::poolsize( 1) );
- boost::barrier b( 2);
- tsk::task< void > t1( barrier_fn, boost::ref( b) );
- tsk::task< int > t2( fibonacci_fn, 10);
- tsk::task< int > t3( fibonacci_fn, 10);
- tsk::handle< void > h1(
- tsk::async( boost::move( t1), pool) );
- boost::this_thread::sleep( pt::millisec( 250) );
- BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
- tsk::handle< int > h2(
- tsk::async( boost::move( t2), pool) );
- boost::this_thread::sleep( pt::millisec(250) );
- BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 1) );
- tsk::handle< int > h3(
- tsk::async( boost::move( t3), pool) );
- boost::this_thread::sleep( pt::millisec(250) );
- BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 2) );
- b.wait();
- h1.get();
- BOOST_CHECK_EQUAL( h2.get(), 55);
- BOOST_CHECK_EQUAL( h3.get(), 55);
- BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
- }
-
- // check wait
- void test_case_11()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 3) );
- tsk::task< int > t( fibonacci_fn, 10);
- tsk::handle< int > h(
- tsk::async( boost::move( t), pool) );
- h.wait();
- BOOST_CHECK( h.is_ready() );
- BOOST_CHECK( h.has_value() );
- BOOST_CHECK( ! h.has_exception() );
- BOOST_CHECK_EQUAL( h.get(), 55);
- }
-
- // check wait_for
- void test_case_12()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 3) );
- tsk::task< void > t( delay_fn, pt::seconds( 1) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( h.wait_for( pt::seconds( 3) ) );
- BOOST_CHECK( h.is_ready() );
- BOOST_CHECK( h.has_value() );
- BOOST_CHECK( ! h.has_exception() );
- }
-
- // check wait_for
- void test_case_13()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 3) );
- tsk::task< void > t( delay_fn, pt::seconds( 3) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( ! h.wait_for( pt::seconds( 1) ) );
- BOOST_CHECK( ! h.is_ready() );
- BOOST_CHECK( ! h.has_value() );
- BOOST_CHECK( ! h.has_exception() );
- }
-
- // check wait_until
- void test_case_14()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 3) );
- tsk::task< void > t( delay_fn, pt::seconds( 1) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( h.wait_until( boost::get_system_time() + pt::seconds( 3) ) );
- BOOST_CHECK( h.is_ready() );
- BOOST_CHECK( h.has_value() );
- BOOST_CHECK( ! h.has_exception() );
- }
-
- // check wait_until
- void test_case_15()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 3) );
- tsk::task< void > t( delay_fn, pt::seconds( 3) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( ! h.wait_until( boost::get_system_time() + pt::seconds( 1) ) );
- BOOST_CHECK( ! h.is_ready() );
- BOOST_CHECK( ! h.has_value() );
- BOOST_CHECK( ! h.has_exception() );
- }
-
- // check interrupt
- void test_case_16()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 3) );
- tsk::task< void > t( delay_fn, pt::seconds( 3) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- h.interrupt();
- BOOST_CHECK( h.interruption_requested() );
- BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
- }
-
- // check interrupt_all_worker
- void test_case_17()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 5) );
- tsk::task< void > t1( delay_fn, pt::seconds( 3) );
- tsk::task< void > t2( delay_fn, pt::seconds( 3) );
- tsk::task< void > t3( delay_fn, pt::seconds( 3) );
- tsk::handle< void > h1(
- tsk::async( boost::move( t1), pool) );
- tsk::handle< void > h2(
- tsk::async( boost::move( t2), pool) );
- tsk::handle< void > h3(
- tsk::async( boost::move( t3), pool) );
- boost::this_thread::sleep( pt::millisec( 250) );
- pool.interrupt_all_worker();
- BOOST_CHECK( ! h1.interruption_requested() );
- BOOST_CHECK( ! h2.interruption_requested() );
- BOOST_CHECK( ! h3.interruption_requested() );
- BOOST_CHECK_THROW( h1.get(), tsk::task_interrupted);
- BOOST_CHECK_THROW( h2.get(), tsk::task_interrupted);
- BOOST_CHECK_THROW( h3.get(), tsk::task_interrupted);
- BOOST_CHECK_EQUAL( pool.size(), std::size_t( 5) );
- }
-
- // check interrupt_and_wait
- void test_case_18()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 3) );
- bool finished( false);
- tsk::task< void > t(
- interrupt_fn,
- pt::seconds( 1),
- boost::ref( finished) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- h.interrupt_and_wait();
- BOOST_CHECK( finished);
- BOOST_CHECK( h.is_ready() );
- BOOST_CHECK( ! h.has_value() );
- BOOST_CHECK( h.has_exception() );
- BOOST_CHECK( h.interruption_requested() );
- BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
- }
-
- // check interrupt_and_wait_for
- void test_case_19()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 3) );
- bool finished( false);
- tsk::task< void > t(
- interrupt_fn,
- pt::seconds( 1),
- boost::ref( finished) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( h.interrupt_and_wait_for( pt::seconds( 3) ) );
- BOOST_CHECK( finished);
- BOOST_CHECK( h.is_ready() );
- BOOST_CHECK( ! h.has_value() );
- BOOST_CHECK( h.has_exception() );
- BOOST_CHECK( h.interruption_requested() );
- BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
- }
-
- // check interrupt_and_wait_for
- void test_case_20()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 3) );
- tsk::task< void > t( non_interrupt_fn, 3);
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( ! h.interrupt_and_wait_for( pt::seconds( 1) ) );
- }
-
- // check interrupt_and_wait_until
- void test_case_21()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 3) );
- bool finished( false);
- tsk::task< void > t(
- interrupt_fn,
- pt::seconds( 1),
- boost::ref( finished) );
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( h.interrupt_and_wait_until( boost::get_system_time() + pt::seconds( 3) ) );
- BOOST_CHECK( finished);
- BOOST_CHECK( h.is_ready() );
- BOOST_CHECK( ! h.has_value() );
- BOOST_CHECK( h.has_exception() );
- BOOST_CHECK( h.interruption_requested() );
- BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
- }
-
- // check interrupt_and_wait_until
- void test_case_22()
- {
- tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool( tsk::poolsize( 3) );
- tsk::task< void > t( non_interrupt_fn, 3);
- tsk::handle< void > h(
- tsk::async( boost::move( t), pool) );
- BOOST_CHECK( ! h.interrupt_and_wait_until( boost::get_system_time() + pt::seconds( 1) ) );
- }
-
- // check fifo scheduling
- void test_case_23()
- {
- typedef tsk::static_pool<
- tsk::unbounded_channel< tsk::fifo >
- > pool_type;
- BOOST_CHECK( ! tsk::has_attribute< pool_type >::value);
- pool_type pool( tsk::poolsize( 1) );
- boost::barrier b( 2);
- std::vector< int > buffer;
- tsk::task< void > t1( barrier_fn, boost::ref( b) );
- tsk::task< void > t2(
- buffer_fibonacci_fn,
- boost::ref( buffer),
- 10);
- tsk::task< void > t3(
- buffer_fibonacci_fn,
- boost::ref( buffer),
- 0);
- tsk::async( boost::move( t1), pool);
- tsk::async( boost::move( t2), pool);
- tsk::async( boost::move( t3), pool);
- b.wait();
- pool.shutdown();
- BOOST_CHECK_EQUAL( buffer[0], 55);
- BOOST_CHECK_EQUAL( buffer[1], 0);
- BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
- }
-
- // check priority scheduling
- void test_case_24()
- {
- typedef tsk::static_pool<
- tsk::unbounded_channel< tsk::priority< int > >
- > pool_type;
- BOOST_CHECK( tsk::has_attribute< pool_type >::value);
- typedef boost::is_same< tsk::attribute_type< pool_type >::type, int > type;
- BOOST_CHECK( type::value);
- pool_type pool( tsk::poolsize( 1) );
- boost::barrier b( 2);
- std::vector< int > buffer;
- tsk::task< void > t1( barrier_fn, boost::ref( b) );
- tsk::task< void > t2(
- buffer_fibonacci_fn,
- boost::ref( buffer),
- 10) ;
- tsk::task< void > t3(
- buffer_fibonacci_fn,
- boost::ref( buffer),
- 0);
- tsk::async( boost::move( t1), 0, pool);
- tsk::async( boost::move( t2), 1, pool);
- tsk::async( boost::move( t3), 0, pool);
- b.wait();
- pool.shutdown();
- BOOST_CHECK_EQUAL( buffer[0], 55);
- BOOST_CHECK_EQUAL( buffer[1], 0);
- BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
- }
-
- // check smart scheduling
- void test_case_25()
- {
- typedef tsk::static_pool<
- tsk::unbounded_channel< tsk::smart< int, std::less< int >, tsk::replace_oldest, tsk::take_oldest > >
- > pool_type;
- BOOST_CHECK( tsk::has_attribute< pool_type >::value);
- typedef boost::is_same< tsk::attribute_type< pool_type >::type, int > type;
- BOOST_CHECK( type::value);
- pool_type pool( tsk::poolsize( 1) );
- boost::barrier b( 2);
- std::vector< int > buffer;
- tsk::task< void > t1( barrier_fn, boost::ref( b) );
- tsk::task< void > t2(
- buffer_fibonacci_fn,
- boost::ref( buffer),
- 10);
- tsk::task< void > t3(
- buffer_fibonacci_fn,
- boost::ref( buffer),
- 0);
- tsk::task< void > t4(
- buffer_fibonacci_fn,
- boost::ref( buffer),
- 1);
- pool.submit( boost::move( t1), 0);
- tsk::async( boost::move( t2), 2, pool);
- tsk::async( boost::move( t3), 1, pool);
- tsk::async( boost::move( t4), 2, pool);
- b.wait();
- pool.shutdown();
- BOOST_CHECK_EQUAL( buffer[0], 0);
- BOOST_CHECK_EQUAL( buffer[1], 1);
- BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
- }
-};
-
-boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
-{
- boost::unit_test::test_suite * test( BOOST_TEST_SUITE("Boost.Task: test suite") );
-
- boost::shared_ptr< test_unbounded_pool > instance( new test_unbounded_pool() );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_1, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_2, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_3, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_4, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_5, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_6, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_7, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_8, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_9, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_10, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_11, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_12, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_13, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_14, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_15, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_16, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_17, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_18, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_19, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_20, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_21, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_22, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_23, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_24, instance) );
- test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_pool::test_case_25, instance) );
-
- return test;
-}
Added: sandbox/task/libs/task/test/test_unbounded_twolock_pool.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/test/test_unbounded_twolock_pool.cpp 2009-09-19 15:06:44 EDT (Sat, 19 Sep 2009)
@@ -0,0 +1,444 @@
+
+// Copyright Oliver Kowalke 2009.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/function.hpp>
+#include <boost/ref.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/barrier.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/task.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tsk = boost::task;
+
+class test_unbounded_twolock_pool
+{
+public:
+ // check size and move op
+ void test_case_1()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool1( tsk::poolsize( 3) );
+ BOOST_CHECK( pool1);
+ BOOST_CHECK_EQUAL( pool1.size(), std::size_t( 3) );
+
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool2;
+ BOOST_CHECK( ! pool2);
+ BOOST_CHECK_THROW( pool2.size(), tsk::pool_moved);
+
+ pool2 = boost::move( pool1);
+
+ BOOST_CHECK( ! pool1);
+ BOOST_CHECK_THROW( pool1.size(), tsk::pool_moved);
+
+ BOOST_CHECK( pool2);
+ BOOST_CHECK_EQUAL( pool2.size(), std::size_t( 3) );
+
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool2) );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check submit
+ void test_case_2()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check assignment
+ void test_case_3()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h1;
+ tsk::handle< int > h2(
+ tsk::async( boost::move( t), pool) );
+ h1 = h2;
+ BOOST_CHECK_EQUAL( h1.get(), 55);
+ BOOST_CHECK_EQUAL( h2.get(), 55);
+ }
+
+ // check swap
+ void test_case_4()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< int > t1( fibonacci_fn, 5);
+ tsk::task< int > t2( fibonacci_fn, 10);
+ tsk::handle< int > h1(
+ tsk::async( boost::move( t1), pool) );
+ tsk::handle< int > h2(
+ tsk::async( boost::move( t2), pool) );
+ BOOST_CHECK_EQUAL( h1.get(), 5);
+ BOOST_CHECK_EQUAL( h2.get(), 55);
+ BOOST_CHECK_NO_THROW( h1.swap( h2) );
+ BOOST_CHECK_EQUAL( h1.get(), 55);
+ BOOST_CHECK_EQUAL( h2.get(), 5);
+ }
+
+ // check runs in pool
+ void test_case_5()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 1) );
+ tsk::task< bool > t( runs_in_pool_fn);
+ tsk::handle< bool > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK_EQUAL( h.get(), true);
+ }
+
+ // check shutdown
+ void test_case_6()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 1) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool) );
+ pool.shutdown();
+ BOOST_CHECK( pool.closed() );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check runtime_error throw inside task
+ void test_case_7()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 1) );
+ tsk::task< void > t( throwing_fn);
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ pool.shutdown();
+ BOOST_CHECK_THROW( h.get(), std::runtime_error);
+ }
+
+ // check shutdown with task_rejected exception
+ void test_case_8()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 1) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ pool.shutdown();
+ BOOST_CHECK( pool.closed() );
+ BOOST_CHECK_THROW(
+ tsk::async( boost::move( t), pool),
+ tsk::task_rejected);
+ }
+
+ // check shutdown_now with thread_interrupted exception
+ void test_case_9()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 1) );
+ tsk::task< void > t( delay_fn, pt::millisec( 500) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 1) );
+ pool.shutdown_now();
+ BOOST_CHECK( pool.closed() );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 0) );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check wait
+ void test_case_10()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< int > t( fibonacci_fn, 10);
+ tsk::handle< int > h(
+ tsk::async( boost::move( t), pool) );
+ h.wait();
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ BOOST_CHECK_EQUAL( h.get(), 55);
+ }
+
+ // check wait_for
+ void test_case_11()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< void > t( delay_fn, pt::seconds( 1) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.wait_for( pt::seconds( 3) ) );
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check wait_for
+ void test_case_12()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< void > t( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.wait_for( pt::seconds( 1) ) );
+ BOOST_CHECK( ! h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check wait_until
+ void test_case_13()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< void > t( delay_fn, pt::seconds( 1) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.wait_until( boost::get_system_time() + pt::seconds( 3) ) );
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check wait_until
+ void test_case_14()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< void > t( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.wait_until( boost::get_system_time() + pt::seconds( 1) ) );
+ BOOST_CHECK( ! h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( ! h.has_exception() );
+ }
+
+ // check interrupt
+ void test_case_15()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< void > t( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ h.interrupt();
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_all_worker
+ void test_case_16()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 5) );
+ tsk::task< void > t1( delay_fn, pt::seconds( 3) );
+ tsk::task< void > t2( delay_fn, pt::seconds( 3) );
+ tsk::task< void > t3( delay_fn, pt::seconds( 3) );
+ tsk::handle< void > h1(
+ tsk::async( boost::move( t1), pool) );
+ tsk::handle< void > h2(
+ tsk::async( boost::move( t2), pool) );
+ tsk::handle< void > h3(
+ tsk::async( boost::move( t3), pool) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ pool.interrupt_all_worker();
+ BOOST_CHECK( ! h1.interruption_requested() );
+ BOOST_CHECK( ! h2.interruption_requested() );
+ BOOST_CHECK( ! h3.interruption_requested() );
+ BOOST_CHECK_THROW( h1.get(), tsk::task_interrupted);
+ BOOST_CHECK_THROW( h2.get(), tsk::task_interrupted);
+ BOOST_CHECK_THROW( h3.get(), tsk::task_interrupted);
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 5) );
+ }
+
+ // check interrupt_and_wait
+ void test_case_17()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 3) );
+ bool finished( false);
+ tsk::task< void > t(
+ interrupt_fn,
+ pt::seconds( 1),
+ boost::ref( finished) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ h.interrupt_and_wait();
+ BOOST_CHECK( finished);
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( h.has_exception() );
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_and_wait_for
+ void test_case_18()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 3) );
+ bool finished( false);
+ tsk::task< void > t(
+ interrupt_fn,
+ pt::seconds( 1),
+ boost::ref( finished) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.interrupt_and_wait_for( pt::seconds( 3) ) );
+ BOOST_CHECK( finished);
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( h.has_exception() );
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_and_wait_for
+ void test_case_19()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< void > t( non_interrupt_fn, 3);
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.interrupt_and_wait_for( pt::seconds( 1) ) );
+ }
+
+ // check interrupt_and_wait_until
+ void test_case_20()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 3) );
+ bool finished( false);
+ tsk::task< void > t(
+ interrupt_fn,
+ pt::seconds( 1),
+ boost::ref( finished) );
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( h.interrupt_and_wait_until( boost::get_system_time() + pt::seconds( 3) ) );
+ BOOST_CHECK( finished);
+ BOOST_CHECK( h.is_ready() );
+ BOOST_CHECK( ! h.has_value() );
+ BOOST_CHECK( h.has_exception() );
+ BOOST_CHECK( h.interruption_requested() );
+ BOOST_CHECK_THROW( h.get(), tsk::task_interrupted);
+ }
+
+ // check interrupt_and_wait_until
+ void test_case_21()
+ {
+ tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool( tsk::poolsize( 3) );
+ tsk::task< void > t( non_interrupt_fn, 3);
+ tsk::handle< void > h(
+ tsk::async( boost::move( t), pool) );
+ BOOST_CHECK( ! h.interrupt_and_wait_until( boost::get_system_time() + pt::seconds( 1) ) );
+ }
+
+ // check fifo scheduling
+ void test_case_22()
+ {
+ typedef tsk::static_pool<
+ tsk::unbounded_twolock_fifo
+ > pool_type;
+ BOOST_CHECK( ! tsk::has_attribute< pool_type >::value);
+ pool_type pool( tsk::poolsize( 1) );
+ boost::barrier b( 2);
+ std::vector< int > buffer;
+ tsk::task< void > t1( barrier_fn, boost::ref( b) );
+ tsk::task< void > t2(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10);
+ tsk::task< void > t3(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0);
+ tsk::async( boost::move( t1), pool);
+ boost::this_thread::sleep( pt::millisec( 250) );
+ tsk::async( boost::move( t2), pool);
+ tsk::async( boost::move( t3), pool);
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 55);
+ BOOST_CHECK_EQUAL( buffer[1], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
+ }
+};
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test( BOOST_TEST_SUITE("Boost.Task: test suite") );
+
+ boost::shared_ptr< test_unbounded_twolock_pool > instance( new test_unbounded_twolock_pool() );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_3, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_5, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_6, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_7, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_8, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_9, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_10, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_11, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_12, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_13, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_14, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_15, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_16, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_17, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_18, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_19, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_20, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_21, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & test_unbounded_twolock_pool::test_case_22, 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