|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r52444 - in sandbox/task: boost boost/task boost/task/detail libs/task libs/task/src
From: oliver.kowalke_at_[hidden]
Date: 2009-04-17 12:10:33
Author: olli
Date: 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
New Revision: 52444
URL: http://svn.boost.org/trac/boost/changeset/52444
Log:
* sources from threadpool move to task
Added:
sandbox/task/boost/task/
sandbox/task/boost/task.hpp (contents, props changed)
sandbox/task/boost/task/bounded_channel.hpp (contents, props changed)
sandbox/task/boost/task/default_pool.hpp (contents, props changed)
sandbox/task/boost/task/detail/
sandbox/task/boost/task/detail/atomic.hpp (contents, props changed)
sandbox/task/boost/task/detail/bind_processor.hpp (contents, props changed)
sandbox/task/boost/task/detail/bind_processor_aix.hpp (contents, props changed)
sandbox/task/boost/task/detail/bind_processor_hpux.hpp (contents, props changed)
sandbox/task/boost/task/detail/bind_processor_linux.hpp (contents, props changed)
sandbox/task/boost/task/detail/bind_processor_solaris.hpp (contents, props changed)
sandbox/task/boost/task/detail/bind_processor_windows.hpp (contents, props changed)
sandbox/task/boost/task/detail/callable.hpp (contents, props changed)
sandbox/task/boost/task/detail/config.hpp (contents, props changed)
sandbox/task/boost/task/detail/guard.hpp (contents, props changed)
sandbox/task/boost/task/detail/info.hpp (contents, props changed)
sandbox/task/boost/task/detail/interrupter.hpp (contents, props changed)
sandbox/task/boost/task/detail/semaphore.hpp (contents, props changed)
sandbox/task/boost/task/detail/semaphore_posix.hpp (contents, props changed)
sandbox/task/boost/task/detail/semaphore_windows.hpp (contents, props changed)
sandbox/task/boost/task/detail/worker.hpp (contents, props changed)
sandbox/task/boost/task/detail/worker_group.hpp (contents, props changed)
sandbox/task/boost/task/detail/wsq.hpp (contents, props changed)
sandbox/task/boost/task/exceptions.hpp (contents, props changed)
sandbox/task/boost/task/fifo.hpp (contents, props changed)
sandbox/task/boost/task/future.hpp (contents, props changed)
sandbox/task/boost/task/info.hpp (contents, props changed)
sandbox/task/boost/task/launch.hpp (contents, props changed)
sandbox/task/boost/task/lifo.hpp (contents, props changed)
sandbox/task/boost/task/pool.hpp (contents, props changed)
sandbox/task/boost/task/poolsize.hpp (contents, props changed)
sandbox/task/boost/task/priority.hpp (contents, props changed)
sandbox/task/boost/task/scanns.hpp (contents, props changed)
sandbox/task/boost/task/smart.hpp (contents, props changed)
sandbox/task/boost/task/task.hpp (contents, props changed)
sandbox/task/boost/task/unbounded_channel.hpp (contents, props changed)
sandbox/task/boost/task/utility.hpp (contents, props changed)
sandbox/task/boost/task/watermark.hpp (contents, props changed)
sandbox/task/libs/task/
sandbox/task/libs/task/src/
sandbox/task/libs/task/src/callable.cpp (contents, props changed)
sandbox/task/libs/task/src/default_pool.cpp (contents, props changed)
sandbox/task/libs/task/src/guard.cpp (contents, props changed)
sandbox/task/libs/task/src/interrupter.cpp (contents, props changed)
sandbox/task/libs/task/src/poolsize.cpp (contents, props changed)
sandbox/task/libs/task/src/scanns.cpp (contents, props changed)
sandbox/task/libs/task/src/semaphore_posix.cpp (contents, props changed)
sandbox/task/libs/task/src/semaphore_windows.cpp (contents, props changed)
sandbox/task/libs/task/src/watermark.cpp (contents, props changed)
sandbox/task/libs/task/src/worker.cpp (contents, props changed)
sandbox/task/libs/task/src/worker_group.cpp (contents, props changed)
sandbox/task/libs/task/src/wsq.cpp (contents, props changed)
Added: sandbox/task/boost/task.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,26 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_H
+#define BOOST_TASK_H
+
+#include <boost/task/bounded_channel.hpp>
+#include <boost/task/default_pool.hpp>
+#include <boost/task/exceptions.hpp>
+#include <boost/task/fifo.hpp>
+#include <boost/task/info.hpp>
+#include <boost/task/launch.hpp>
+#include <boost/task/lifo.hpp>
+#include <boost/task/pool.hpp>
+#include <boost/task/poolsize.hpp>
+#include <boost/task/priority.hpp>
+#include <boost/task/scanns.hpp>
+#include <boost/task/smart.hpp>
+#include <boost/task/task.hpp>
+#include <boost/task/unbounded_channel.hpp>
+#include <boost/task/utility.hpp>
+#include <boost/task/watermark.hpp>
+
+#endif // BOOST_TASK_H
+
Added: sandbox/task/boost/task/bounded_channel.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/bounded_channel.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,389 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_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/detail/callable.hpp>
+#include <boost/task/exceptions.hpp>
+#include <boost/task/watermark.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< detail::callable > drain_()
+ {
+ BOOST_ASSERT( deactive_now_() );
+ std::vector< detail::callable > unprocessed;
+ unprocessed.reserve( queue_.size() );
+ BOOST_FOREACH( detail::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)
+ {
+ not_full_cond_.wait(
+ lk,
+ bind(
+ & bounded_channel::producers_activate_,
+ this) );
+ if ( ! active_() )
+ throw task_rejected("channel is not active");
+ queue_.push( itm);
+ not_empty_cond_.notify_one();
+ }
+
+ template< typename Duration >
+ void put_(
+ item const& itm,
+ Duration const& rel_time,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( ! not_full_cond_.timed_wait(
+ lk,
+ rel_time,
+ bind(
+ & bounded_channel::producers_activate_,
+ this) ) )
+ throw task_rejected("timed out");
+ if ( ! active_() )
+ throw task_rejected("channel is not active");
+ queue_.push( itm);
+ not_empty_cond_.notify_one();
+ }
+
+ bool take_(
+ detail::callable & ca,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ try
+ {
+ not_empty_cond_.wait(
+ lk,
+ bind(
+ & bounded_channel::consumers_activate_,
+ this) );
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ ca = queue_.pop();
+ if ( size_() <= lwm_)
+ {
+ if ( lwm_ == hwm_)
+ not_full_cond_.notify_one();
+ else
+ // more than one producer could be waiting
+ // for submiting an action object
+ not_full_cond_.notify_all();
+ }
+ return ! ca.empty();
+ }
+
+ template< typename Duration >
+ bool take_(
+ detail::callable & ca,
+ Duration const& rel_time,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ try
+ {
+ if ( ! not_empty_cond_.timed_wait(
+ lk,
+ rel_time,
+ bind(
+ & bounded_channel::consumers_activate_,
+ this) ) )
+ return false;
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ ca = queue_.pop();
+ 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_( detail::callable & ca)
+ {
+ if ( deactive_now_() || empty_() )
+ return false;
+ ca = queue_.pop();
+ 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 producers_activate_() const
+ { return ! active_() || ! full_(); }
+
+ bool consumers_activate_() const
+ { return ! active_() || ! empty_(); }
+
+public:
+ bounded_channel(
+ high_watermark const& hwm,
+ low_watermark const& lwm)
+ :
+ state_( channel_active),
+ queue_(),
+ mtx_(),
+ not_empty_cond_(),
+ not_full_cond_(),
+ hwm_( hwm),
+ lwm_( lwm)
+ {
+ if ( lwm_ > hwm_ )
+ throw invalid_watermark("low watermark must be less than or equal to high watermark");
+ }
+
+ bool active()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return active_();
+ }
+
+ void activate()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ activate_();
+ }
+
+ void clear()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ clear_();
+ }
+
+ bool deactive()
+ { return ! active(); }
+
+ void deactivate()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ deactivate_();
+ }
+
+ void deactivate_now()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ deactivate_now_();
+ }
+
+ const std::vector< detail::callable > drain()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return drain_();
+ }
+
+ bool empty()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return empty_();
+ }
+
+ bool full()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return full_();
+ }
+
+ std::size_t upper_bound()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return hwm_;
+ }
+
+ void upper_bound( std::size_t hwm)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ upper_bound_( hwm);
+ }
+
+ std::size_t lower_bound()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return lwm_;
+ }
+
+ void lower_bound( std::size_t lwm)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ lower_bound_( lwm);
+ }
+
+ std::size_t size()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return size_();
+ }
+
+ void put( item const& itm)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( itm, lk);
+ }
+
+ template< typename Duration >
+ void put(
+ item const& itm,
+ Duration const& rel_time)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( itm, rel_time, lk);
+ }
+
+ bool take( detail::callable & ca)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, lk);
+ }
+
+ template< typename Duration >
+ bool take(
+ detail::callable & ca,
+ Duration const& rel_time)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, rel_time, lk);
+ }
+
+ bool try_take( detail::callable & ca)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return try_take_( ca);
+ }
+};
+} }
+
+#endif // BOOST_TASK_BOUNDED_CHANNEL_H
Added: sandbox/task/boost/task/default_pool.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/default_pool.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,27 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DEFAULT_POOL_H
+#define BOOST_TASK_DEFAULT_POOL_H
+
+#include <boost/task/fifo.hpp>
+#include <boost/task/pool.hpp>
+#include <boost/task/unbounded_channel.hpp>
+
+namespace boost { namespace task
+{
+typedef pool< unbounded_channel< fifo > > default_pool;
+
+namespace detail
+{
+struct static_pool
+{ static default_pool instance; };
+}
+
+inline
+default_pool & get_default_pool()
+{ return detail::static_pool::instance; }
+} }
+
+#endif // BOOST_TASK_DEFAULT_POOL_H
Added: sandbox/task/boost/task/detail/atomic.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/atomic.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,141 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_ATOMIC_H
+#define BOOST_TASK_DETAIL_ATOMIC_H
+
+#include <boost/task/detail/config.hpp>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+# if defined( BOOST_WINDOWS_OS)
+
+#include <Windows.h>
+
+template< typename T >
+bool atomic_compare_exchange_ptr( volatile T * object, T expected, T desired)
+{ return InterlockedCompareExchangePointer( ( PVOID *) object, ( PVOID) expected, ( PVOID) desired); }
+
+inline
+void atomic_write_32( volatile unsigned int * object, unsigned int desired)
+{ InterlockedExchange( reinterpret_cast< volatile LONG * >( object), desired); }
+
+template< typename T >
+void atomic_write_ptr( volatile T * object, T desired)
+{ InterlockedExchangePointer( reinterpret_cast< volatile LONG * >( object), desired); }
+
+inline
+unsigned int atomic_inc_32( volatile unsigned int * object)
+{ return InterlockedIncrement( reinterpret_cast< volatile LONG * >( object) ); }
+
+inline
+unsigned int atomic_dec_32( volatile unsigned int * object)
+{ return InterlockedDecrement( reinterpret_cast< volatile LONG * >( object) ); }
+
+# elif defined(BOOST_AIX_OS)
+
+#include <sys/atomic_ops.h>
+
+template< typename T >
+bool atomic_compare_exchange_ptr( volatile T * object, T expected, T desired)
+{ return ::compare_and_swap( object, expected, & desired); }
+
+inline
+void atomic_write_32( volatile unsigned int * object, unsigned int desired)
+{ * object = desired; }
+
+template< typename T >
+void atomic_write_ptr( volatile T * object, T * desired)
+{ * object = desired; }
+
+inline
+unsigned int atomic_inc_32( volatile unsigned int * object)
+{ return ::fetch_and_add( object, 1); }
+
+inline
+unsigned int atomic_dec_32( volatile unsigned int * object)
+{ return ::fetch_and_add( object, -1); }
+
+# elif defined(BOOST_HPUX_OS)
+
+#include <atomic.h>
+
+template< typename T >
+bool atomic_compare_exchange_ptr( volatile T * object, T expected, T desired)
+{ return ::atomic_cas( object, expected, & desired) == object; }
+
+inline
+void atomic_write_32( volatile unsigned int * object, unsigned int desired)
+{ * object = desired; }
+
+template< typename T >
+void atomic_write_ptr( volatile T * object, T * desired)
+{ * object = desired; }
+
+inline
+unsigned int atomic_inc_32( volatile unsigned int * object)
+{ return ::atomic_inc( object); }
+
+inline
+unsigned int atomic_dec_32( volatile unsigned int * object)
+{ return ::atomic_dec( object); }
+
+# elif defined(BOOST_SOLARIS_OS)
+
+#include <atomic.h>
+
+template< typename T >
+bool atomic_compare_exchange_ptr( volatile T * object, T expected, T desired)
+{ return ::atomic_cas_ptr( object, expected, & desired) == object; }
+
+inline
+void atomic_write_32( volatile unsigned int * object, unsigned int desired)
+{
+ unsigned int desired_( desired);
+ ::atomic_swap_32( object, desired_);
+}
+
+template< typename T >
+void atomic_write_ptr( volatile T * object, T * desired)
+{ * object = desired; }
+
+inline
+unsigned int atomic_inc_32( volatile unsigned int * object)
+{ return ::atomic_inc_32( object); }
+
+inline
+unsigned int atomic_dec_32( volatile unsigned int * object)
+{ return ::atomic_dec_32( object); }
+
+#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
+
+template< typename T >
+bool atomic_compare_exchange_ptr( volatile T * object, T expected, T desired)
+{ return __sync_bool_compare_and_swap( object, expected, desired); }
+
+inline
+void atomic_write_32( volatile unsigned int * object, unsigned int desired)
+{ * object = desired; }
+
+template< typename T >
+void atomic_write_ptr( volatile T * object, T desired)
+{ * object = desired; }
+
+inline
+unsigned int atomic_inc_32( volatile unsigned int * object)
+{ return __sync_fetch_and_add( object, 1); }
+
+inline
+unsigned int atomic_dec_32( volatile unsigned int * object)
+{ return __sync_fetch_and_sub( object, 1); }
+
+# else
+# error "No atomic operations available for this platform!"
+# endif
+} } }
+
+#endif // BOOST_TASK_DETAIL_ATOMIC_H
+
Added: sandbox/task/boost/task/detail/bind_processor.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/bind_processor.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,28 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_BIND_PROCESSOR_H
+#define BOOST_TASK_DETAIL_BIND_PROCESSOR_H
+
+#include <boost/tp/detail/config.hpp>
+
+#define BOOST_THREAD_BIND_PROCESSOR_AFFINITY 1
+
+# if defined(BOOST_WINDOWS_OS)
+# include <boost/tp/detail/bind_processor_windows.hpp>
+# elif defined(BOOST_LINUX_OS)
+# include <boost/tp/detail/bind_processor_linux.hpp>
+//# elif defined(BOOST_xBSD_OS)
+//# include <boost/tp/detail/bind_processor_bsd.hpp>
+# elif defined(BOOST_AIX_OS)
+# include <boost/tp/detail/bind_processor_aix.hpp>
+# elif defined(BOOST_HPUX_OS)
+# include <boost/tp/detail/bind_processor_hpux.hpp>
+# elif defined(BOOST_SOLARIS_OS)
+# include <boost/tp/detail/bind_processor_solaris.hpp>
+# else
+# undef BOOST_THREAD_BIND_PROCESSOR_AFFINITY
+# endif
+
+#endif // BOOST_TASK_DETAIL_BIND_PROCESSOR_H
Added: sandbox/task/boost/task/detail/bind_processor_aix.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/bind_processor_aix.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,45 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_BIND_PROCESSOR_AIX_H
+#define BOOST_TASK_DETAIL_BIND_PROCESSOR_AIX_H
+
+extern "C"
+{
+#include <sys/processor.h>
+#include <sys/thread.h>
+}
+
+#include <boost/assert.hpp>
+#include <boost/thread.hpp>
+#include <boost/system/system_error.hpp>
+
+namespace boost { namespace this_thread
+{
+ inline
+ void bind_to_processor( unsigned int n)
+ {
+ BOOST_ASSERT( n >= 0);
+ BOOST_ASSERT( n < boost::thread::hardware_concurrency() );
+
+ if ( ::bindprocessor( BINDTHREAD, ::thread_self(), static_cast< cpu_t >( n) ) == -1)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno,
+ boost::system::system_category) );
+ }
+
+
+ inline
+ void bind_to_any_processor()
+ {
+ if ( ::bindprocessor( BINDTHREAD, ::thread_self(), PROCESSOR_CLASS_ANY) == -1)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno,
+ boost::system::system_category) );
+ }
+}}
+
+#endif // BOOST_TASK_DETAIL_BIND_PROCESSOR_AIX_H
Added: sandbox/task/boost/task/detail/bind_processor_hpux.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/bind_processor_hpux.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,57 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_BIND_PROCESSOR_HPUX_H
+#define BOOST_TASK_DETAIL_BIND_PROCESSOR_HPUX_H
+
+extern "C"
+{
+#include <sys/pthread.h>
+}
+
+#include <boost/assert.hpp>
+#include <boost/thread.hpp>
+#include <boost/system/system_error.hpp>
+
+namespace boost { namespace this_thread
+{
+ inline
+ void bind_to_processor( unsigned int n)
+ {
+ BOOST_ASSERT( n >= 0);
+ BOOST_ASSERT( n < boost::thread::hardware_concurrency() );
+
+ ::pthread_spu_t spu;
+ int errno_(
+ ::pthread_processor_bind_np(
+ PTHREAD_BIND_FORCED_NP,
+ & spu,
+ static_cast< pthread_spu_t >( n),
+ PTHREAD_SELFTID_NP) );
+ if ( errno_ != 0)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno_,
+ boost::system::system_category) );
+ }
+
+ inline
+ void bind_to_any_processor()
+ {
+ ::pthread_spu_t spu;
+ int errno_(
+ ::pthread_processor_bind_np(
+ PTHREAD_BIND_FORCED_NP,
+ & spu,
+ PTHREAD_SPUFLOAT_NP,
+ PTHREAD_SELFTID_NP) );
+ if ( errno_ != 0)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno_,
+ boost::system::system_category) );
+ }
+}}
+
+#endif // BOOST_TASK_DETAIL_BIND_PROCESSOR_HPUX_H
Added: sandbox/task/boost/task/detail/bind_processor_linux.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/bind_processor_linux.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,58 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_BIND_PRCESSOR_LINUX_H
+#define BOOST_TASK_DETAIL_BIND_PRCESSOR_LINUX_H
+
+extern "C"
+{
+#include <pthread.h>
+#include <sched.h>
+}
+
+#include <boost/assert.hpp>
+#include <boost/thread.hpp>
+#include <boost/system/system_error.hpp>
+
+namespace boost { namespace this_thread
+{
+ inline
+ void bind_to_processor( unsigned int n)
+ {
+ BOOST_ASSERT( n >= 0);
+ BOOST_ASSERT( n < CPU_SETSIZE);
+ BOOST_ASSERT( n < boost::thread::hardware_concurrency() );
+
+ cpu_set_t cpuset;
+ CPU_ZERO( & cpuset);
+ CPU_SET( n, & cpuset);
+
+ int errno_( ::pthread_setaffinity_np( ::pthread_self(), sizeof( cpuset), & cpuset) );
+ if ( errno_ != 0)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno_,
+ boost::system::system_category) );
+ }
+
+ inline
+ void bind_to_any_processor()
+ {
+ cpu_set_t cpuset;
+ CPU_ZERO( & cpuset);
+
+ unsigned int max( boost::thread::hardware_concurrency() );
+ for ( unsigned int i( 0); i < max; ++i)
+ CPU_SET( i, & cpuset);
+
+ int errno_( ::pthread_setaffinity_np( ::pthread_self(), sizeof( cpuset), & cpuset) );
+ if ( errno_ != 0)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno_,
+ boost::system::system_category) );
+ }
+}}
+
+#endif // BOOST_TASK_DETAIL_BIND_PRCESSOR_LINUX_H
Added: sandbox/task/boost/task/detail/bind_processor_solaris.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/bind_processor_solaris.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,45 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_BIND_PROCESSOR_SOLARIS_H
+#define BOOST_TASK_DETAIL_BIND_PROCESSOR_SOLARIS_H
+
+extern "C"
+{
+#include <sys/types.h>
+#include <sys/processor.h>
+#include <sys/procset.h>
+}
+
+#include <boost/assert.hpp>
+#include <boost/thread.hpp>
+#include <boost/system/system_error.hpp>
+
+namespace boost { namespace this_thread
+{
+ inline
+ void bind_to_processor( unsigned int n)
+ {
+ BOOST_ASSERT( n >= 0);
+ BOOST_ASSERT( n < boost::thread::hardware_concurrency() );
+
+ if ( ::processor_bind( P_LWPID, P_MYID, static_cast< processorid_t >( n), 0) == -1)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno,
+ boost::system::system_category) );
+ }
+
+ inline
+ void bind_to_any_processor()
+ {
+ if ( ::processor_bind( P_LWPID, P_MYID, PBIND_NONE, 0) == -1)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ errno,
+ boost::system::system_category) );
+ }
+}}
+
+#endif // BOOST_TASK_DETAIL_BIND_PROCESSOR_SOLARIS_H
Added: sandbox/task/boost/task/detail/bind_processor_windows.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/bind_processor_windows.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,47 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_BIND_PROCESSOR_WINDOWS_H
+#define BOOST_TASK_DETAIL_BIND_PROCESSOR_WINDOWS_H
+
+extern "C"
+{
+#include <windows.h>
+}
+
+#include <boost/assert.hpp>
+#include <boost/thread.hpp>
+#include <boost/system/system_error.hpp>
+
+namespace boost { namespace this_thread
+{
+ inline
+ void bind_to_processor( unsigned int n)
+ {
+ BOOST_ASSERT( n >= 0);
+ BOOST_ASSERT( n < boost::thread::hardware_concurrency() );
+
+ if ( ::SetThreadAffinityMask( ::GetCurrentThread(), ( DWORD_PTR)1 << n) == 0)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ ::GetLastError(),
+ boost::system::system_category) );
+ }
+
+ inline
+ void bind_to_any_processor()
+ {
+ DWORD_PTR ptr( 1);
+ for ( unsigned int i( 0); i < boost::thread::hardware_concurrency(); ++i)
+ ptr = ptr << i;
+
+ if ( ::SetThreadAffinityMask( ::GetCurrentThread(), ptr) == 0)
+ throw boost::system::system_error(
+ boost::system::error_code(
+ ::GetLastError(),
+ boost::system::system_category) );
+ }
+}}
+
+#endif // BOOST_TASK_DETAIL_BIND_PROCESSOR_WINDOWS_H
Added: sandbox/task/boost/task/detail/callable.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/callable.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,80 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_CALLABLE_H
+#define BOOST_TASK_DETAIL_CALLABLE_H
+
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/task/task.hpp>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+class callable
+{
+private:
+ struct impl
+ {
+ virtual ~impl() {}
+ virtual void run() = 0;
+ virtual void set( shared_ptr< thread > &) = 0;
+ virtual void reset() = 0;
+ };
+
+ template< typename R >
+ class impl_wrapper : public impl
+ {
+ private:
+ task< R > t_;
+
+ public:
+ impl_wrapper( task< R > const& t)
+ : t_( t)
+ {}
+
+ void run()
+ { t_(); }
+
+ void set( shared_ptr< thread > & thrd)
+ { t_.impl_->intr.set( thrd); }
+
+ void reset()
+ { t_.impl_->intr.reset(); }
+ };
+
+ shared_ptr< impl > impl_;
+
+public:
+ class scoped_lock : public noncopyable
+ {
+ private:
+ callable & ca_;
+
+ public:
+ scoped_lock( callable &, shared_ptr< thread > &);
+
+ ~scoped_lock();
+ };
+
+ callable();
+
+ template< typename R >
+ callable( task< R > const& t)
+ : impl_( new impl_wrapper< R >( t) )
+ {}
+
+ void operator()();
+
+ bool empty() const;
+
+ void clear();
+};
+} } }
+
+#endif // BOOST_TASK_DETAIL_CALLABLE_H
+
Added: sandbox/task/boost/task/detail/config.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/config.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,35 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_CONFIG_H
+#define BOOST_TASK_DETAIL_CONFIG_H
+
+#include <boost/config.hpp>
+
+# if defined(BOOST_WINDOWS_API) && defined(BOOST_POSIX_API)
+# error "Both BOOST_WINDOWS_API and BOOST_POSIX_API are defined!"
+# elif ! defined(BOOST_WINDOWS_API ) && ! defined(BOOST_POSIX_API)
+# if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)
+# define BOOST_WINDOWS_API
+# else
+# define BOOST_POSIX_API
+# endif
+# endif
+
+# if defined(BOOST_WINDOWS_API)
+# define BOOST_WINDOWS_OS
+# elif defined(linux) || defined(__linux) || defined(__linux__)
+# define BOOST_LINUX_OS
+# elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+# define BOOST_xBSD_OS
+# elif defined(__IBMCPP__) || defined(_AIX)
+# define BOOST_AIX_OS
+# elif defined(__hpux)
+# define BOOST_HPUX_OS
+# elif defined(sun) || defined(__sun)
+# define BOOST_SOLARIS_OS
+# endif
+
+#endif // BOOST_TASK_DETAIL_CONFIG_H
+
Added: sandbox/task/boost/task/detail/guard.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/guard.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,27 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_GUARD_H
+#define BOOST_TASK_DETAIL_GUARD_H
+
+#include <boost/utility.hpp>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+class guard : private noncopyable
+{
+private:
+ unsigned int & active_worker_;
+
+public:
+ guard( unsigned int & active_worker);
+
+ ~guard();
+};
+} } }
+
+#endif // BOOST_TASK_DETAIL_GUARD_H
+
Added: sandbox/task/boost/task/detail/info.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/info.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,20 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_INFO_H
+#define BOOST_TASK_DETAIL_INFO_H
+
+namespace boost { namespace task
+{
+namespace detail
+{
+struct has_priority
+{};
+
+struct has_no_priority
+{};
+} } }
+
+#endif // BOOST_TASK_DETAIL_INFO_H
+
Added: sandbox/task/boost/task/detail/interrupter.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/interrupter.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,83 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_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>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+class interrupter
+{
+private:
+ class impl : private noncopyable
+ {
+ private:
+ bool interruption_requested_;
+ condition_variable cond_;
+ mutex mtx_;
+ shared_ptr< thread > thrd_;
+
+ void interrupt_();
+
+ public:
+ impl();
+
+ void set( shared_ptr< thread > const& thrd);
+
+ void reset();
+
+ void interrupt();
+
+ void interrupt_and_wait();
+
+ void interrupt_and_wait( system_time const& abs_time);
+
+ template< typename DurationType >
+ void interrupt_and_wait( DurationType const& rel_time)
+ {
+ unique_lock< mutex > lk( mtx_);
+ interrupt_();
+ cond_.timed_wait( lk, rel_time);
+ }
+
+ bool interruption_requested();
+ };
+
+ shared_ptr< impl > impl_;
+
+public:
+ interrupter();
+
+ void set( shared_ptr< thread > const& thrd);
+
+ void reset();
+
+ void interrupt();
+
+ void interrupt_and_wait();
+
+ void interrupt_and_wait( system_time const& abs_time);
+
+ template< typename DurationType >
+ void interrupt_and_wait( DurationType const& rel_time)
+ { impl_->interrupt_and_wait( rel_time); }
+
+ bool interruption_requested();
+
+ void swap( interrupter & other)
+ { impl_.swap( other.impl_); }
+};
+}}}
+
+#endif // BOOST_TASK_DETAIL_INTERRUPTER_H
Added: sandbox/task/boost/task/detail/semaphore.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/semaphore.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,18 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_SEMAPHORE_H
+#define BOOST_TASK_DETAIL_SEMAPHORE_H
+
+#include <boost/task/detail/config.hpp>
+
+# if defined(BOOST_WINDOWS_API)
+# include <boost/task/detail/semaphore_windows.hpp>
+# elif defined(BOOST_POSIX_API)
+# include <boost/task/detail/semaphore_posix.hpp>
+# else
+# error "No semaphore available for this platform!"
+# endif
+
+#endif // BOOST_TASK_DETAIL_SEMAPHORE_H
Added: sandbox/task/boost/task/detail/semaphore_posix.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/semaphore_posix.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,38 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_SEMAPHORE_POSIX_H
+#define BOOST_TASK_DETAIL_SEMAPHORE_POSIX_H
+
+extern "C"
+{
+#include <semaphore.h>
+}
+
+#include <boost/utility.hpp>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+class semaphore : private boost::noncopyable
+{
+private:
+ sem_t sem_;
+
+public:
+ semaphore( int);
+
+ ~semaphore();
+
+ void post();
+
+ bool try_wait();
+ void wait();
+
+ int value();
+};
+}}}
+
+#endif // BOOST_TASK_DETAIL_SEMAPHORE_POSIX_H
Added: sandbox/task/boost/task/detail/semaphore_windows.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/semaphore_windows.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,38 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_SEMAPHORE_WINDOWS_H
+#define BOOST_TASK_DETAIL_SEMAPHORE_WINDOWS_H
+
+extern "C"
+{
+#include <Windows.h>
+}
+
+#include <boost/utility.hpp>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+class semaphore : private boost::noncopyable
+{
+private:
+ HANDLE handle_;
+
+public:
+ semaphore( int);
+
+ ~semaphore();
+
+ void post();
+
+ bool try_wait();
+ void wait();
+
+ int value();
+};
+}}}
+
+#endif // BOOST_TASK_DETAIL_SEMAPHORE_WINDOWS_H
Added: sandbox/task/boost/task/detail/worker.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/worker.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,296 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_WORKER_H
+#define BOOST_TASK_DETAIL_WORKER_H
+
+#include <cstddef>
+#include <utility>
+
+#include <boost/assert.hpp>
+#include <boost/function.hpp>
+#include <boost/random.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/task/detail/callable.hpp>
+#include <boost/task/detail/guard.hpp>
+#include <boost/task/detail/interrupter.hpp>
+#include <boost/task/detail/semaphore.hpp>
+#include <boost/task/detail/wsq.hpp>
+#include <boost/task/poolsize.hpp>
+#include <boost/task/scanns.hpp>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+class worker
+{
+private:
+ static thread_specific_ptr< worker > tss_;
+
+ struct impl
+ {
+ virtual ~impl() {}
+
+ virtual const thread::id get_id() const = 0;
+
+ virtual void join() const = 0;
+
+ virtual void interrupt() const = 0;
+
+ virtual void put( callable const&) = 0;
+
+ virtual bool try_take( callable &) = 0;
+
+ virtual bool try_steal( callable &) = 0;
+
+ virtual void signal_shutdown() = 0;
+
+ virtual void signal_shutdown_now() = 0;
+
+ virtual void schedule_until( function< bool() > const&) = 0;
+
+ virtual void run() = 0;
+ };
+
+ template< typename Pool >
+ class impl_pool : public impl,
+ private noncopyable
+ {
+ private:
+ class random_idx
+ {
+ private:
+ rand48 rng_;
+ uniform_int<> six_;
+ variate_generator< rand48 &, uniform_int<> > die_;
+
+ public:
+ random_idx( std::size_t size)
+ :
+ rng_(),
+ six_( 0, size - 1),
+ die_( rng_, six_)
+ {}
+
+ std::size_t operator()()
+ { return die_(); }
+ };
+
+ Pool & pool_;
+ shared_ptr< thread > thrd_;
+ wsq wsq_;
+ semaphore shtdwn_sem_;
+ semaphore shtdwn_now_sem_;
+ bool shtdwn_;
+ posix_time::time_duration asleep_;
+ scanns max_scns_;
+ std::size_t scns_;
+ random_idx rnd_idx_;
+
+ void execute_( callable & ca)
+ {
+ BOOST_ASSERT( ! ca.empty() );
+ guard grd( get_pool().active_worker_);
+ {
+ callable::scoped_lock lk( ca, thrd_);
+ ca();
+ }
+ ca.clear();
+ BOOST_ASSERT( ca.empty() );
+ }
+
+ void next_callable_( callable & ca)
+ {
+ if ( ! try_take( ca) )
+ {
+ if ( ! get_pool().channel_.try_take( ca) )
+ {
+ std::size_t idx( rnd_idx_() );
+ for ( std::size_t j( 0); j < get_pool().wg_.size(); ++j)
+ {
+ worker other( get_pool().wg_[idx]);
+ if ( this_thread::get_id() == other.get_id() ) continue;
+ if ( ++idx >= get_pool().wg_.size() ) idx = 0;
+ if ( other.try_steal( ca) ) break;
+ }
+
+ if ( ca.empty() )
+ {
+ guard grd( get_pool().idle_worker_);
+ if ( shutdown_() ) return;
+ ++scns_;
+ if ( scns_ >= max_scns_)
+ {
+ if ( get_pool().size_() == get_pool().idle_worker_)
+ get_pool().channel_.take( ca, asleep_);
+ else
+ this_thread::sleep( asleep_);
+ scns_ = 0;
+ }
+ else
+ this_thread::yield();
+ }
+ }
+ }
+ }
+
+ bool shutdown_()
+ {
+ if ( shutdown__() && get_pool().channel_.empty() )
+ return true;
+ else if ( shutdown_now__() )
+ return true;
+ return false;
+ }
+
+ bool shutdown__()
+ {
+ if ( ! shtdwn_)
+ shtdwn_ = shtdwn_sem_.try_wait();
+ return shtdwn_;
+ }
+
+ bool shutdown_now__()
+ { return shtdwn_now_sem_.try_wait(); }
+
+ public:
+ impl_pool(
+ Pool & pool,
+ poolsize const& psize,
+ posix_time::time_duration const& asleep,
+ scanns const& max_scns,
+ function< void() > const& fn)
+ :
+ pool_( pool),
+ thrd_( new thread( fn) ),
+ wsq_(),
+ shtdwn_sem_( 0),
+ shtdwn_now_sem_( 0),
+ shtdwn_( false),
+ asleep_( asleep),
+ max_scns_( max_scns),
+ scns_( 0),
+ rnd_idx_( psize)
+ { BOOST_ASSERT( ! fn.empty() ); }
+
+ const thread::id get_id() const
+ { return thrd_->get_id(); }
+
+ void join() const
+ { thrd_->join(); }
+
+ void
+ interrupt() const
+ { thrd_->interrupt(); }
+
+ void signal_shutdown()
+ { shtdwn_sem_.post(); }
+
+ void signal_shutdown_now()
+ { shtdwn_now_sem_.post(); }
+
+ void put( callable const& ca)
+ {
+ BOOST_ASSERT( ! ca.empty() );
+ wsq_.put( ca);
+ }
+
+ bool try_take( callable & ca)
+ {
+ callable tmp;
+ bool result( wsq_.try_take( tmp) );
+ if ( result)
+ ca = tmp;
+ return result;
+ }
+
+ bool try_steal( callable & ca)
+ {
+ callable tmp;
+ bool result( wsq_.try_steal( tmp) );
+ if ( result)
+ ca = tmp;
+ return result;
+ }
+
+ Pool & get_pool() const
+ { return pool_; }
+
+ void run()
+ {
+ BOOST_ASSERT( get_id() == this_thread::get_id() );
+
+ schedule_until(
+ bind( & impl_pool::shutdown_, this) );
+ }
+
+ void schedule_until( function< bool() > const& pred)
+ {
+ callable ca;
+ while ( ! pred() )
+ {
+ next_callable_( ca);
+ if( ! ca.empty() )
+ {
+ execute_( ca);
+ scns_ = 0;
+ }
+ }
+ }
+ };
+
+ shared_ptr< impl > impl_;
+
+public:
+ template< typename Pool >
+ worker(
+ Pool & pool,
+ poolsize const& psize,
+ posix_time::time_duration const& asleep,
+ scanns const& max_scns,
+ function< void() > const& fn)
+ :
+ impl_(
+ new impl_pool< Pool >(
+ pool,
+ psize,
+ asleep,
+ max_scns,
+ fn) )
+ {}
+
+ const thread::id get_id() const;
+
+ void join() const;
+ void interrupt() const;
+ void signal_shutdown();
+ void signal_shutdown_now();
+
+ void put( callable const&);
+ bool try_take( callable &);
+ bool try_steal( callable &);
+
+ void reschedule_until( function< bool() > const&);
+
+ template< typename Pool >
+ Pool & get_pool() const
+ {
+ impl_pool< Pool > * p( dynamic_cast< impl_pool< Pool > * >( impl_.get() ) );
+ BOOST_ASSERT( p);
+ return p->get_pool();
+ }
+
+ void run();
+
+ static worker * tss_get();
+};
+
+} } }
+
+#endif // BOOST_TASK_DETAIL_WORKER_H
+
Added: sandbox/task/boost/task/detail/worker_group.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/worker_group.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,83 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_WORKER_GROUP_H
+#define BOOST_TASK_DETAIL_WORKER_GROUP_H
+
+#include <cstddef>
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/mem_fun.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/random_access_index.hpp>
+#include <boost/thread.hpp>
+
+#include <boost/task/detail/worker.hpp>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+class worker_group
+{
+private:
+ struct id_idx_tag {};
+ struct rnd_idx_tag {};
+
+ typedef multi_index::multi_index_container<
+ worker,
+ multi_index::indexed_by<
+ multi_index::ordered_unique<
+ multi_index::tag< id_idx_tag >,
+ multi_index::const_mem_fun<
+ worker,
+ const thread::id,
+ & worker::get_id
+ >
+ >,
+ multi_index::random_access< multi_index::tag< rnd_idx_tag > >
+ >
+ > container;
+
+ typedef container::index< id_idx_tag >::type id_idx;
+ typedef container::index< rnd_idx_tag >::type rnd_idx;
+
+ container cont_;
+ id_idx & id_idx_;
+ rnd_idx & rnd_idx_;
+
+public:
+ typedef id_idx::iterator iterator;
+ typedef id_idx::const_iterator const_iterator;
+
+ worker_group();
+
+ const worker operator[]( std::size_t pos) const;
+
+ std::size_t size() const;
+
+ const iterator begin();
+
+ const const_iterator begin() const;
+
+ const iterator end();
+
+ const const_iterator end() const;
+
+ const const_iterator find( thread::id const& id) const;
+
+ void join_all();
+
+ void interrupt_all();
+
+ void insert( worker const& w);
+
+ void signal_shutdown_all();
+
+ void signal_shutdown_now_all();
+};
+} } }
+
+#endif // BOOST_TASK_DETAIL_WORKER_GROUP_H
+
Added: sandbox/task/boost/task/detail/wsq.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/detail/wsq.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,45 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_DETAIL_WSQ_H
+#define BOOST_TASK_DETAIL_WSQ_H
+
+#include <boost/shared_array.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/task/detail/callable.hpp>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+class wsq : private noncopyable
+{
+private:
+ const int initial_size_;
+ shared_array< callable > array_;
+ int capacity_;
+ int mask_;
+ volatile uint32_t head_idx_;
+ volatile uint32_t tail_idx_;
+ recursive_mutex mtx_;
+
+public:
+ wsq();
+
+ bool empty() const;
+
+ std::size_t size() const;
+
+ void put( callable const&);
+
+ bool try_take( callable &);
+
+ bool try_steal( callable &);
+};
+} } }
+
+#endif // BOOST_TASK_DETAIL_WSQ_H
+
Added: sandbox/task/boost/task/exceptions.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/exceptions.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,65 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_EXCEPTIONS_H
+#define BOOST_TASK_EXCEPTIONS_H
+
+#include <stdexcept>
+#include <string>
+
+namespace boost { namespace task
+{
+class invalid_poolsize : public std::invalid_argument
+{
+public:
+ invalid_poolsize()
+ : std::invalid_argument("core poolsize must be greater than zero")
+ {}
+};
+
+class invalid_scanns : public std::invalid_argument
+{
+public:
+ invalid_scanns()
+ : std::invalid_argument("scanns must be greater than or equal to zero")
+ {}
+};
+
+class invalid_timeduration : public std::invalid_argument
+{
+public:
+ invalid_timeduration()
+ : std::invalid_argument("argument asleep is not valid")
+ {}
+};
+
+class invalid_watermark : public std::invalid_argument
+{
+public:
+ invalid_watermark( std::string const& msg)
+ : std::invalid_argument( msg)
+ {}
+};
+
+class task_already_executed : public std::logic_error
+{
+public:
+ task_already_executed()
+ : std::logic_error("task already executed")
+ {}
+};
+
+struct task_interrupted
+{};
+
+class task_rejected : public std::runtime_error
+{
+public:
+ task_rejected( std::string const& msg)
+ : std::runtime_error( msg)
+ {}
+};
+} }
+
+#endif // BOOST_TASK_EXCEPTIONS_H
Added: sandbox/task/boost/task/fifo.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/fifo.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,65 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_FIFO_H
+#define BOOST_TASK_FIFO_H
+
+#include <cstddef>
+#include <list>
+
+#include <boost/task/detail/callable.hpp>
+#include <boost/task/detail/info.hpp>
+
+namespace boost { namespace task
+{
+struct fifo
+{
+ typedef detail::has_no_priority priority_tag_type;
+
+ class impl
+ {
+ public:
+ typedef detail::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); }
+
+ const item pop()
+ {
+ item itm( lst_.front() );
+ lst_.pop_front();
+ return itm;
+ }
+
+ std::size_t size() const
+ { return lst_.size(); }
+
+ bool empty() const
+ { return lst_.empty(); }
+
+ void clear()
+ { lst_.clear(); }
+
+ const iterator begin()
+ { return lst_.begin(); }
+
+ const const_iterator begin() const
+ { return lst_.begin(); }
+
+ const iterator end()
+ { return lst_.end(); }
+
+ const const_iterator end() const
+ { return lst_.end(); }
+ };
+};
+} }
+
+#endif // BOOST_TASK_FIFO_H
Added: sandbox/task/boost/task/future.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/future.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,1367 @@
+// (C) Copyright 2008 Anthony Williams
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_FUTURE_HPP
+#define BOOST_FUTURE_HPP
+#include <stdexcept>
+#include <boost/exception.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/exception_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/type_traits/is_fundamental.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/config.hpp>
+#include <algorithm>
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/ref.hpp>
+#include <boost/scoped_array.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <list>
+#include <boost/next_prior.hpp>
+
+namespace boost
+{
+ class future_uninitialized:
+ public std::logic_error
+ {
+ public:
+ future_uninitialized():
+ std::logic_error("Future Uninitialized")
+ {}
+ };
+ class broken_promise:
+ public std::logic_error
+ {
+ public:
+ broken_promise():
+ std::logic_error("Broken promise")
+ {}
+ };
+ class future_already_retrieved:
+ public std::logic_error
+ {
+ public:
+ future_already_retrieved():
+ std::logic_error("Future already retrieved")
+ {}
+ };
+ class promise_already_satisfied:
+ public std::logic_error
+ {
+ public:
+ promise_already_satisfied():
+ std::logic_error("Promise already satisfied")
+ {}
+ };
+
+ class task_already_started:
+ public std::logic_error
+ {
+ public:
+ task_already_started():
+ std::logic_error("Task already started")
+ {}
+ };
+
+ class task_moved:
+ public std::logic_error
+ {
+ public:
+ task_moved():
+ std::logic_error("Task moved")
+ {}
+ };
+
+ namespace future_state
+ {
+ enum state { uninitialized, waiting, ready, moved };
+ }
+
+ namespace detail
+ {
+ struct future_object_base
+ {
+ boost::exception_ptr exception;
+ bool done;
+ boost::mutex mutex;
+ boost::condition_variable waiters;
+ typedef std::list<boost::condition_variable_any*> waiter_list;
+ waiter_list external_waiters;
+ boost::function<void()> callback;
+
+ future_object_base():
+ done(false)
+ {}
+ virtual ~future_object_base()
+ {}
+
+ waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv)
+ {
+ boost::unique_lock<boost::mutex> lock(mutex);
+ do_callback(lock);
+ return external_waiters.insert(external_waiters.end(),&cv);
+ }
+
+ void remove_external_waiter(waiter_list::iterator it)
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+ external_waiters.erase(it);
+ }
+
+ void mark_finished_internal()
+ {
+ done=true;
+ waiters.notify_all();
+ for(waiter_list::const_iterator it=external_waiters.begin(),
+ end=external_waiters.end();it!=end;++it)
+ {
+ (*it)->notify_all();
+ }
+ }
+
+ struct relocker
+ {
+ boost::unique_lock<boost::mutex>& lock;
+
+ relocker(boost::unique_lock<boost::mutex>& lock_):
+ lock(lock_)
+ {
+ lock.unlock();
+ }
+ ~relocker()
+ {
+ lock.lock();
+ }
+ };
+
+ void do_callback(boost::unique_lock<boost::mutex>& lock)
+ {
+ if(callback && !done)
+ {
+ boost::function<void()> local_callback=callback;
+ relocker relock(lock);
+ local_callback();
+ }
+ }
+
+
+ void wait(bool rethrow=true)
+ {
+ boost::unique_lock<boost::mutex> lock(mutex);
+ do_callback(lock);
+ while(!done)
+ {
+ waiters.wait(lock);
+ }
+ if(rethrow && exception)
+ {
+ boost::rethrow_exception(exception);
+ }
+ }
+
+ bool timed_wait_until(boost::system_time const& target_time)
+ {
+ boost::unique_lock<boost::mutex> lock(mutex);
+ do_callback(lock);
+ while(!done)
+ {
+ bool const success=waiters.timed_wait(lock,target_time);
+ if(!success && !done)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void mark_exceptional_finish_internal(boost::exception_ptr const& e)
+ {
+ exception=e;
+ mark_finished_internal();
+ }
+ void mark_exceptional_finish()
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+ mark_exceptional_finish_internal(boost::current_exception());
+ }
+
+ bool has_value()
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+ return done && !exception;
+ }
+ bool has_exception()
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+ return done && exception;
+ }
+
+ template<typename F,typename U>
+ void set_wait_callback(F f,U* u)
+ {
+ callback=boost::bind(f,boost::ref(*u));
+ }
+
+ private:
+ future_object_base(future_object_base const&);
+ future_object_base& operator=(future_object_base const&);
+ };
+
+ template<typename T>
+ struct future_traits
+ {
+ typedef boost::scoped_ptr<T> storage_type;
+#ifdef BOOST_HAS_RVALUE_REFS
+ typedef T const& source_reference_type;
+ struct dummy;
+ typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,T&&>::type rvalue_source_type;
+ typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,T&&>::type move_dest_type;
+#else
+ typedef T& source_reference_type;
+ typedef typename boost::mpl::if_<boost::is_convertible<T&,boost::detail::thread_move_t<T> >,boost::detail::thread_move_t<T>,T const&>::type rvalue_source_type;
+ typedef typename boost::mpl::if_<boost::is_convertible<T&,boost::detail::thread_move_t<T> >,boost::detail::thread_move_t<T>,T>::type move_dest_type;
+#endif
+
+ static void init(storage_type& storage,source_reference_type t)
+ {
+ storage.reset(new T(t));
+ }
+
+ static void init(storage_type& storage,rvalue_source_type t)
+ {
+ storage.reset(new T(static_cast<rvalue_source_type>(t)));
+ }
+
+ static void cleanup(storage_type& storage)
+ {
+ storage.reset();
+ }
+ };
+
+ template<typename T>
+ struct future_traits<T&>
+ {
+ typedef T* storage_type;
+ typedef T& source_reference_type;
+ struct rvalue_source_type
+ {};
+ typedef T& move_dest_type;
+
+ static void init(storage_type& storage,T& t)
+ {
+ storage=&t;
+ }
+
+ static void cleanup(storage_type& storage)
+ {
+ storage=0;
+ }
+ };
+
+ template<>
+ struct future_traits<void>
+ {
+ typedef bool storage_type;
+ typedef void move_dest_type;
+
+ static void init(storage_type& storage)
+ {
+ storage=true;
+ }
+
+ static void cleanup(storage_type& storage)
+ {
+ storage=false;
+ }
+
+ };
+
+ template<typename T>
+ struct future_object:
+ detail::future_object_base
+ {
+ typedef typename future_traits<T>::storage_type storage_type;
+ typedef typename future_traits<T>::source_reference_type source_reference_type;
+ typedef typename future_traits<T>::rvalue_source_type rvalue_source_type;
+ typedef typename future_traits<T>::move_dest_type move_dest_type;
+
+ storage_type result;
+
+ future_object():
+ result(0)
+ {}
+
+ void mark_finished_with_result_internal(source_reference_type result_)
+ {
+ future_traits<T>::init(result,result_);
+ mark_finished_internal();
+ }
+ void mark_finished_with_result_internal(rvalue_source_type result_)
+ {
+ future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
+ mark_finished_internal();
+ }
+
+ void mark_finished_with_result(source_reference_type result_)
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+ mark_finished_with_result_internal(result_);
+ }
+ void mark_finished_with_result(rvalue_source_type result_)
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+ mark_finished_with_result_internal(result_);
+ }
+
+ move_dest_type get()
+ {
+ wait();
+ return *result;
+ }
+
+ future_state::state get_state()
+ {
+ boost::lock_guard<boost::mutex> guard(mutex);
+ if(!done)
+ {
+ return future_state::waiting;
+ }
+ else
+ {
+ return future_state::ready;
+ }
+ }
+
+ private:
+ future_object(future_object const&);
+ future_object& operator=(future_object const&);
+ };
+
+ template<>
+ struct future_object<void>:
+ detail::future_object_base
+ {
+ future_object()
+ {}
+
+ void mark_finished_with_result_internal()
+ {
+ mark_finished_internal();
+ }
+
+ void mark_finished_with_result()
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+ mark_finished_with_result_internal();
+ }
+
+ void get()
+ {
+ wait();
+ }
+
+ future_state::state get_state()
+ {
+ boost::lock_guard<boost::mutex> guard(mutex);
+ if(!done)
+ {
+ return future_state::waiting;
+ }
+ else
+ {
+ return future_state::ready;
+ }
+ }
+
+ private:
+ future_object(future_object const&);
+ future_object& operator=(future_object const&);
+ };
+
+ class future_waiter
+ {
+ struct registered_waiter
+ {
+ boost::shared_ptr<detail::future_object_base> future;
+ detail::future_object_base::waiter_list::iterator wait_iterator;
+ unsigned index;
+
+ registered_waiter(boost::shared_ptr<detail::future_object_base> const& future_,
+ detail::future_object_base::waiter_list::iterator wait_iterator_,
+ unsigned index_):
+ future(future_),wait_iterator(wait_iterator_),index(index_)
+ {}
+
+ };
+
+ struct all_futures_lock
+ {
+ unsigned count;
+ boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
+
+ all_futures_lock(std::vector<registered_waiter>& futures):
+ count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
+ {
+ for(unsigned i=0;i<count;++i)
+ {
+ locks[i]=boost::unique_lock<boost::mutex>(futures[i].future->mutex);
+ }
+ }
+
+ void lock()
+ {
+ boost::lock(locks.get(),locks.get()+count);
+ }
+
+ void unlock()
+ {
+ for(unsigned i=0;i<count;++i)
+ {
+ locks[i].unlock();
+ }
+ }
+ };
+
+ boost::condition_variable_any cv;
+ std::vector<registered_waiter> futures;
+ unsigned future_count;
+
+ public:
+ future_waiter():
+ future_count(0)
+ {}
+
+ template<typename F>
+ void add(F& f)
+ {
+ if(f.future)
+ {
+ futures.push_back(registered_waiter(f.future,f.future->register_external_waiter(cv),future_count));
+ }
+ ++future_count;
+ }
+
+ unsigned wait()
+ {
+ all_futures_lock lk(futures);
+ for(;;)
+ {
+ for(unsigned i=0;i<futures.size();++i)
+ {
+ if(futures[i].future->done)
+ {
+ return futures[i].index;
+ }
+ }
+ cv.wait(lk);
+ }
+ }
+
+ ~future_waiter()
+ {
+ for(unsigned i=0;i<futures.size();++i)
+ {
+ futures[i].future->remove_external_waiter(futures[i].wait_iterator);
+ }
+ }
+
+ };
+
+ }
+
+ template <typename R>
+ class unique_future;
+
+ template <typename R>
+ class shared_future;
+
+ template<typename T>
+ struct is_future_type
+ {
+ BOOST_STATIC_CONSTANT(bool, value=false);
+ };
+
+ template<typename T>
+ struct is_future_type<unique_future<T> >
+ {
+ BOOST_STATIC_CONSTANT(bool, value=true);
+ };
+
+ template<typename T>
+ struct is_future_type<shared_future<T> >
+ {
+ BOOST_STATIC_CONSTANT(bool, value=true);
+ };
+
+ template<typename Iterator>
+ typename boost::disable_if<is_future_type<Iterator>,void>::type wait_for_all(Iterator begin,Iterator end)
+ {
+ for(Iterator current=begin;current!=end;++current)
+ {
+ current->wait();
+ }
+ }
+
+ template<typename F1,typename F2>
+ typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1,F2& f2)
+ {
+ f1.wait();
+ f2.wait();
+ }
+
+ template<typename F1,typename F2,typename F3>
+ void wait_for_all(F1& f1,F2& f2,F3& f3)
+ {
+ f1.wait();
+ f2.wait();
+ f3.wait();
+ }
+
+ template<typename F1,typename F2,typename F3,typename F4>
+ void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4)
+ {
+ f1.wait();
+ f2.wait();
+ f3.wait();
+ f4.wait();
+ }
+
+ template<typename F1,typename F2,typename F3,typename F4,typename F5>
+ void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
+ {
+ f1.wait();
+ f2.wait();
+ f3.wait();
+ f4.wait();
+ f5.wait();
+ }
+
+ template<typename Iterator>
+ typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end)
+ {
+ detail::future_waiter waiter;
+ for(Iterator current=begin;current!=end;++current)
+ {
+ waiter.add(*current);
+ }
+ return boost::next(begin,waiter.wait());
+ }
+
+ template<typename F1,typename F2>
+ typename boost::enable_if<is_future_type<F1>,unsigned>::type wait_for_any(F1& f1,F2& f2)
+ {
+ detail::future_waiter waiter;
+ waiter.add(f1);
+ waiter.add(f2);
+ return waiter.wait();
+ }
+
+ template<typename F1,typename F2,typename F3>
+ unsigned wait_for_any(F1& f1,F2& f2,F3& f3)
+ {
+ detail::future_waiter waiter;
+ waiter.add(f1);
+ waiter.add(f2);
+ waiter.add(f3);
+ return waiter.wait();
+ }
+
+ template<typename F1,typename F2,typename F3,typename F4>
+ unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4)
+ {
+ detail::future_waiter waiter;
+ waiter.add(f1);
+ waiter.add(f2);
+ waiter.add(f3);
+ waiter.add(f4);
+ return waiter.wait();
+ }
+
+ template<typename F1,typename F2,typename F3,typename F4,typename F5>
+ unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
+ {
+ detail::future_waiter waiter;
+ waiter.add(f1);
+ waiter.add(f2);
+ waiter.add(f3);
+ waiter.add(f4);
+ waiter.add(f5);
+ return waiter.wait();
+ }
+
+ template <typename R>
+ class promise;
+
+ template <typename R>
+ class packaged_task;
+
+ template <typename R>
+ class unique_future
+ {
+ unique_future(unique_future & rhs);// = delete;
+ unique_future& operator=(unique_future& rhs);// = delete;
+
+ typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
+
+ future_ptr future;
+
+ friend class shared_future<R>;
+ friend class promise<R>;
+ friend class packaged_task<R>;
+ friend class detail::future_waiter;
+
+ typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
+
+ unique_future(future_ptr future_):
+ future(future_)
+ {}
+
+ public:
+ typedef future_state::state state;
+
+ unique_future()
+ {}
+
+ ~unique_future()
+ {}
+
+#ifdef BOOST_HAS_RVALUE_REFS
+ unique_future(unique_future && other)
+ {
+ future.swap(other.future);
+ }
+ unique_future& operator=(unique_future && other)
+ {
+ future=other.future;
+ other.future.reset();
+ return *this;
+ }
+#else
+ unique_future(boost::detail::thread_move_t<unique_future> other):
+ future(other->future)
+ {
+ other->future.reset();
+ }
+
+ unique_future& operator=(boost::detail::thread_move_t<unique_future> other)
+ {
+ future=other->future;
+ other->future.reset();
+ return *this;
+ }
+
+ operator boost::detail::thread_move_t<unique_future>()
+ {
+ return boost::detail::thread_move_t<unique_future>(*this);
+ }
+#endif
+
+ void swap(unique_future& other)
+ {
+ future.swap(other.future);
+ }
+
+ // retrieving the value
+ move_dest_type get()
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+
+ return future->get();
+ }
+
+ // functions to check state, and wait for ready
+ state get_state() const
+ {
+ if(!future)
+ {
+ return future_state::uninitialized;
+ }
+ return future->get_state();
+ }
+
+
+ bool is_ready() const
+ {
+ return get_state()==future_state::ready;
+ }
+
+ bool has_exception() const
+ {
+ return future && future->has_exception();
+ }
+
+ bool has_value() const
+ {
+ return future && future->has_value();
+ }
+
+ void wait() const
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+ future->wait(false);
+ }
+
+ template<typename Duration>
+ bool timed_wait(Duration const& rel_time) const
+ {
+ return timed_wait_until(boost::get_system_time()+rel_time);
+ }
+
+ bool timed_wait_until(boost::system_time const& abs_time) const
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+ return future->timed_wait_until(abs_time);
+ }
+
+ };
+
+ template <typename R>
+ class shared_future
+ {
+ typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
+
+ future_ptr future;
+
+// shared_future(const unique_future<R>& other);
+// shared_future& operator=(const unique_future<R>& other);
+
+ friend class detail::future_waiter;
+ friend class promise<R>;
+ friend class packaged_task<R>;
+
+ shared_future(future_ptr future_):
+ future(future_)
+ {}
+
+ public:
+ shared_future(shared_future const& other):
+ future(other.future)
+ {}
+
+ typedef future_state::state state;
+
+ shared_future()
+ {}
+
+ ~shared_future()
+ {}
+
+ shared_future& operator=(shared_future const& other)
+ {
+ future=other.future;
+ return *this;
+ }
+#ifdef BOOST_HAS_RVALUE_REFS
+ shared_future(shared_future && other)
+ {
+ future.swap(other.future);
+ }
+ shared_future(unique_future<R> && other)
+ {
+ future.swap(other.future);
+ }
+ shared_future& operator=(shared_future && other)
+ {
+ future.swap(other.future);
+ other.future.reset();
+ return *this;
+ }
+ shared_future& operator=(unique_future<R> && other)
+ {
+ future.swap(other.future);
+ other.future.reset();
+ return *this;
+ }
+#else
+ shared_future(boost::detail::thread_move_t<shared_future> other):
+ future(other->future)
+ {
+ other->future.reset();
+ }
+// shared_future(const unique_future<R> &) = delete;
+ shared_future(boost::detail::thread_move_t<unique_future<R> > other):
+ future(other->future)
+ {
+ other->future.reset();
+ }
+ shared_future& operator=(boost::detail::thread_move_t<shared_future> other)
+ {
+ future.swap(other->future);
+ other->future.reset();
+ return *this;
+ }
+ shared_future& operator=(boost::detail::thread_move_t<unique_future<R> > other)
+ {
+ future.swap(other->future);
+ other->future.reset();
+ return *this;
+ }
+
+ operator boost::detail::thread_move_t<shared_future>()
+ {
+ return boost::detail::thread_move_t<shared_future>(*this);
+ }
+
+#endif
+
+ void swap(shared_future& other)
+ {
+ future.swap(other.future);
+ }
+
+ // retrieving the value
+ R get()
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+
+ return future->get();
+ }
+
+ // functions to check state, and wait for ready
+ state get_state() const
+ {
+ if(!future)
+ {
+ return future_state::uninitialized;
+ }
+ return future->get_state();
+ }
+
+
+ bool is_ready() const
+ {
+ return get_state()==future_state::ready;
+ }
+
+ bool has_exception() const
+ {
+ return future && future->has_exception();
+ }
+
+ bool has_value() const
+ {
+ return future && future->has_value();
+ }
+
+ void wait() const
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+ future->wait(false);
+ }
+
+ template<typename Duration>
+ bool timed_wait(Duration const& rel_time) const
+ {
+ return timed_wait_until(boost::get_system_time()+rel_time);
+ }
+
+ bool timed_wait_until(boost::system_time const& abs_time) const
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+ return future->timed_wait_until(abs_time);
+ }
+
+ };
+
+ template <typename R>
+ class promise
+ {
+ typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
+
+ future_ptr future;
+ bool future_obtained;
+
+ promise(promise & rhs);// = delete;
+ promise & operator=(promise & rhs);// = delete;
+
+ void lazy_init()
+ {
+ if(!future)
+ {
+ future_obtained=false;
+ future.reset(new detail::future_object<R>);
+ }
+ }
+
+ public:
+// template <class Allocator> explicit promise(Allocator a);
+
+ promise():
+ future(),future_obtained(false)
+ {}
+
+ ~promise()
+ {
+ if(future)
+ {
+ boost::lock_guard<boost::mutex> lock(future->mutex);
+
+ if(!future->done)
+ {
+ future->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
+ }
+ }
+ }
+
+ // Assignment
+#ifdef BOOST_HAS_RVALUE_REFS
+ promise(promise && rhs):
+ future_obtained(rhs.future_obtained)
+ {
+ future.swap(rhs.future);
+ }
+ promise & operator=(promise&& rhs)
+ {
+ future.swap(rhs.future);
+ future_obtained=rhs.future_obtained;
+ rhs.future.reset();
+ return *this;
+ }
+#else
+ promise(boost::detail::thread_move_t<promise> rhs):
+ future(rhs->future),future_obtained(rhs->future_obtained)
+ {
+ rhs->future.reset();
+ }
+ promise & operator=(boost::detail::thread_move_t<promise> rhs)
+ {
+ future=rhs->future;
+ future_obtained=rhs->future_obtained;
+ rhs->future.reset();
+ return *this;
+ }
+
+ operator boost::detail::thread_move_t<promise>()
+ {
+ return boost::detail::thread_move_t<promise>(*this);
+ }
+#endif
+
+ void swap(promise& other)
+ {
+ future.swap(other.future);
+ std::swap(future_obtained,other.future_obtained);
+ }
+
+ // Result retrieval
+ unique_future<R> get_future()
+ {
+ lazy_init();
+ if(future_obtained)
+ {
+ throw future_already_retrieved();
+ }
+ future_obtained=true;
+ return unique_future<R>(future);
+ }
+
+ void set_value(typename detail::future_traits<R>::source_reference_type r)
+ {
+ lazy_init();
+ boost::lock_guard<boost::mutex> lock(future->mutex);
+ if(future->done)
+ {
+ throw promise_already_satisfied();
+ }
+ future->mark_finished_with_result_internal(r);
+ }
+
+// void set_value(R && r);
+ void set_value(typename detail::future_traits<R>::rvalue_source_type r)
+ {
+ lazy_init();
+ boost::lock_guard<boost::mutex> lock(future->mutex);
+ if(future->done)
+ {
+ throw promise_already_satisfied();
+ }
+ future->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r));
+ }
+
+ void set_exception(boost::exception_ptr p)
+ {
+ lazy_init();
+ boost::lock_guard<boost::mutex> lock(future->mutex);
+ if(future->done)
+ {
+ throw promise_already_satisfied();
+ }
+ future->mark_exceptional_finish_internal(p);
+ }
+
+ template<typename F>
+ void set_wait_callback(F f)
+ {
+ lazy_init();
+ future->set_wait_callback(f,this);
+ }
+
+ };
+
+ template <>
+ class promise<void>
+ {
+ typedef boost::shared_ptr<detail::future_object<void> > future_ptr;
+
+ future_ptr future;
+ bool future_obtained;
+
+ promise(promise & rhs);// = delete;
+ promise & operator=(promise & rhs);// = delete;
+
+ void lazy_init()
+ {
+ if(!future)
+ {
+ future_obtained=false;
+ future.reset(new detail::future_object<void>);
+ }
+ }
+ public:
+// template <class Allocator> explicit promise(Allocator a);
+
+ promise():
+ future(),future_obtained(false)
+ {}
+
+ ~promise()
+ {
+ if(future)
+ {
+ boost::lock_guard<boost::mutex> lock(future->mutex);
+
+ if(!future->done)
+ {
+ future->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
+ }
+ }
+ }
+
+ // Assignment
+#ifdef BOOST_HAS_RVALUE_REFS
+ promise(promise && rhs):
+ future_obtained(rhs.future_obtained)
+ {
+ future.swap(rhs.future);
+ }
+ promise & operator=(promise&& rhs)
+ {
+ future.swap(rhs.future);
+ future_obtained=rhs.future_obtained;
+ rhs.future.reset();
+ return *this;
+ }
+#else
+ promise(boost::detail::thread_move_t<promise> rhs):
+ future(rhs->future),future_obtained(rhs->future_obtained)
+ {
+ rhs->future.reset();
+ }
+ promise & operator=(boost::detail::thread_move_t<promise> rhs)
+ {
+ future=rhs->future;
+ future_obtained=rhs->future_obtained;
+ rhs->future.reset();
+ return *this;
+ }
+
+ operator boost::detail::thread_move_t<promise>()
+ {
+ return boost::detail::thread_move_t<promise>(*this);
+ }
+#endif
+
+ void swap(promise& other)
+ {
+ future.swap(other.future);
+ std::swap(future_obtained,other.future_obtained);
+ }
+
+ // Result retrieval
+ unique_future<void> get_future()
+ {
+ lazy_init();
+
+ if(future_obtained)
+ {
+ throw future_already_retrieved();
+ }
+ future_obtained=true;
+ return unique_future<void>(future);
+ }
+
+ void set_value()
+ {
+ lazy_init();
+ boost::lock_guard<boost::mutex> lock(future->mutex);
+ if(future->done)
+ {
+ throw promise_already_satisfied();
+ }
+ future->mark_finished_with_result_internal();
+ }
+
+ void set_exception(boost::exception_ptr p)
+ {
+ lazy_init();
+ boost::lock_guard<boost::mutex> lock(future->mutex);
+ if(future->done)
+ {
+ throw promise_already_satisfied();
+ }
+ future->mark_exceptional_finish_internal(p);
+ }
+
+ template<typename F>
+ void set_wait_callback(F f)
+ {
+ lazy_init();
+ future->set_wait_callback(f,this);
+ }
+
+ };
+
+ namespace detail
+ {
+ template<typename R>
+ struct task_base:
+ detail::future_object<R>
+ {
+ bool started;
+
+ task_base():
+ started(false)
+ {}
+
+ void run()
+ {
+ {
+ boost::lock_guard<boost::mutex> lk(this->mutex);
+ if(started)
+ {
+ throw task_already_started();
+ }
+ started=true;
+ }
+ do_run();
+ }
+
+ void owner_destroyed()
+ {
+ boost::lock_guard<boost::mutex> lk(this->mutex);
+ if(!started)
+ {
+ started=true;
+ this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()));
+ }
+ }
+
+
+ virtual void do_run()=0;
+ };
+
+
+ template<typename R,typename F>
+ struct task_object:
+ task_base<R>
+ {
+ F f;
+ task_object(F const& f_):
+ f(f_)
+ {}
+ task_object(boost::detail::thread_move_t<F> f_):
+ f(f_)
+ {}
+
+ void do_run()
+ {
+ try
+ {
+ this->mark_finished_with_result(f());
+ }
+ catch(...)
+ {
+ this->mark_exceptional_finish();
+ }
+ }
+ };
+
+ template<typename F>
+ struct task_object<void,F>:
+ task_base<void>
+ {
+ F f;
+ task_object(F const& f_):
+ f(f_)
+ {}
+ task_object(boost::detail::thread_move_t<F> f_):
+ f(f_)
+ {}
+
+ void do_run()
+ {
+ try
+ {
+ f();
+ this->mark_finished_with_result();
+ }
+ catch(...)
+ {
+ this->mark_exceptional_finish();
+ }
+ }
+ };
+
+ }
+
+
+ template<typename R>
+ class packaged_task
+ {
+ boost::shared_ptr<detail::task_base<R> > task;
+ bool future_obtained;
+
+ packaged_task(packaged_task&);// = delete;
+ packaged_task& operator=(packaged_task&);// = delete;
+
+ public:
+ packaged_task():
+ future_obtained(false)
+ {}
+
+ // construction and destruction
+ template <class F>
+ explicit packaged_task(F const& f):
+ task(new detail::task_object<R,F>(f)),future_obtained(false)
+ {}
+ explicit packaged_task(R(*f)()):
+ task(new detail::task_object<R,R(*)()>(f)),future_obtained(false)
+ {}
+
+ template <class F>
+ explicit packaged_task(boost::detail::thread_move_t<F> f):
+ task(new detail::task_object<R,F>(f)),future_obtained(false)
+ {}
+
+// template <class F, class Allocator>
+// explicit packaged_task(F const& f, Allocator a);
+// template <class F, class Allocator>
+// explicit packaged_task(F&& f, Allocator a);
+
+
+ ~packaged_task()
+ {
+ if(task)
+ {
+ task->owner_destroyed();
+ }
+ }
+
+ // assignment
+#ifdef BOOST_HAS_RVALUE_REFS
+ packaged_task(packaged_task&& other):
+ future_obtained(other.future_obtained)
+ {
+ task.swap(other.task);
+ other.future_obtained=false;
+ }
+ packaged_task& operator=(packaged_task&& other)
+ {
+ packaged_task temp(static_cast<packaged_task&&>(other));
+ swap(temp);
+ return *this;
+ }
+#else
+ packaged_task(boost::detail::thread_move_t<packaged_task> other):
+ future_obtained(other->future_obtained)
+ {
+ task.swap(other->task);
+ other->future_obtained=false;
+ }
+ packaged_task& operator=(boost::detail::thread_move_t<packaged_task> other)
+ {
+ packaged_task temp(other);
+ swap(temp);
+ return *this;
+ }
+ operator boost::detail::thread_move_t<packaged_task>()
+ {
+ return boost::detail::thread_move_t<packaged_task>(*this);
+ }
+#endif
+
+ void swap(packaged_task& other)
+ {
+ task.swap(other.task);
+ std::swap(future_obtained,other.future_obtained);
+ }
+
+ // result retrieval
+ unique_future<R> get_future()
+ {
+ if(!task)
+ {
+ throw task_moved();
+ }
+ else if(!future_obtained)
+ {
+ future_obtained=true;
+ return unique_future<R>(task);
+ }
+ else
+ {
+ throw future_already_retrieved();
+ }
+ }
+
+
+ // execution
+ void operator()()
+ {
+ if(!task)
+ {
+ throw task_moved();
+ }
+ task->run();
+ }
+
+ template<typename F>
+ void set_wait_callback(F f)
+ {
+ task->set_wait_callback(f,this);
+ }
+
+ };
+
+ template< typename T >
+ detail::thread_move_t< packaged_task< T > > move( packaged_task< T > & t)
+ { return detail::thread_move_t< packaged_task< T > >( t); }
+}
+
+#endif
Added: sandbox/task/boost/task/info.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/info.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,32 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_INFO_H
+#define BOOST_TASK_INFO_H
+
+#include <boost/mpl/bool.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/task/detail/info.hpp>
+
+namespace boost { namespace task
+{
+template< typename Pool >
+struct has_priority : public mpl::bool_<
+ is_same<
+ detail::has_priority,
+ typename Pool::scheduler_type::priority_tag_type
+ >::value
+ >
+{};
+
+template< typename Pool >
+struct priority_type
+{
+ typedef typename Pool::scheduler_type::attribute_type type;
+};
+} }
+
+#endif // BOOST_TASK_INFO_H
+
Added: sandbox/task/boost/task/launch.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/launch.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,59 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_LAUNCH_H
+#define BOOST_TASK_LAUNCH_H
+
+#include <boost/task/default_pool.hpp>
+#include <boost/task/pool.hpp>
+#include <boost/task/task.hpp>
+
+namespace boost { namespace task
+{
+template< typename R >
+void launch_in_pool( task< R > t)
+{ get_default_pool().submit( t); }
+
+template<
+ typename R,
+ typename Attr
+>
+void launch_in_pool(
+ task< R > t,
+ Attr const& attr)
+{ get_default_pool().submit( t, attr); }
+
+template<
+ typename Channel,
+ typename R
+>
+void launch_in_pool(
+ pool< Channel > & pool,
+ task< R > t)
+{ pool.submit( t); }
+
+template<
+ typename Channel,
+ typename R,
+ typename Attr
+>
+void launch_in_pool(
+ pool< Channel > & pool,
+ task< R > t,
+ Attr const& attr)
+{ pool.submit( t, attr); }
+
+template< typename R >
+void launch_in_thread( task< R > t)
+{
+ thread th( t);
+ th.join();
+}
+
+template< typename R >
+void launch_in_current( task< R > t)
+{ t(); }
+} }
+
+#endif // BOOST_TASK_LAUNCH_H
Added: sandbox/task/boost/task/lifo.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/lifo.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,65 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_LIFO_H
+#define BOOST_TASK_LIFO_H
+
+#include <cstddef>
+#include <list>
+
+#include <boost/task/detail/callable.hpp>
+#include <boost/task/detail/info.hpp>
+
+namespace boost { namespace task
+{
+struct lifo
+{
+ typedef detail::has_no_priority priority_tag_type;
+
+ class impl
+ {
+ public:
+ typedef detail::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_front( itm); }
+
+ const item pop()
+ {
+ item itm( lst_.front() );
+ lst_.pop_front();
+ return itm;
+ }
+
+ std::size_t size() const
+ { return lst_.size(); }
+
+ bool empty() const
+ { return lst_.empty(); }
+
+ void clear()
+ { lst_.clear(); }
+
+ const iterator begin()
+ { return lst_.begin(); }
+
+ const const_iterator begin() const
+ { return lst_.begin(); }
+
+ const iterator end()
+ { return lst_.end(); }
+
+ const const_iterator end() const
+ { return lst_.end(); }
+ };
+};
+} }
+
+#endif // BOOST_TASK_LIFO_H
Added: sandbox/task/boost/task/pool.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/pool.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,348 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_POOL_H
+#define BOOST_TASK_POOL_H
+
+#include <cstddef>
+#include <utility>
+#include <vector>
+
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/thread.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/task/detail/atomic.hpp>
+#include <boost/task/detail/callable.hpp>
+#ifdef BOOST_TASK_BIND_WORKER_TO_PROCESSOR
+#include <boost/task/detail/bind_processor.hpp>
+#endif
+#include <boost/task/detail/worker.hpp>
+#include <boost/task/detail/worker_group.hpp>
+#include <boost/task/exceptions.hpp>
+#include <boost/task/future.hpp>
+#include <boost/task/poolsize.hpp>
+#include <boost/task/scanns.hpp>
+#include <boost/task/task.hpp>
+#include <boost/task/watermark.hpp>
+
+namespace boost { namespace task
+{
+typedef detail::callable callable;
+
+template< typename Channel >
+class pool : private noncopyable
+{
+private:
+ friend class detail::worker;
+
+ typedef Channel channel;
+ typedef typename channel::item channel_item;
+
+ detail::worker_group wg_;
+ shared_mutex mtx_wg_;
+ unsigned int state_;
+ channel channel_;
+ unsigned int active_worker_;
+ unsigned int idle_worker_;
+
+ void worker_entry_()
+ {
+ shared_lock< shared_mutex > lk( mtx_wg_);
+ typename detail::worker_group::iterator i( wg_.find( this_thread::get_id() ) );
+ lk.unlock();
+ BOOST_ASSERT( i != wg_.end() );
+
+ detail::worker w( * i);
+ w.run();
+ }
+
+ void create_worker_(
+ poolsize const& psize,
+ posix_time::time_duration const& asleep,
+ scanns const& max_scns)
+ {
+ wg_.insert(
+ detail::worker(
+ * this,
+ psize,
+ asleep,
+ max_scns,
+ boost::bind(
+ & pool::worker_entry_,
+ this) ) );
+ }
+
+#ifdef BOOST_TASK_BIND_WORKER_TO_PROCESSOR
+ void worker_entry_( std::size_t n)
+ {
+ this_thread::bind_to_processor( n);
+ worker_entry_();
+ }
+
+ void create_worker_(
+ poolsize const& psize,
+ posix_time::time_duration const& asleep,
+ scanns const& max_scns,
+ std::size_t n)
+ {
+ wg_.insert(
+ detail::worker(
+ * this,
+ psize,
+ asleep,
+ max_scns,
+ boost::bind(
+ & pool::worker_entry_,
+ this,
+ n) ) );
+ }
+#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(); }
+
+ bool closed_() const
+ { return state_ > 0; }
+
+ unsigned int close_()
+ { return detail::atomic_inc_32( & state_); }
+
+public:
+ explicit pool(
+ poolsize const& psize,
+ posix_time::time_duration const& asleep = posix_time::microseconds( 10),
+ scanns const& max_scns = scanns( 20) )
+ :
+ wg_(),
+ mtx_wg_(),
+ state_( 0),
+ channel_(),
+ active_worker_( 0),
+ idle_worker_( 0)
+ {
+ if ( asleep.is_special() || asleep.is_negative() )
+ throw invalid_timeduration();
+ channel_.activate();
+ unique_lock< shared_mutex > lk( mtx_wg_);
+ for ( std::size_t i( 0); i < psize; ++i)
+ create_worker_( psize, asleep, max_scns);
+ lk.unlock();
+ }
+
+ explicit pool(
+ poolsize const& psize,
+ high_watermark const& hwm,
+ low_watermark const& lwm,
+ posix_time::time_duration const& asleep = posix_time::microseconds( 100),
+ scanns const& max_scns = scanns( 20) )
+ :
+ wg_(),
+ mtx_wg_(),
+ state_( 0),
+ channel_(
+ hwm,
+ lwm),
+ active_worker_( 0),
+ idle_worker_( 0)
+ {
+ if ( asleep.is_special() || asleep.is_negative() )
+ throw invalid_timeduration();
+ channel_.activate();
+ unique_lock< shared_mutex > lk( mtx_wg_);
+ for ( std::size_t i( 0); i < psize; ++i)
+ create_worker_( psize, asleep, max_scns);
+ lk.unlock();
+ }
+
+#ifdef BOOST_TASK_BIND_WORKER_TO_PROCESSOR
+ explicit pool(
+ posix_time::time_duration const& asleep = posix_time::microseconds( 10),
+ scanns const& max_scns = scanns( 20) )
+ :
+ wg_(),
+ mtx_wg_(),
+ state_( 0),
+ channel_(),
+ 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();
+ unique_lock< shared_mutex > lk( mtx_wg_);
+ for ( std::size_t i( 0); i < psize; ++i)
+ create_worker_( psize, asleep, max_scns, i);
+ lk.unlock();
+ }
+
+ explicit pool(
+ high_watermark const& hwm,
+ low_watermark const& lwm,
+ posix_time::time_duration const& asleep = posix_time::microseconds( 100),
+ scanns const& max_scns = scanns( 20) )
+ :
+ wg_(),
+ mtx_wg_(),
+ state_( 0),
+ channel_(
+ 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();
+ unique_lock< shared_mutex > lk( mtx_wg_);
+ for ( std::size_t i( 0); i < psize; ++i)
+ create_worker_( psize, asleep, max_scns, i);
+ lk.unlock();
+ }
+#endif
+
+ ~pool()
+ { 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 shutdown()
+ {
+ if ( closed_() || close_() > 1) return;
+
+ channel_.deactivate();
+ shared_lock< shared_mutex > lk( mtx_wg_);
+ wg_.signal_shutdown_all();
+ wg_.join_all();
+ lk.unlock();
+ }
+
+ const std::vector< callable > shutdown_now()
+ {
+ if ( closed_() || close_() > 1)
+ return std::vector< callable >();
+
+ channel_.deactivate_now();
+ shared_lock< shared_mutex > lk( mtx_wg_);
+ wg_.signal_shutdown_now_all();
+ wg_.interrupt_all();
+ wg_.join_all();
+ lk.unlock();
+ std::vector< callable > drain( channel_.drain() );
+
+ return drain;
+ }
+
+ std::size_t size()
+ {
+ shared_lock< shared_mutex > lk( mtx_wg_);
+ return size_();
+ }
+
+ 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(); }
+
+ void upper_bound( high_watermark const& hwm)
+ { return channel_.upper_bound( hwm); }
+
+ std::size_t lower_bound()
+ { return channel_.lower_bound(); }
+
+ void lower_bound( low_watermark const lwm)
+ { return channel_.lower_bound( lwm); }
+
+ template< typename R >
+ void submit( task< R > t)
+ {
+ detail::worker * w( detail::worker::tss_get() );
+ if ( w)
+ {
+ function< bool() > wcb(
+ bind(
+ & shared_future< R >::is_ready,
+ t.impl_->fut) );
+ t.set_wait_callback(
+ bind(
+ ( void ( detail::worker::*)( function< bool() > const&) ) & detail::worker::reschedule_until,
+ w,
+ wcb) );
+ w->put( detail::callable( t) );
+ }
+ else
+ {
+ if ( closed_() )
+ throw task_rejected("pool is closed");
+
+ channel_.put( detail::callable( t) );
+ }
+ }
+
+ template<
+ typename R,
+ typename Attr
+ >
+ void submit( task< R > t, Attr const& attr)
+ {
+ detail::worker * w( detail::worker::tss_get() );
+ if ( w)
+ {
+ function< bool() > wcb(
+ bind(
+ & shared_future< R >::is_ready,
+ t.impl_->fut) );
+ t.set_wait_callback(
+ bind(
+ ( void ( detail::worker::*)( function< bool() > const&) ) & detail::worker::reschedule_until,
+ w,
+ wcb) );
+ w->put( detail::callable( t) );
+ }
+ else
+ {
+ if ( closed_() )
+ throw task_rejected("pool is closed");
+
+ channel_.put( channel_item( detail::callable( t), attr) );
+ }
+ }
+};
+}}
+
+#endif // BOOST_TASK_POOL_H
+
Added: sandbox/task/boost/task/poolsize.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/poolsize.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,24 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_POOLSIZE_H
+#define BOOST_TASK_POOLSIZE_H
+
+#include <cstddef>
+
+namespace boost { namespace task
+{
+class poolsize
+{
+private:
+ std::size_t value_;
+
+public:
+ explicit poolsize( std::size_t value);
+
+ operator std::size_t () const;
+};
+} }
+
+#endif // BOOST_TASK_POOLSIZE_H
Added: sandbox/task/boost/task/priority.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/priority.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,122 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_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/mem_fun.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+
+#include <boost/task/detail/callable.hpp>
+#include <boost/task/detail/info.hpp>
+
+namespace boost { namespace task
+{
+template<
+ typename Attr,
+ typename Ord = std::less< Attr >
+>
+struct priority
+{
+ typedef detail::has_priority priority_tag_type;
+ typedef Attr attribute_type;
+
+ class impl
+ {
+ private:
+ typedef Attr attribute;
+ typedef Ord ordering;
+
+ public:
+ class item
+ {
+ private:
+ detail::callable ca_;
+ attribute attr_;
+
+ public:
+ item(
+ detail::callable const& ca,
+ attribute const& attr)
+ : ca_( ca), attr_( attr)
+ { BOOST_ASSERT( ! ca_.empty() ); }
+
+ const detail::callable ca() const
+ { return ca_; }
+
+ const attribute attr() const
+ { return attr_; }
+ };
+
+ private:
+ typedef multi_index::multi_index_container<
+ item,
+ multi_index::indexed_by<
+ multi_index::ordered_non_unique<
+ multi_index::const_mem_fun<
+ item,
+ const attribute,
+ & item::attr
+ >,
+ ordering
+ >
+ >
+ > list;
+ typedef typename list::template nth_index< 0 >::type index;
+
+ list lst_;
+ index & idx_;
+
+ public:
+ typedef typename list::iterator iterator;
+ typedef typename list::const_iterator const_iterator;
+
+ impl()
+ :
+ lst_(),
+ idx_( lst_.get< 0 >() )
+ {}
+
+ void push( item const& itm)
+ { idx_.insert( itm); }
+
+ const detail::callable pop()
+ {
+ iterator i( lst_.begin() );
+ BOOST_ASSERT( i != lst_.end() );
+ item itm( * i);
+ lst_.erase( i);
+ return 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(); }
+ };
+};
+} }
+
+#endif // BOOST_TASK_PRIORITY_H
Added: sandbox/task/boost/task/scanns.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/scanns.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,24 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_SCANNS_H
+#define BOOST_TASK_SCANNS_H
+
+#include <cstddef>
+
+namespace boost { namespace task
+{
+class scanns
+{
+private:
+ std::size_t value_;
+
+public:
+ explicit scanns( std::size_t value);
+
+ operator std::size_t () const;
+};
+} }
+
+#endif // BOOST_TASK_SCANNS_H
Added: sandbox/task/boost/task/smart.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/smart.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,166 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_SMART_H
+#define BOOST_TASK_SMART_H
+
+#include <cstddef>
+
+#include <boost/assert.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/mem_fun.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+
+#include <boost/task/detail/callable.hpp>
+#include <boost/task/detail/info.hpp>
+
+namespace boost { namespace task
+{
+template<
+ typename Attr,
+ typename Ord,
+ typename Enq,
+ typename Deq
+>
+struct smart
+{
+ typedef detail::has_priority priority_tag_type;
+ typedef Attr attribute_type;
+
+ class impl
+ {
+ private:
+ typedef Attr attribute;
+ typedef Deq dequeue_op;
+ typedef Enq enqueue_op;
+ typedef Ord ordering;
+
+ public:
+ class item
+ {
+ private:
+ detail::callable ca_;
+ attribute attr_;
+
+ public:
+ item()
+ : ca_(), attr_()
+ {}
+
+ item(
+ detail::callable const& ca,
+ attribute const& attr)
+ : ca_( ca), attr_( attr)
+ { BOOST_ASSERT( ! ca_.empty() ); }
+
+ const detail::callable ca() const
+ { return ca_; }
+
+ const attribute attr() const
+ { return attr_; }
+ };
+
+ private:
+ typedef multi_index::multi_index_container<
+ item,
+ multi_index::indexed_by<
+ multi_index::ordered_non_unique<
+ multi_index::const_mem_fun<
+ item,
+ const attribute,
+ & item::attr
+ >,
+ ordering
+ >
+ >
+ > list;
+ typedef typename list::template nth_index< 0 >::type index;
+
+ list lst_;
+ index & idx_;
+ enqueue_op enq_op_;
+ dequeue_op deq_op_;
+
+ public:
+ typedef typename index::iterator iterator;
+ typedef typename index::const_iterator const_iterator;
+
+ impl(
+ enqueue_op const& enq_op = enqueue_op(),
+ dequeue_op const& deq_op = dequeue_op() )
+ :
+ lst_(),
+ idx_( lst_.get< 0 >() ),
+ enq_op_( enq_op),
+ deq_op_( deq_op)
+ {}
+
+ void push( item const& itm)
+ { enq_op_( idx_, itm); }
+
+ const detail::callable pop()
+ {
+ item itm;
+ deq_op_( idx_, itm);
+ return 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 Index,
+ typename Item
+ >
+ void operator()( Index & idx, Item & itm)
+ {
+ typedef typename Index::iterator iterator;
+ iterator i( idx.begin() );
+ BOOST_ASSERT( i != idx.end() );
+ itm = * i;
+ idx.erase( i);
+ }
+};
+} }
+
+#endif // BOOST_TASK_SMART_H
Added: sandbox/task/boost/task/task.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/task.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,448 @@
+// Copright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_TASK_H
+#define BOOST_TASK_TASK_H
+
+#include <exception>
+#include <ios>
+#include <new>
+#include <stdexcept>
+#include <typeinfo>
+
+#include <boost/exception_ptr.hpp>
+#include <boost/exception.hpp>
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/utility/result_of.hpp>
+
+#include <boost/task/detail/interrupter.hpp>
+#include <boost/task/exceptions.hpp>
+#include <boost/task/future.hpp>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+class callable;
+}
+template< typename Channel >
+class pool;
+
+template< typename R >
+class task
+{
+private:
+ template< typename Channel >
+ friend class pool;
+ friend class detail::callable;
+ template< typename Iterator >
+ friend void waitfor_all( Iterator begin, Iterator end);
+ template< typename T1, typename T2 >
+ friend void waitfor_all( T1 & t1, T2 & t2);
+ template< typename T1, typename T2, typename T3 >
+ friend void waitfor_all( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3);
+ template< typename T1, typename T2, typename T3, typename T4 >
+ friend void waitfor_all( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3, task< T4 > & t4);
+ template< typename T1, typename T2, typename T3, typename T4, typename T5 >
+ friend void waitfor_all( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3, task< T4 > & t4, task< T5 > & t5);
+ template< typename Iterator >
+ friend Iterator waitfor_any( Iterator begin, Iterator end);
+ template< typename T1, typename T2 >
+ friend unsigned int waitfor_any( task< T1 > & t1, task< T2 > & t2);
+ template< typename T1, typename T2, typename T3 >
+ friend unsigned int waitfor_any( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3);
+ template< typename T1, typename T2, typename T3, typename T4 >
+ friend unsigned int waitfor_any( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3, task< T4 > & t4);
+ template< typename T1, typename T2, typename T3, typename T4, typename T5 >
+ friend unsigned int waitfor_any( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3, task< T4 > & t4, task< T5 > & t5);
+
+ struct impl
+ {
+ promise< R > prom;
+ shared_future< R > fut;
+ detail::interrupter intr;
+ exception_ptr excep;
+
+ impl()
+ :
+ prom(),
+ fut( prom.get_future() ),
+ intr(),
+ excep()
+ {}
+
+ virtual ~impl() {}
+
+ virtual void operator()() = 0;
+ };
+
+ template< typename Fn >
+ class impl_wrapper : public impl
+ {
+ private:
+ Fn fn_;
+
+ public:
+ impl_wrapper( Fn const& fn)
+ : fn_( fn)
+ {}
+
+ void operator()() // throw()
+ {
+ try
+ { impl::prom.set_value( fn_() ); }
+ catch ( promise_already_satisfied const&)
+ { impl::excep = copy_exception( task_already_executed() ); }
+ catch ( thread_interrupted const&)
+ { impl::prom.set_exception( copy_exception( task_interrupted() ) ); }
+ catch ( boost::exception const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::ios_base::failure const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::domain_error const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::invalid_argument const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::length_error const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::out_of_range const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::logic_error const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::overflow_error const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::range_error const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::underflow_error const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::runtime_error const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::bad_alloc const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::bad_cast const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::bad_typeid const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::bad_exception const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch(...)
+ { impl::prom.set_exception( current_exception() ); }
+ }
+ };
+
+ shared_ptr< impl > impl_;
+
+public:
+ task()
+ : impl_()
+ {}
+
+ template< typename Fn >
+ task( Fn const& fn)
+ : impl_( new impl_wrapper< Fn >( fn) )
+ {}
+
+ void interrupt()
+ { impl_->intr.interrupt(); }
+
+ void interrupt_and_wait()
+ { impl_->intr.interrupt_and_wait(); }
+
+ void interrupt_and_wait( system_time const& abs_time)
+ { impl_->intr.interrupt_and_wait( abs_time); }
+
+ template< typename Duration >
+ void interrupt_and_wait( Duration const& rel_time)
+ { impl_->intr.interrupt_and_wait( rel_time); }
+
+ bool interruption_requested()
+ { return impl_->intr.interruption_requested(); }
+
+ R get()
+ {
+ if ( impl_->excep)
+ rethrow_exception( impl_->excep);
+ return impl_->fut.get();
+ }
+
+ bool is_ready() const
+ { return impl_->fut.is_ready(); }
+
+ bool has_value() const
+ { return impl_->fut.has_value(); }
+
+ bool has_exception() const
+ { return impl_->excep ? true : impl_->fut.has_exception(); }
+
+ void wait() const
+ { impl_->fut.wait(); }
+
+ template< typename Duration >
+ bool timed_wait( Duration const& rel_time) const
+ { return impl_->fut.timed_wait( rel_time); }
+
+ bool timed_wait_until( system_time const& abs_time) const
+ { return impl_->fut.timed_wait_until( abs_time); }
+
+ void swap( task< R > & other) // throw()
+ { impl_.swap( other.impl_); }
+
+ void operator()() // throw()
+ { ( * impl_)(); }
+
+ template< typename F >
+ void set_wait_callback( F const& f)
+ { impl_->prom.set_wait_callback( f); }
+};
+
+template<>
+class task< void >
+{
+private:
+ template< typename Channel >
+ friend class pool;
+ friend class detail::callable;
+ template< typename Iterator >
+ friend void waitfor_all( Iterator begin, Iterator end);
+ template< typename T1, typename T2 >
+ friend void waitfor_all( T1 & t1, T2 & t2);
+ template< typename T1, typename T2, typename T3 >
+ friend void waitfor_all( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3);
+ template< typename T1, typename T2, typename T3, typename T4 >
+ friend void waitfor_all( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3, task< T4 > & t4);
+ template< typename T1, typename T2, typename T3, typename T4, typename T5 >
+ friend void waitfor_all( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3, task< T4 > & t4, task< T5 > & t5);
+ template< typename Iterator >
+ friend Iterator waitfor_any( Iterator begin, Iterator end);
+ template< typename T1, typename T2 >
+ friend unsigned int waitfor_any( task< T1 > & t1, task< T2 > & t2);
+ template< typename T1, typename T2, typename T3 >
+ friend unsigned int waitfor_any( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3);
+ template< typename T1, typename T2, typename T3, typename T4 >
+ friend unsigned int waitfor_any( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3, task< T4 > & t4);
+ template< typename T1, typename T2, typename T3, typename T4, typename T5 >
+ friend unsigned int waitfor_any( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3, task< T4 > & t4, task< T5 > & t5);
+
+ struct impl
+ {
+ promise< void > prom;
+ shared_future< void > fut;
+ detail::interrupter intr;
+ exception_ptr excep;
+
+ impl()
+ :
+ prom(),
+ fut( prom.get_future() ),
+ intr(),
+ excep()
+ {}
+
+ virtual ~impl() {}
+
+ virtual void operator()() = 0;
+ };
+
+ template< typename Fn >
+ class impl_wrapper : public impl
+ {
+ private:
+ Fn fn_;
+
+ public:
+ impl_wrapper( Fn const& fn)
+ : fn_( fn)
+ {}
+
+ void operator()() // throw()
+ {
+ try
+ {
+ fn_();
+ impl::prom.set_value();
+ }
+ catch ( promise_already_satisfied const&)
+ { impl::excep = copy_exception( task_already_executed() ); }
+ catch ( thread_interrupted const&)
+ { impl::prom.set_exception( copy_exception( task_interrupted() ) ); }
+ catch ( boost::exception const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::ios_base::failure const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::domain_error const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::invalid_argument const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::length_error const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::out_of_range const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::logic_error const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::overflow_error const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::range_error const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::underflow_error const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::runtime_error const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::bad_alloc const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::bad_cast const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::bad_typeid const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch ( std::bad_exception const& e)
+ { impl::prom.set_exception( copy_exception( e) ); }
+ catch(...)
+ { impl::prom.set_exception( current_exception() ); }
+ }
+ };
+
+ shared_ptr< impl > impl_;
+
+public:
+ task()
+ : impl_()
+ {}
+
+ template< typename Fn >
+ task( Fn const& fn)
+ : impl_( new impl_wrapper< Fn >( fn) )
+ {}
+
+ void interrupt()
+ { impl_->intr.interrupt(); }
+
+ void interrupt_and_wait()
+ { impl_->intr.interrupt_and_wait(); }
+
+ void interrupt_and_wait( system_time const& abs_time)
+ { impl_->intr.interrupt_and_wait( abs_time); }
+
+ template< typename Duration >
+ void interrupt_and_wait( Duration const& rel_time)
+ { impl_->intr.interrupt_and_wait( rel_time); }
+
+ bool interruption_requested()
+ { return impl_->intr.interruption_requested(); }
+
+ void get()
+ {
+ if ( impl_->excep)
+ rethrow_exception( impl_->excep);
+ impl_->fut.get();
+ }
+
+ bool is_ready() const
+ { return impl_->fut.is_ready(); }
+
+ bool has_value() const
+ { return impl_->fut.has_value(); }
+
+ bool has_exception() const
+ { return impl_->excep ? true : impl_->fut.has_exception(); }
+
+ void wait() const
+ { impl_->fut.wait(); }
+
+ template< typename Duration >
+ bool timed_wait( Duration const& rel_time) const
+ { return impl_->fut.timed_wait( rel_time); }
+
+ bool timed_wait_until( system_time const& abs_time) const
+ { return impl_->fut.timed_wait_until( abs_time); }
+
+ void swap( task< void > & other) // throw()
+ { impl_.swap( other.impl_); }
+
+ void operator()() // throw()
+ { ( * impl_)(); }
+
+ template< typename F >
+ void set_wait_callback( F const& f)
+ { impl_->prom.set_wait_callback( f); }
+};
+
+template< typename Iterator >
+void waitfor_all( Iterator begin, Iterator end)
+{
+ for ( Iterator i = begin; i != end; ++i)
+ i->wait();
+}
+
+template< typename T1, typename T2 >
+void waitfor_all( T1 & t1, T2 & t2)
+{ wait_for_all( t1.fut_, t2.fut_); }
+
+template< typename T1, typename T2, typename T3 >
+void waitfor_all( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3)
+{ wait_for_all( t1.fut_, t2.fut_, t3.fut_); }
+
+template< typename T1, typename T2, typename T3, typename T4 >
+void waitfor_all( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3, task< T4 > & t4)
+{ wait_for_all( t1.fut_, t2.fut_, t3.fut_, t4.fut_); }
+
+template< typename T1, typename T2, typename T3, typename T4, typename T5 >
+void waitfor_all( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3, task< T4 > & t4, task< T5 > & t5)
+{ wait_for_all( t1.fut_, t2.fut_, t3.fut_, t4.fut_, t5.fut_); }
+
+template< typename Iterator >
+Iterator waitfor_any( Iterator begin, Iterator end)
+{
+ boost::detail::future_waiter waiter;
+ for ( Iterator i = begin; i != end; ++i)
+ waiter.add( i->fut_);
+ return next( begin, waiter.wait() );
+}
+
+template< typename T1, typename T2 >
+unsigned int waitfor_any( task< T1 > & t1, task< T2 > & t2)
+{ return wait_for_any( t1.fut_, t2.fut_); }
+
+template< typename T1, typename T2, typename T3 >
+unsigned int waitfor_any( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3)
+{ return wait_for_any( t1.fut_, t2.fut_, t3.fut_); }
+
+template< typename T1, typename T2, typename T3, typename T4 >
+unsigned int waitfor_any( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3, task< T4 > & t4)
+{ return wait_for_any( t1.fut_, t2.fut_, t3.fut_, t4.fut_); }
+
+template< typename T1, typename T2, typename T3, typename T4, typename T5 >
+unsigned int waitfor_any( task< T1 > & t1, task< T2 > & t2, task< T3 > & t3, task< T4 > & t4, task< T5 > & t5)
+{ return wait_for_any( t1.fut_, t2.fut_, t3.fut_, t4.fut_, t5.fut_); }
+
+template< typename Fn >
+task< typename result_of< Fn() >::type > make_task( Fn fn)
+{ return task< typename boost::result_of< Fn() >::type >( fn); }
+
+# ifndef BOOST_TASK_MAKE_TASK_MAX_ARITY
+# define BOOST_TASK_MAKE_TASK_MAX_ARITY 10
+# endif
+
+# define BOOST_TASK_MAKE_TASK_FUNC_ARG(z, n, unused) \
+ BOOST_PP_CAT(A, n) BOOST_PP_CAT(a, n)
+# define BOOST_ENUM_TASK_MAKE_TASK_FUNC_ARGS(n) BOOST_PP_ENUM(n, BOOST_TASK_MAKE_TASK_FUNC_ARG, ~)
+
+# define BOOST_TASK_MAKE_TASK_FUNCTION(z, n, unused) \
+template< \
+ typename Fn, \
+ BOOST_PP_ENUM_PARAMS(n, typename A) \
+> \
+task< typename result_of< Fn( BOOST_PP_ENUM_PARAMS(n, A)) >::type > \
+make_task( Fn fn, BOOST_ENUM_TASK_MAKE_TASK_FUNC_ARGS(n)) \
+{ return make_task( boost::bind( fn, BOOST_PP_ENUM_PARAMS(n, a))); }
+
+BOOST_PP_REPEAT_FROM_TO( 1, BOOST_TASK_MAKE_TASK_MAX_ARITY, BOOST_TASK_MAKE_TASK_FUNCTION, ~)
+
+# undef BOOST_TASK_MAKE_TASK_FUNCTION
+# undef BOOST_TASK_MAKE_TASK_FUNC_ARG
+# undef BOOST_ENUM_TASK_MAKE_TASK_FUNC_ARGS
+
+}}
+
+#endif // BOOST_TASK_TASK_H
Added: sandbox/task/boost/task/unbounded_channel.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/unbounded_channel.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,275 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_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/detail/callable.hpp>
+#include <boost/task/exceptions.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< detail::callable > drain_()
+ {
+ BOOST_ASSERT( deactive_now_() );
+ std::vector< detail::callable > unprocessed;
+ unprocessed.reserve( queue_.size() );
+ BOOST_FOREACH( detail::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,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( ! active_() )
+ throw task_rejected("channel is not active");
+ queue_.push( itm);
+ not_empty_cond_.notify_one();
+ }
+
+ bool take_(
+ detail::callable & ca,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ try
+ {
+ not_empty_cond_.wait(
+ lk,
+ bind(
+ & unbounded_channel::consumers_activate_,
+ this) );
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ ca = queue_.pop();
+ return ! ca.empty();
+ }
+
+ template< typename Duration >
+ bool take_(
+ detail::callable & ca,
+ Duration const& rel_time,
+ unique_lock< shared_mutex > & lk)
+ {
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ try
+ {
+ if ( ! not_empty_cond_.timed_wait(
+ lk,
+ rel_time,
+ bind(
+ & unbounded_channel::consumers_activate_,
+ this) ) )
+ return false;
+ }
+ catch ( thread_interrupted const&)
+ { return false; }
+ if ( deactive_now_() || ( deactive_() && empty_() ) )
+ return false;
+ ca = queue_.pop();
+ return ! ca.empty();
+ }
+
+ bool try_take_( detail::callable & ca)
+ {
+ if ( deactive_now_() || empty_() )
+ return false;
+ ca = queue_.pop();
+ return ! ca.empty();
+ }
+
+ bool consumers_activate_() const
+ { return ! active_() || ! empty_(); }
+
+public:
+ unbounded_channel()
+ :
+ state_( channel_active),
+ queue_(),
+ mtx_(),
+ not_empty_cond_()
+ {}
+
+ bool active()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return active_();
+ }
+
+ void activate()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ activate_();
+ }
+
+ void clear()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ clear_();
+ }
+
+ bool deactive()
+ { return ! active(); }
+
+ void deactivate()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ deactivate_();
+ }
+
+ void deactivate_now()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ deactivate_now_();
+ }
+
+ const std::vector< detail::callable > drain()
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return drain_();
+ }
+
+ bool empty()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return empty_();
+ }
+
+ bool full()
+ { return false; }
+
+ std::size_t size()
+ {
+ shared_lock< shared_mutex > lk( mtx_);
+ return size_();
+ }
+
+ void put( item const& itm)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( itm, lk);
+ }
+
+ template< typename Duration >
+ void put(
+ item & itm,
+ Duration const&)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ put_( itm, lk);
+ }
+
+ bool take( detail::callable & ca)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, lk);
+ }
+
+ template< typename Duration >
+ bool take(
+ detail::callable & ca,
+ Duration const& rel_time)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return take_( ca, rel_time, lk);
+ }
+
+ bool try_take( detail::callable & ca)
+ {
+ unique_lock< shared_mutex > lk( mtx_);
+ return try_take_( ca);
+ }
+};
+} }
+
+#endif // BOOST_TASK_UNBOUNDED_CHANNEL_H
Added: sandbox/task/boost/task/utility.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/utility.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,119 @@
+// Copright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_UTILITY_H
+#define BOOST_TASK_UTILITY_H
+
+#include <boost/assert.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/thread_time.hpp>
+
+#include <boost/task/detail/worker.hpp>
+
+namespace boost { namespace this_task
+{
+namespace detail
+{
+struct time_reached
+{
+ system_time abs_time;
+
+ time_reached( system_time & abs_time_)
+ : abs_time( abs_time_)
+ {}
+
+ bool operator()()
+ { return get_system_time() >= abs_time; }
+};
+
+class once_false
+{
+private:
+ bool result_;
+
+public:
+ once_false()
+ : result_( false)
+ {}
+
+ bool operator()()
+ {
+ if ( ! result_)
+ {
+ result_ = true;
+ return false;
+ }
+ else
+ return true;
+ }
+};
+}
+
+template< typename Pred >
+void reschedule_until( Pred const& pred)
+{
+ task::detail::worker * w( task::detail::worker::tss_get() );
+ BOOST_ASSERT( w);
+ w->reschedule_until( pred);
+}
+
+template< typename Pool >
+Pool & get_pool()
+{
+ task::detail::worker * w( task::detail::worker::tss_get() );
+ BOOST_ASSERT( w);
+ return w->get_pool< Pool >();
+}
+
+inline
+bool runs_in_pool()
+{ return task::detail::worker::tss_get() != 0; }
+
+inline
+thread::id worker_id()
+{
+ task::detail::worker * w( task::detail::worker::tss_get() );
+ BOOST_ASSERT( w);
+ return w->get_id();
+}
+
+inline
+void delay( system_time abs_time)
+{
+ if ( runs_in_pool() )
+ {
+ detail::time_reached t( abs_time);
+ reschedule_until( t);
+ }
+ else
+ this_thread::sleep( abs_time);
+}
+
+template< typename Duration >
+void delay( Duration const& rel_time)
+{ delay( get_system_time() + rel_time); }
+
+inline
+void yield()
+{
+ if ( runs_in_pool() )
+ {
+ detail::once_false t;
+ reschedule_until( t);
+ }
+ else
+ this_thread::yield();
+}
+
+inline
+void interrupt()
+{
+ task::detail::worker * w( task::detail::worker::tss_get() );
+ BOOST_ASSERT( w);
+ w->interrupt();
+ this_thread::interruption_point();
+}
+}}
+
+#endif // BOOST_TASK_UTILITY_H
Added: sandbox/task/boost/task/watermark.hpp
==============================================================================
--- (empty file)
+++ sandbox/task/boost/task/watermark.hpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,35 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TASK_WATER_MARK_H
+#define BOOST_TASK_WATER_MARK_H
+
+#include <cstddef>
+
+namespace boost { namespace task
+{
+class high_watermark
+{
+private:
+ std::size_t value_;
+
+public:
+ explicit high_watermark( std::size_t value);
+
+ operator std::size_t () const;
+};
+
+class low_watermark
+{
+private:
+ std::size_t value_;
+
+public:
+ explicit low_watermark( std::size_t value);
+
+ operator std::size_t () const;
+};
+} }
+
+#endif // BOOST_TASK_WATER_MARK_H
Added: sandbox/task/libs/task/src/callable.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/src/callable.cpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,30 @@
+#include "boost/task/detail/callable.hpp"
+
+namespace boost { namespace task
+{
+namespace detail
+{
+callable::callable()
+: impl_()
+{}
+
+void
+callable::operator()()
+{ impl_->run(); }
+
+bool
+callable::empty() const
+{ return ! impl_; }
+
+void
+callable::clear()
+{ impl_.reset(); }
+
+callable::scoped_lock::scoped_lock( callable & ca, shared_ptr< thread > & thrd)
+: ca_( ca)
+{ ca_.impl_->set( thrd); }
+
+callable::scoped_lock::~scoped_lock()
+{ ca_.impl_->reset(); }
+} } }
+
Added: sandbox/task/libs/task/src/default_pool.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/src/default_pool.cpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,14 @@
+#include "boost/task/default_pool.hpp"
+
+#include <boost/thread.hpp>
+
+#include "boost/task/poolsize.hpp"
+
+namespace boost { namespace task
+{
+namespace detail
+{
+default_pool
+static_pool::instance( poolsize( thread::hardware_concurrency() ) );
+}
+} }
Added: sandbox/task/libs/task/src/guard.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/src/guard.cpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,24 @@
+#include "boost/task/detail/guard.hpp"
+
+#include <boost/assert.hpp>
+
+#include <boost/task/detail/atomic.hpp>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+guard::guard( unsigned int & active_worker)
+: active_worker_( active_worker)
+{
+ BOOST_ASSERT( active_worker_ >= 0);
+ atomic_inc_32( & active_worker_);
+}
+
+guard::~guard()
+{
+ atomic_dec_32( & active_worker_);
+ BOOST_ASSERT( active_worker_ >= 0);
+}
+} } }
+
Added: sandbox/task/libs/task/src/interrupter.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/src/interrupter.cpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,110 @@
+#include "boost/task/detail/interrupter.hpp"
+
+#include <boost/assert.hpp>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+void
+interrupter::impl::interrupt_()
+{
+ if ( ! interruption_requested_)
+ {
+ interruption_requested_ = true;
+ if ( thrd_) thrd_->interrupt();
+ }
+}
+
+interrupter::impl::impl()
+:
+interruption_requested_( false),
+cond_(),
+mtx_(),
+thrd_()
+{}
+
+void
+interrupter::impl::set( shared_ptr< thread > const& thrd)
+{
+ BOOST_ASSERT( thrd);
+ unique_lock< mutex > lk( mtx_);
+ thrd_ = thrd;
+ BOOST_ASSERT( thrd_);
+ if ( interruption_requested_) thrd_->interrupt();
+}
+
+void
+interrupter::impl::reset()
+{
+ unique_lock< mutex > lk( mtx_);
+ thrd_.reset();
+ BOOST_ASSERT( ! thrd_);
+ try
+ { this_thread::interruption_point(); }
+ catch ( thread_interrupted const&)
+ {}
+ BOOST_ASSERT( ! this_thread::interruption_requested() );
+ cond_.notify_all();
+}
+
+void
+interrupter::impl::interrupt()
+{
+ unique_lock< mutex > lk( mtx_);
+ interrupt_();
+}
+
+void
+interrupter::impl::interrupt_and_wait()
+{
+ unique_lock< mutex > lk( mtx_);
+ interrupt_();
+ cond_.wait( lk);
+}
+
+void
+interrupter::impl::interrupt_and_wait( system_time const& abs_time)
+{
+ unique_lock< mutex > lk( mtx_);
+ interrupt_();
+ cond_.timed_wait( lk, abs_time);
+}
+
+bool
+interrupter::impl::interruption_requested()
+{
+ unique_lock< mutex > lk( mtx_);
+ return interruption_requested_;
+}
+
+interrupter::interrupter()
+: impl_( new impl() )
+{}
+
+void
+interrupter::set( shared_ptr< thread > const& thrd)
+{ impl_->set( thrd); }
+
+void
+interrupter::reset()
+{ impl_->reset(); }
+
+void
+interrupter::interrupt()
+{ impl_->interrupt(); }
+
+void
+interrupter::interrupt_and_wait()
+{ impl_->interrupt_and_wait(); }
+
+void
+interrupter::interrupt_and_wait( system_time const& abs_time)
+{ impl_->interrupt_and_wait( abs_time); }
+
+bool
+interrupter::interruption_requested()
+{ return impl_->interruption_requested(); }
+}
+} }
+
Added: sandbox/task/libs/task/src/poolsize.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/src/poolsize.cpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,14 @@
+#include "boost/task/poolsize.hpp"
+
+#include <boost/task/exceptions.hpp>
+
+namespace boost { namespace task
+{
+poolsize::poolsize( std::size_t value)
+: value_( value)
+{ if ( value <= 0) throw invalid_poolsize(); }
+
+poolsize::operator std::size_t () const
+{ return value_; }
+} }
+
Added: sandbox/task/libs/task/src/scanns.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/src/scanns.cpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,14 @@
+#include "boost/task/scanns.hpp"
+
+#include <boost/task/exceptions.hpp>
+
+namespace boost { namespace task
+{
+scanns::scanns( std::size_t value)
+: value_( value)
+{ if ( value < 0) throw invalid_scanns(); }
+
+scanns::operator std::size_t () const
+{ return value_; }
+} }
+
Added: sandbox/task/libs/task/src/semaphore_posix.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/src/semaphore_posix.cpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,57 @@
+#include "boost/task/detail/semaphore_posix.hpp"
+
+#include <cerrno>
+
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+semaphore::semaphore( int value)
+: sem_()
+{
+ if ( ::sem_init( & sem_, 0, value) == -1)
+ throw system::system_error( errno, system::system_category);
+}
+
+semaphore::~semaphore()
+{ ::sem_destroy( & sem_); }
+
+void
+semaphore::post()
+{
+ if ( ::sem_post( & sem_) == -1)
+ throw system::system_error( errno, system::system_category);
+}
+
+void
+semaphore::wait()
+{
+ if ( ::sem_wait( & sem_) == -1)
+ throw system::system_error( errno, system::system_category);
+}
+
+bool
+semaphore::try_wait()
+{
+ if ( ::sem_trywait( & sem_) == -1)
+ {
+ if ( errno == EAGAIN)
+ return false;
+ else
+ throw system::system_error( errno, system::system_category);
+ }
+ return true;
+}
+
+int
+semaphore::value()
+{
+ int value( 0);
+ if ( ::sem_getvalue( & sem_, & value) == -1)
+ throw system::system_error( errno, system::system_category);
+ return value;
+}
+}}}
Added: sandbox/task/libs/task/src/semaphore_windows.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/src/semaphore_windows.cpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,64 @@
+#include "boost/task/detail/semaphore_windows.hpp"
+
+#include <cerrno>
+#include <limits>
+
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+semaphore::semaphore( int value)
+: handle_()
+{
+ if ( ( handle_ = ::CreateSemaphore( 0, value, std::numeric_limits< int >::max(), 0) ) == 0)
+ throw system::system_error( ::GetLastError(), system::system_category);
+}
+
+semaphore::~semaphore()
+{ ::CloseHandle( handle_); }
+
+void
+semaphore::post()
+{
+ if ( ! ::ReleaseSemaphore( handle_, 1, 0) )
+ throw system::system_error( ::GetLastError(), system::system_category);
+}
+
+void
+semaphore::wait()
+{
+ if ( ::WaitForSingleObject( handle_, INFINITE) != WAIT_OBJECT_0)
+ throw system::system_error( ::GetLastError(), system::system_category);
+}
+
+bool
+semaphore::try_wait()
+{
+ switch ( ::WaitForSingleObject( handle_, 0) )
+ {
+ case WAIT_OBJECT_0:
+ return true;
+ case WAIT_TIMEOUT:
+ return false;
+ default:
+ throw system::system_error( ::GetLastError(), system::system_category);
+ }
+ return true;
+}
+
+int
+semaphore::value()
+{
+ int value( 0);
+ if ( ::WaitForSingleObject( handle_, 0) != WAIT_TIMEOUT)
+ {
+ if ( ! ::ReleaseSemaphore( handle_, 1, & value) )
+ throw system::system_error( ::GetLastError(), system::system_category);
+ ++ value;
+ }
+ return value;
+}
+}}}
Added: sandbox/task/libs/task/src/watermark.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/src/watermark.cpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,26 @@
+#include "boost/task/watermark.hpp"
+
+#include <boost/task/exceptions.hpp>
+
+namespace boost { namespace task
+{
+high_watermark::high_watermark( std::size_t value)
+: value_( value)
+{
+ if ( value <= 0)
+ throw invalid_watermark("high watermark must be greater than zero");
+}
+
+high_watermark::operator std::size_t () const
+{ return value_; }
+
+low_watermark::low_watermark( std::size_t value)
+: value_( value)
+{
+ if ( value < 0)
+ throw invalid_watermark("low watermark must be greater than or equal to zero");
+}
+
+low_watermark::operator std::size_t () const
+{ return value_; }
+} }
Added: sandbox/task/libs/task/src/worker.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/src/worker.cpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,56 @@
+#include "boost/task/detail/worker.hpp"
+
+namespace boost { namespace task
+{
+namespace detail
+{
+thread_specific_ptr< worker > worker::tss_;
+
+const thread::id
+worker::get_id() const
+{ return impl_->get_id(); }
+
+void
+worker::join() const
+{ impl_->join(); }
+
+void
+worker::interrupt() const
+{ impl_->interrupt(); }
+
+void
+worker::signal_shutdown()
+{ impl_->signal_shutdown(); }
+
+void
+worker::signal_shutdown_now()
+{ impl_->signal_shutdown_now(); }
+
+void
+worker::put( callable const& ca)
+{ impl_->put( ca); }
+
+bool
+worker::try_take( callable & ca)
+{ return impl_->try_take( ca); }
+
+bool
+worker::try_steal( callable & ca)
+{ return impl_->try_steal( ca); }
+
+void
+worker::reschedule_until( function< bool() > const& pred)
+{ return impl_->schedule_until( pred); }
+
+void
+worker::run()
+{
+ worker::tss_.reset( new worker( * this) );
+ impl_->run();
+}
+
+worker *
+worker::tss_get()
+{ return worker::tss_.get(); }
+} } }
+
Added: sandbox/task/libs/task/src/worker_group.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/src/worker_group.cpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,81 @@
+// Copyright (c) 2008 Oliver Kowalke. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "boost/task/detail/worker_group.hpp"
+
+#include <boost/foreach.hpp>
+#include <boost/utility.hpp>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+worker_group::worker_group()
+:
+cont_(),
+id_idx_( cont_.get< id_idx_tag >() ),
+rnd_idx_( cont_.get< rnd_idx_tag >() )
+{}
+
+const worker
+worker_group::operator[]( std::size_t pos) const
+{ return rnd_idx_[pos]; }
+
+std::size_t
+worker_group::size() const
+{ return cont_.size(); }
+
+const worker_group::iterator
+worker_group::begin()
+{ return id_idx_.begin(); }
+
+const worker_group::const_iterator
+worker_group::begin() const
+{ return id_idx_.begin(); }
+
+const worker_group::iterator
+worker_group::end()
+{ return id_idx_.end(); }
+
+const worker_group::const_iterator
+worker_group::end() const
+{ return id_idx_.end(); }
+
+const worker_group::const_iterator
+worker_group::find( thread::id const& id) const
+{ return id_idx_.find( id); }
+
+void
+worker_group::join_all()
+{
+ BOOST_FOREACH( worker w, cont_)
+ { w.join(); }
+}
+
+void
+worker_group::interrupt_all()
+{
+ BOOST_FOREACH( worker w, cont_)
+ { w.interrupt(); }
+}
+
+void
+worker_group::insert( worker const& w)
+{ cont_.insert( w); }
+
+void
+worker_group::signal_shutdown_all()
+{
+ BOOST_FOREACH( worker w, cont_)
+ { w.signal_shutdown(); }
+}
+
+void
+worker_group::signal_shutdown_now_all()
+{
+ BOOST_FOREACH( worker w, cont_)
+ { w.signal_shutdown_now(); }
+}
+} } }
+
Added: sandbox/task/libs/task/src/wsq.cpp
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/src/wsq.cpp 2009-04-17 12:10:19 EDT (Fri, 17 Apr 2009)
@@ -0,0 +1,113 @@
+#include "boost/task/detail/wsq.hpp"
+
+#include <boost/thread/locks.hpp>
+
+#include <boost/task/detail/atomic.hpp>
+
+namespace boost { namespace task
+{
+namespace detail
+{
+wsq::wsq()
+:
+initial_size_( 32),
+array_( new callable[ initial_size_]),
+capacity_( initial_size_),
+mask_( initial_size_ - 1),
+head_idx_( 0),
+tail_idx_( 0),
+mtx_()
+{}
+
+bool
+wsq::empty() const
+{ return head_idx_ >= tail_idx_; }
+
+std::size_t
+wsq::size() const
+{ return tail_idx_ - head_idx_; }
+
+void
+wsq::put( callable const& ca)
+{
+ uint32_t tail( tail_idx_);
+ if ( tail <= head_idx_ + mask_)
+ {
+ array_[tail & mask_] = ca;
+ tail_idx_ = tail + 1;
+ }
+ else
+ {
+ unique_lock< recursive_mutex > lk( mtx_);
+ uint32_t head( head_idx_);
+ int count( size() );
+
+ if ( count >= mask_)
+ {
+ capacity_ <<= 1;
+ shared_array< callable > array( new callable[capacity_]);
+ for ( int i( 0); i != count; ++i)
+ array[i] = array_[(i + head) & mask_];
+ array_.swap( array);
+ head_idx_ = 0;
+ tail_idx_ = tail = count;
+ mask_ = (mask_ << 1) | 1;
+ }
+ array_[tail & mask_] = ca;
+ tail_idx_ = tail + 1;
+ }
+}
+
+bool
+wsq::try_take( callable & ca)
+{
+ uint32_t tail( tail_idx_);
+ if ( tail == 0)
+ return false;
+ tail -= 1;
+ atomic_write_32( & tail_idx_, tail); // Interlocked.Exchange( & tail_idx_, tail); -> XCHG
+ if ( head_idx_ <= tail)
+ {
+ ca = array_[tail & mask_];
+ return true;
+ }
+ else
+ {
+ unique_lock< recursive_mutex > lk( mtx_);
+ if ( head_idx_ <= tail)
+ {
+ ca = array_[tail & mask_];
+ return true;
+ }
+ else
+ {
+ tail_idx_ = tail + 1;
+ return false;
+ }
+ }
+}
+
+bool
+wsq::try_steal( callable & ca)
+{
+ recursive_mutex::scoped_try_lock lk( mtx_);
+ if ( lk.owns_lock() )
+ {
+ uint32_t head( head_idx_);
+ atomic_write_32( & head_idx_, head + 1); // Interlocked.Exchange( & head_idx_, head + 1);
+ if ( head < tail_idx_)
+ {
+ ca = array_[head & mask_];
+ return true;
+ }
+ else
+ {
+ head_idx_ = head;
+ return false;
+ }
+ }
+ return false;
+}
+} } }
+
+
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