Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r58840 - sandbox/task/libs/task/doc
From: oliver.kowalke_at_[hidden]
Date: 2010-01-09 10:08:58


Author: olli
Date: 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
New Revision: 58840
URL: http://svn.boost.org/trac/boost/changeset/58840

Log:
- docu updated

Added:
   sandbox/task/libs/task/doc/
   sandbox/task/libs/task/doc/Jamfile.v2 (contents, props changed)
   sandbox/task/libs/task/doc/acknowledgements.qbk (contents, props changed)
   sandbox/task/libs/task/doc/as_sub_task.qbk (contents, props changed)
   sandbox/task/libs/task/doc/async_completion_token.qbk (contents, props changed)
   sandbox/task/libs/task/doc/async_execution.qbk (contents, props changed)
   sandbox/task/libs/task/doc/execution_policies.qbk (contents, props changed)
   sandbox/task/libs/task/doc/fork_join.qbk (contents, props changed)
   sandbox/task/libs/task/doc/handle.qbk (contents, props changed)
   sandbox/task/libs/task/doc/meta_functions.qbk (contents, props changed)
   sandbox/task/libs/task/doc/new_thread.qbk (contents, props changed)
   sandbox/task/libs/task/doc/overview.qbk (contents, props changed)
   sandbox/task/libs/task/doc/own_thread.qbk (contents, props changed)
   sandbox/task/libs/task/doc/processor_binding.qbk (contents, props changed)
   sandbox/task/libs/task/doc/queue.qbk (contents, props changed)
   sandbox/task/libs/task/doc/scheduler.qbk (contents, props changed)
   sandbox/task/libs/task/doc/shutdown.qbk (contents, props changed)
   sandbox/task/libs/task/doc/spin_barrier.qbk (contents, props changed)
   sandbox/task/libs/task/doc/spin_condition_variables.qbk (contents, props changed)
   sandbox/task/libs/task/doc/spin_event_variables.qbk (contents, props changed)
   sandbox/task/libs/task/doc/spin_fifos.qbk (contents, props changed)
   sandbox/task/libs/task/doc/spin_future_ref.qbk (contents, props changed)
   sandbox/task/libs/task/doc/spin_futures.qbk (contents, props changed)
   sandbox/task/libs/task/doc/spin_mutexes.qbk (contents, props changed)
   sandbox/task/libs/task/doc/spin_synchronization.qbk (contents, props changed)
   sandbox/task/libs/task/doc/static_pool.qbk (contents, props changed)
   sandbox/task/libs/task/doc/task.qbk (contents, props changed)
   sandbox/task/libs/task/doc/task_ref.qbk (contents, props changed)
   sandbox/task/libs/task/doc/this_task.qbk (contents, props changed)
   sandbox/task/libs/task/doc/threadpool.qbk (contents, props changed)
   sandbox/task/libs/task/doc/todo.qbk (contents, props changed)
   sandbox/task/libs/task/doc/work_stealing.qbk (contents, props changed)

Added: sandbox/task/libs/task/doc/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/Jamfile.v2 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,36 @@
+# Boost.ThreadPool Library Documentation Jamfile
+
+# Copyright (C) 2008 Oliver Kowalke
+
+# Use, modification and distribution is subject to the Boost Software License,
+# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+path-constant boost-images : ../../../doc/src/images ;
+
+xml task : task.qbk ;
+
+boostbook standalone
+ :
+ task
+ :
+ # HTML options first:
+ # Use graphics not text for navigation:
+ <xsl:param>navig.graphics=1
+ # How far down we chunk nested sections, basically all of them:
+ <xsl:param>chunk.section.depth=3
+ # Don't put the first section on the same page as the TOC:
+ <xsl:param>chunk.first.sections=1
+ # How far down sections get TOC's
+ <xsl:param>toc.section.depth=10
+ # Max depth in each TOC:
+ <xsl:param>toc.max.depth=3
+ # How far down we go with TOC's
+ <xsl:param>generate.section.toc.level=10
+ # Path for links to Boost:
+ <xsl:param>boost.root=../../../..
+ # Path for libraries index:
+ <xsl:param>boost.libraries=../../../../libs/libraries.htm
+ # Use the main Boost stylesheet:
+ <xsl:param>html.stylesheet=../../../../doc/html/boostbook.css
+ ;

Added: sandbox/task/libs/task/doc/acknowledgements.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/acknowledgements.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,13 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:acknowledgements Acknowledgments]
+
+I'd like to thank Vicente J. Botet Escriba for his comments.
+
+[endsect]

Added: sandbox/task/libs/task/doc/as_sub_task.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/as_sub_task.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,40 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:as_sub_task Execute as Sub-Task]
+
+__as_sub_task__ is a convenient way to execute a __sub_task__. If the parent task is executed inside a __thread_pool__ the __sub_task__ is put into the local-queue of the
+__worker_thread__ in the other case the __sub_task__ will be executed in a new thread. __as_sub_task__ is used as default __ep__ for __fn_async__,
+
+ boost::task::handle< long > h(
+ boost::task::async(
+ boost::task::make_task( fibonacci, 10),
+ boost::task::as_sub_task() ) );
+
+
+[section:as_sub_task Class `as_sub_task`]
+
+ #include <boost/task/as_sub_task.hpp>
+
+ struct as_sub_task
+ {
+ template< typename R >
+ handle< R > operator()( task< R >);
+ };
+
+
+[section `template< typename R > handle< R > operator()( task< R > t)`]
+[variablelist
+[[Effects:] [moves task in a new thread or thread-pool and returns an handle associated with the task]]
+[[Throws:] [`boost::thread_resource_error`]]
+]
+[endsect]
+
+[endsect]
+
+[endsect]

Added: sandbox/task/libs/task/doc/async_completion_token.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/async_completion_token.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,315 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:async_completion_token Asynchronous Completion Token]
+
+[heading Synopsis]
+
+The __act__ dispatches processing tasks in response to the completion of asynchronous operations. __act__ uniquely identifies
+the task and state necessary to process the result of the operation [footnote see [@http://www.cs.wustl.edu/~schmidt/PDF/ACT.pdf 'Asynchronous Completion Token'], Douglas Schmidt].
+
+__handle__ represents an __act__. It will be returned by __async__ and is associated with the submitted __task__.
+
+ long fibonacci( long n)
+ {
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ long k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ long tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ return k1;
+ }
+
+ void main()
+ {
+ // create task
+ boost::tasks::task< long > t( fibonacci, 10);
+
+ // move task ownership to executor
+ boost::tasks::handle< long > h(
+ boost::tasks::async(
+ boost::move( t),
+ boost::tasks::new_thread() ) );
+
+ std::cout << "is ready == " << std::boolalpha << h.is_ready() << "\n";
+
+ // wait for task completion
+ h.wait();
+
+ std::cout << "has value == " << std::boolalpha << h.has_value() << "\n";
+ std::cout << "has exception == " << std::boolalpha << h.has_exception() << "\n";
+
+ // return result
+ std::cout << "fibonacci(10) == " << h.get() << std::endl;
+ }
+
+[heading Interruption]
+
+Each invokation of __fn_async__ returns an __handle__ which allows to control the associated __task__ (passed to __fn_async__). This includes
+the ability to interrupt an __task__ if it is cooperative. Cooperative means that the __task__ contains __interruption_points__ or checks for
+interruption requests [footnote see [@http://www.ddj.com/architect/207100682 'Interrupt Politely'], Herb Sutter].
+
+* __fn_interrupt__: interrupt __task__ and return immediately
+
+* __fn_interrupt_and_wait__: interrupt and wait until __task__ was removed from __worker_thread__
+
+* __fn_interrupt_and_wait_for__: interrupt and wait until __task__ was removed from __worker_thread__ or time duration has elapsed
+
+* __fn_interrupt_and_wait_until__: interrupt and wait until __task__ was removed from __worker_thread__ or time point has reached
+
+* __fn_interruption_requested__: return bool if interruption was requested
+
+ long cooperative( long n)
+ {
+ boost::this_thread::interruption_point(); // interruption point
+
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ long k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ if ( boost::this_thread::interruption_requested() ) // check if interruption was requested
+ return;
+
+ long tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+
+ boost::this_thread::interruption_point(); // interruption point
+
+ return k1;
+ }
+
+ void main()
+ {
+ // task, to be executed asynchronously
+ boost::tasks::task< long > t( cooperative, 10);
+
+ // move task to async. executor
+ boost::tasks::handle< long > h(
+ boost::tasks::async(
+ boost::move( t),
+ boost::tasks::new_thread() ) );
+
+ // interrupt task and wait until task is removed by worker-thread
+ h.interrupt_and_wait();
+
+ std::cout << "is ready == " << std::boolalpha << h.is_ready() << "\n";
+ std::cout << "has value == " << std::boolalpha << h.has_value() << "\n";
+ std::cout << "has exception == " << std::boolalpha << h.has_exception() << "\n";
+
+ // access result
+ // throws boost::tasks::task_interrupted
+ std::cout << h.get() << std::endl;
+ }
+
+[note If the task is still pending (not executed yet) when an interruption is requested - the task is not removed from the queue, it is marked to be interrupted instead.]
+
+
+[heading Completion]
+
+__boost_task__ provides function __waitfor_all__ waits for all handles passed to this function to become ready
+
+ void main()
+ {
+ std::vector handles< boost::tasks::handle< long > > results;
+ results.reserve( 10);
+
+ for ( int i = 0; i < 10; ++i)
+ {
+ boost::tasks::task< long > t( fibonacci, i);
+
+ results.push_back(
+ boost::tasks::async(
+ boost::move( t) ) );
+ }
+
+ // wait until all tasks are ready
+ boost::tasks::waitfor_all( results.begin(), results.end() );
+
+ int k = 0;
+ std::vector< boost::tasks::handle< long > >::iterator e( results.end() );
+ for (
+ std::vector< boost::tasks::handle< long > >::iterator i( results.begin() );
+ i != e;
+ ++i)
+ std::cout << "fibonacci(" << k++ << ") == " << i->get() << std::endl;
+ }
+
+[section:handle Class template `handle`]
+
+ #include <boost/task/handle.hpp>
+
+ template< typename R >
+ class handle
+ {
+ handle();
+
+ template< typename F >
+ handle( F const&, context const&);
+
+ void interrupt();
+ void interrupt_and_wait();
+ void interrupt_and_wait_until( system_time const& abs_time);
+ template< typename TimeDuration >
+ void interrupt_and_wait_for( Duration const& rel_time);
+ bool interruption_requested();
+
+ R get();
+ bool is_ready() const;
+ bool has_value() const;
+ bool has_exception() const;
+ void wait() const;
+ bool wait_until( system_time const& abs_time);
+ template< typename TimeDuration >
+ bool wait_for( TimeDuration const& rel_time);
+
+ void swap( handle< R > & other);
+ };
+
+ 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, typename T4, typename T5 >
+ friend void waitfor_all( handle< T1 > & t1, handle< T2 > & t2, handle< T3 > & t3, handle< T4 > & t4, handle< T5 > & t5);
+
+[section `handle()`]
+[variablelist
+[[Effects:] [constructs an empty (invalid) handle]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section `template< typename F > handle( F const&, context const&)`]
+[variablelist
+[[Effects:] [constructs an handle associated with an future and an context]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section `bool interruption_requested()`]
+[variablelist
+[[Effects:] [checks if interruption is already requested]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section `void interrupt()`]
+[variablelist
+[[Effects:] [requests task interruption; doesn not block (immediatly returns)]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section `void interrupt_and_wait()`]
+[variablelist
+[[Effects:] [requests task interruption and blocks until worker-thread stops task]]
+[[Throws:] [`boost::thread_resource_error`]]
+]
+[endsect]
+
+[section `bool interrupt_and_wait_until( system_time const&)`]
+[variablelist
+[[Effects:] [requests task interruption and blocks until worker-thread stops task or time-point elapsed]]
+[[Returns:] [false if the the time specified by abs_time was reached, true otherwise]]
+[[Throws:] [`boost::thread_resource_error`]]
+]
+[endsect]
+
+[section `template< typename TimeDuration > interrupt_and_wait_for( TimeDuration const&)`]
+[variablelist
+[[Effects:] [requests task interruption and blocks until worker-thread stops task or time-duration elapsed]]
+[[Returns:] [false if the the time specified by rel_time was reached, true otherwise]]
+[[Throws:] [`boost::thread_resource_error`]]
+]
+[endsect]
+
+[section `R get()`]
+[variablelist
+[[Effects:] [requests the result]]
+[[Throws:] [`boost::task::task_interrupted`, `boost::task::task_uninialized`, `boost::task::task_rejected`, `boost::task::broken_task`]]
+]
+[endsect]
+
+[section `void wait()`]
+[variablelist
+[[Effects:] [blocks caller until task is done]]
+[[Throws:] [`boost::task::task_interrupted`, `boost::task::task_uninialized`, `boost::task::task_rejected`, `boost::task::broken_task`]]
+]
+[endsect]
+
+[section `template< typename TimeDuration > wait_for( TimeDuration const&)`]
+[variablelist
+[[Effects:] [blocks caller until task is done]]
+[[Throws:] [`boost::task::task_interrupted`, `boost::task::task_uninialized`, `boost::task::task_rejected`, `boost::task::broken_task`]]
+]
+[endsect]
+
+[section `bool wait_until( system_time const& abs_time) const`]
+[variablelist
+[[Effects:] [blocks caller until task is done]]
+[[Throws:] [`boost::task::task_interrupted`, `boost::task::task_uninialized`, `boost::task::task_rejected`, `boost::task::broken_task`]]
+]
+[endsect]
+
+[section `bool is_ready()`]
+[variablelist
+[[Effects:] [checks if task is done]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section `bool has_value()`]
+[variablelist
+[[Effects:] [checks if task is done and a result value is set]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section `bool has_exception()`]
+[variablelist
+[[Effects:] [checks if task is done and an exception is set]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section `void swap( handle< R > & other)`]
+[variablelist
+[[Effects:] [swapps handle]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section Non-member function `wait_for_all()`]
+
+ template< typename Iterator >
+ void waitfor_all( Iterator begin, Iterator end);
+
+ template< typename T1, typename T2 >
+ void waitfor_all( T1 & t1, T2 & t2);
+ ...
+ template< typename T1, typename T2, typename T3, typename T4, typename T5 >
+ void waitfor_all( handle< T1 > & t1, handle< T2 > & t2, handle< T3 > & t3, handle< T4 > & t4, handle< T5 > & t5);
+
+[variablelist
+[[Effects:] [waits for all handles to become ready]]
+[[Throws:] [`boost::task::task_interrupted`, `boost::task::task_rejected`]]
+]
+[endsect]
+
+[endsect]
+
+[endsect]

Added: sandbox/task/libs/task/doc/async_execution.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/async_execution.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,106 @@
+[/ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:async_execution Asynchronous Execution]
+
+[heading Synopsis]
+
+In order to execute a task it has to be passed to function __fn_async__. The task is store inside
+the __ep__ (may be given as an additional argument to __fn_async__) and will by means of __ep__.
+
+
+[section:async Non-member function `async()`]
+
+Function __fn_async__ applies the moved __task__ to the __ep__ which executes the __task__ (for this purpose __ep__ is
+required to provide `handle< R > operator()( task< R > && t)`).
+The function returns a __handle__ which controls the submitted __task__.
+
+ long fibonacci( long n)
+ {
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ long k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ long tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ return k1;
+ }
+
+ void main()
+ {
+ // task computing fibonacci(10)
+ // move the task to executor
+ boost::tasks::handle< long > h1(
+ boost::tasks::async(
+ boost::tasks::make_task( fibonacci, 10) ) );
+
+ // task computing fibonacci(5)
+ boost::task< long > t( fibonacci, 5);
+ // move the task to executor
+ boost::tasks::handle< long > h2(
+ boost::tasks::async(
+ boost::move( t) ) );
+
+ // access the results
+ std::cout << "fibonacci(10) == " << h1.get() << std::endl;
+ std::cout << "fibonacci(5) == " << h2.get() << std::endl;
+ }
+
+
+[section:async Non-member function `template< typename R, typename EP > async( task< R >, EP)`]
+
+ #include <boost/task/async.hpp>
+
+ template< typename R, typename EP >
+ handle< R > async( task< R > t, EP ep);
+
+[variablelist
+[[Effects:] [moves task to an asyncrounous executer and returns a handle associated with the task]]
+[[Throws:] [`boost::thread_resource_error`]]
+]
+
+[endsect]
+
+
+[section:async1 Non-member function `template< typename R, typename Channel > async( task< R >, pool< Channel > &)`]
+
+ #include <boost/task/async.hpp>
+
+ template< typename R, typename Channel >
+ handle< R > async( task< R > t, pool< Channel > & ep);
+
+[variablelist
+[[Effects:] [moves task into a thread-pool and returns a handle associated with the task]]
+[[Throws:] [`boost::tasks::task_rejected`]]
+]
+
+[endsect]
+
+
+[section:async2 Non-member function `template< typename R, typename Channel, typename Attr > async( task< R >, Attr, pool< Channel > &)`]
+
+ #include <boost/task/async.hpp>
+
+ template< typename R, typename Channel, typename Attr >
+ handle< R > async( task< R > t, Attr attr, pool< Channel > & ep);
+
+[variablelist
+[[Effects:] [moves attributed task into a thread-pool and returns a handle associated with the task]]
+[[Throws:] [`boost::tasks::task_rejected`]]
+]
+
+[endsect]
+
+[endsect]
+
+[include async_completion_token.qbk]
+[include execution_policies.qbk]
+
+[endsect]

Added: sandbox/task/libs/task/doc/execution_policies.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/execution_policies.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,21 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:execution_policy Execution Policies]
+
+In contrast to synchronous methods asynchronous methods do not block the program flow when a time consuming operation is executed.
+The application continues executing the current context and when the result of the asynchronous method is required the __act__ can be used.
+
+A __ep__ describes how a __task__ gets asynchronously executed and provides a __act__ to manage the __task__.
+
+[include own_thread.qbk]
+[include new_thread.qbk]
+[include as_sub_task.qbk]
+[include threadpool.qbk]
+
+[endsect]

Added: sandbox/task/libs/task/doc/fork_join.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/fork_join.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,78 @@
+/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:forkjoin Fork/Join]
+
+Fork/Join algorithms are recursive divide-and-conquer algorithms which repeatedly splitt into sub-tasks until they become small
+enough to solve using simple, short sequential methods, so that they run in parallel on multiple cores.
+
+The fork operation creates new __sub_tasks__ which can run in parallel. The current __task__ is not proceeded in the join operation
+until the forked __sub_tasks__ have completed. In the meantime the __worker_thread__ executes other tasks from its local __worker_queue__.
+
+``
+ long serial_fib( long n)
+ {
+ if( n < 2) return n;
+ else return serial_fib( n - 1) + serial_fib( n - 2);
+ }
+
+ long parallel_fib( long n, long cutof)
+ {
+ if ( n < cutof) return serial_fib( n);
+ else
+ {
+ // fork sub-task by moving the task
+ // ownership to the thread-pool
+ // sub-task computes fibonacci(n-1)
+ h1 = boost::task::async(
+ boost::task::make_task(
+ parallel_fib,
+ n - 1,
+ cutof) );
+
+ // fork sub-task by moving the task
+ // ownership to the thread-pool
+ // sub-task computes fibonacci(n-2)
+ h2 = boost::task::async(
+ boost::task::make_task(
+ parallel_fib,
+ n - 2,
+ cutof) );
+
+ // join the results of both sub-tasks
+ // if one of the both sub-tasks is not ready
+ // the worker-thread does not block, it executes other
+ // task from its local-queue
+ return h1.get() + h2.get();
+ }
+ }
+
+ void main()
+ {
+ boost::task::static_pool< boost::task::unbounded_fifo > pool( boost::task::poolsize( 5) );
+
+ // compute fibonacci-number 10
+ // for numbers < 5 do inline calculation
+ boost::task::task< long > t(
+ parallel_fib,
+ 10,
+ 5);
+
+ // move task ownership to thread-pool
+ boost::task::handle< long > h(
+ boost::task::async(
+ boost::move( t),
+ pool) );
+
+ // access result
+ std::cout << "fibonacci(10) == " << h.get() << std::endl;
+ }
+``
+
+
+[endsect]

Added: sandbox/task/libs/task/doc/handle.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/handle.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,333 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:handle Class template `handle`]
+
+[heading Synopsis]
+
+__handle__ represents an __act__. It will be returned by __async__ and is associated with the submitted __task__.
+
+ long fibonacci( long n)
+ {
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ long k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ long tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ return k1;
+ }
+
+ void main()
+ {
+ // create task
+ boost::tasks::task< long > t( fibonacci, 10);
+
+ // move task ownership to executor
+ boost::tasks::handle< long > h(
+ boost::tasks::async(
+ boost::move( t),
+ boost::tasks::new_thread() ) );
+
+ std::cout << "is ready == " << std::boolalpha << h.is_ready() << "\n";
+
+ // wait for task completion
+ h.wait();
+
+ std::cout << "has value == " << std::boolalpha << h.has_value() << "\n";
+ std::cout << "has exception == " << std::boolalpha << h.has_exception() << "\n";
+
+ // return result
+ std::cout << "fibonacci(10) == " << h.get() << std::endl;
+ }
+
+[heading Interruption]
+
+Each invokation of __fn_async__ returns an __handle__ which allows to control the associated __task__ (passed to __fn_async__). This includes
+the ability to interrupt an __task__ if it is cooperative. Cooperative means that the __task__ contains __interruption_points__ or checks for
+interruption requests [footnote see [@http://www.ddj.com/architect/207100682 'Interrupt Politely'], Herb Sutter].
+
+* __fn_interrupt__: interrupt __task__ and return immediately
+
+* __fn_interrupt_and_wait__: interrupt and wait until __task__ was removed from __worker_thread__
+
+* __fn_interrupt_and_wait_for__: interrupt and wait until __task__ was removed from __worker_thread__ or time duration has elapsed
+
+* __fn_interrupt_and_wait_until__: interrupt and wait until __task__ was removed from __worker_thread__ or time point has reached
+
+* __fn_interruption_requested__: return bool if interruption was requested
+
+ long cooperative( long n)
+ {
+ boost::this_thread::interruption_point(); // interruption point
+
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ long k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ if ( boost::this_thread::interruption_requested() ) // check if interruption was requested
+ return;
+
+ long tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+
+ boost::this_thread::interruption_point(); // interruption point
+
+ return k1;
+ }
+
+ void main()
+ {
+ // task, to be executed asynchronously
+ boost::tasks::task< long > t( cooperative, 10);
+
+ // move task to async. executor
+ boost::tasks::handle< long > h(
+ boost::tasks::async(
+ boost::move( t),
+ boost::tasks::new_thread() ) );
+
+ // interrupt task and wait until task is removed by worker-thread
+ h.interrupt_and_wait();
+
+ std::cout << "is ready == " << std::boolalpha << h.is_ready() << "\n";
+ std::cout << "has value == " << std::boolalpha << h.has_value() << "\n";
+ std::cout << "has exception == " << std::boolalpha << h.has_exception() << "\n";
+
+ // access result
+ // throws boost::tasks::task_interrupted
+ std::cout << h.get() << std::endl;
+ }
+
+[note If the task is still pending (not executed yet) when an interruption is requested - the task is not removed from the queue, it is marked to be interrupted instead.]
+
+
+[heading Completion]
+
+__boost_task__ provides function __waitfor_all__ waits for all handles passed to this function to become ready
+
+ void main()
+ {
+ std::vector handles< boost::tasks::handle< long > > results;
+ results.reserve( 10);
+
+ for ( int i = 0; i < 10; ++i)
+ {
+ boost::tasks::task< long > t( fibonacci, i);
+
+ results.push_back(
+ boost::tasks::async(
+ boost::move( t) ) );
+ }
+
+ // wait until all tasks are ready
+ boost::tasks::waitfor_all( results.begin(), results.end() );
+
+ int k = 0;
+ std::vector< boost::tasks::handle< long > >::iterator e( results.end() );
+ for (
+ std::vector< boost::tasks::handle< long > >::iterator i( results.begin() );
+ i != e;
+ ++i)
+ std::cout << "fibonacci(" << k++ << ") == " << i->get() << std::endl;
+ }
+
+[section:handle Class template `handle`]
+
+ #include <boost/task/handle.hpp>
+
+ template< typename R >
+ class handle
+ {
+ handle();
+
+ template< typename F >
+ handle( F const&, context const&);
+
+ void interrupt();
+ void interrupt_and_wait();
+ void interrupt_and_wait_until( system_time const& abs_time);
+ template< typename TimeDuration >
+ void interrupt_and_wait_for( Duration const& rel_time);
+ bool interruption_requested();
+
+ R get();
+ bool is_ready() const;
+ bool has_value() const;
+ bool has_exception() const;
+ void wait() const;
+ bool wait_until( system_time const& abs_time);
+ template< typename TimeDuration >
+ bool wait_for( TimeDuration const& rel_time);
+
+ void swap( handle< R > & other);
+ };
+
+ 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, typename T4, typename T5 >
+ friend void waitfor_all( handle< T1 > & t1, handle< T2 > & t2, handle< T3 > & t3, handle< T4 > & t4, handle< T5 > & t5);
+
+[section `handle()`]
+[variablelist
+[[Effects:] [constructs an empty (invalid) handle]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section `template< typename F > handle( F const&, context const&)`]
+[variablelist
+[[Effects:] [constructs an handle associated with an future and an context]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section `bool interruption_requested()`]
+[variablelist
+[[Effects:] [checks if interruption is already requested]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section `void interrupt()`]
+[variablelist
+[[Effects:] [requests task interruption; doesn not block (immediatly returns)]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section `void interrupt_and_wait()`]
+[variablelist
+[[Effects:] [requests task interruption and blocks until worker-thread stops task]]
+[[Throws:] [`boost::thread_resource_error`]]
+]
+[endsect]
+
+[section `bool interrupt_and_wait_until( system_time const&)`]
+[variablelist
+[[Effects:] [requests task interruption and blocks until worker-thread stops task or time-point elapsed]]
+[[Returns:] [false if the the time specified by abs_time was reached, true otherwise]]
+[[Throws:] [`boost::thread_resource_error`]]
+]
+[endsect]
+
+[section `template< typename TimeDuration > interrupt_and_wait_for( TimeDuration const&)`]
+[variablelist
+[[Effects:] [requests task interruption and blocks until worker-thread stops task or time-duration elapsed]]
+[[Returns:] [false if the the time specified by rel_time was reached, true otherwise]]
+[[Throws:] [`boost::thread_resource_error`]]
+]
+[endsect]
+
+[section `R get()`]
+[variablelist
+[[Effects:] [requests the result]]
+[[Throws:] [`boost::task::task_interrupted`, `boost::task::task_uninialized`, `boost::task::task_rejected`, `boost::task::broken_task`]]
+]
+[endsect]
+
+[section `void wait()`]
+[variablelist
+[[Effects:] [blocks caller until task is done]]
+[[Throws:] [`boost::task::task_interrupted`, `boost::task::task_uninialized`, `boost::task::task_rejected`, `boost::task::broken_task`]]
+]
+[endsect]
+
+[section `template< typename TimeDuration > wait_for( TimeDuration const&)`]
+[variablelist
+[[Effects:] [blocks caller until task is done]]
+[[Throws:] [`boost::task::task_interrupted`, `boost::task::task_uninialized`, `boost::task::task_rejected`, `boost::task::broken_task`]]
+]
+[endsect]
+
+[section `bool wait_until( system_time const& abs_time) const`]
+[variablelist
+[[Effects:] [blocks caller until task is done]]
+[[Throws:] [`boost::task::task_interrupted`, `boost::task::task_uninialized`, `boost::task::task_rejected`, `boost::task::broken_task`]]
+]
+[endsect]
+
+[section `bool is_ready()`]
+[variablelist
+[[Effects:] [checks if task is done]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[heading Member function `has_value()`]
+
+ bool has_value()
+
+[variablelist
+[[Effects:] [checks if task is done and a result value is set]]
+[[Throws:] [Nothing]]
+]
+
+
+[heading Member function `has_exception()`]
+
+ bool has_exception()
+
+[variablelist
+[[Effects:] [checks if task is done and an exception is set]]
+[[Throws:] [Nothing]]
+]
+
+
+[heading Member function `get_future()`]
+
+ shared_future< R > & get_future()
+
+[variablelist
+[[Effects:] [returns a reference to the internal shared_future< R >]]
+[[Throws:] [Nothing]]
+]
+
+
+[heading Member function `swap()`]
+
+ void swap( handle< R > & other)
+
+[variablelist
+[[Effects:] [swapps handle]]
+[[Throws:] [Nothing]]
+]
+
+
+[section Non-member function `wait_for_all()`]
+
+ template< typename Iterator >
+ void waitfor_all( Iterator begin, Iterator end);
+
+ template< typename T1, typename T2 >
+ void waitfor_all( T1 & t1, T2 & t2);
+
+ ...
+
+ template< typename T1, typename T2, typename T3, typename T4, typename T5 >
+ void waitfor_all( handle< T1 > & t1, handle< T2 > & t2, handle< T3 > & t3, handle< T4 > & t4, handle< T5 > & t5);
+
+[variablelist
+[[Effects:] [waits for all handles to become ready]]
+[[Throws:] [`boost::task::task_interrupted`, `boost::task::task_rejected`]]
+]
+[endsect]
+
+[endsect]
+
+[endsect]

Added: sandbox/task/libs/task/doc/meta_functions.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/meta_functions.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,60 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:meta_functions Meta functions]
+
+If the __thread_pool__ supports attributes (like priorities) __has_attribute__ evaluates to `true` at compile-time (derived from
+boost::mpl::bool_). The type of the attribute is determined by __attribute_type__.
+
+ // thread-pool with priority scheduling
+ // type of priority is int
+ typdef boost::task::static_pool< boost::task::unbounded_priority< int > > pool_type;
+
+ // test if thread-pool supports priorities at compile time
+ std::cout << std::boolalpha << boost::task::has_attribute< pool_type >::value << "\n";
+
+ // access the type used for priority
+ std::cout << typeid( boost::task::attribute_type< pool_type >::type).name() << std::endl;
+
+[section:has_attribute Meta function `has_attribute`]
+
+ #include <boost/task/meta.hpp>
+
+ template< typename Pool >
+ struct has_attribute : public mpl::bool_<
+ is_same<
+ detail::has_priority,
+ typename Pool::scheduler_type::priority_tag_type
+ >::value
+ >
+ {};
+
+[variablelist
+[[Effects:] [returns true if Pool supports attributes (priority-scheduling)]]
+[[Throws:] [nothing]]
+]
+[endsect]
+
+
+[section:attribute_type Meta function `attribute_type`]
+
+ #include <boost/task/meta.hpp>
+
+ template< typename Pool >
+ struct attribute_type
+ {
+ typedef typename Pool::scheduler_type::attribute_type type;
+ };
+
+[variablelist
+[[Effects:] [returns type of attribute]]
+[[Throws:] [nothing]]
+]
+[endsect]
+
+[endsect]

Added: sandbox/task/libs/task/doc/new_thread.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/new_thread.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,86 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:new_thread Execute in Separat Thread]
+
+[heading Synopsis]
+
+__new_thread__ creates a new thread and executes the task in this thread (asynchronous). The created thread gets
+joined by handle.
+The returned __handle__ joins the thread in its destructor (if the last reference gets out of scope).
+
+ long fibonacci( long n)
+ {
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ long k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ long tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ return k1;
+ }
+
+ void main()
+ {
+ boost::task::task< long > t( fibonacci, 10);
+
+ boost::task::handle< long > h(
+ boost::task::async(
+ boost::move( t),
+ boost::task::new_thread() ) );
+
+ std::cout << "fibonacci(10) == " << h.get() << std::endl;
+ }
+
+
+[caution Always store the returned __act__ in a variable because __handle__ joins the thread in its destructor (if the last
+reference gets out of scope). ]
+
+
+In the example below both `a_function()` and `another_function()` are executed synchron because the returned __handle__ is not stored in
+a variable. Thatswhy the __worker_thread__ is joined after return from __fn_async__!
+
+ boost::task::task< void > t1( a_function);
+ boost::task::task< void > t2( another_function);
+
+ // handles are not retrieved
+ // both task executed in sequence
+ boost::task::async(
+ boost::move( t1),
+ boost::task::new_thread() ) );
+ boost::task::async(
+ boost::move( t2),
+ boost::task::new_thread() ) );
+
+
+[section:new_thread Class `new_thread`]
+
+ #include <boost/task/async.hpp>
+
+ struct new_thread
+ {
+ template< typename R >
+ handle< R > operator()( task< R >);
+ };
+
+
+[section `template< typename R > handle< R > operator()( task< R > t)`]
+[variablelist
+[[Effects:] [moves task in a new thread an returns an handle associated with the task]]
+[[Throws:] [`boost::thread_resource_error`]]
+]
+[endsect]
+
+[endsect]
+
+[endsect]
+
+

Added: sandbox/task/libs/task/doc/overview.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/overview.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,138 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:overview Overview]
+
+__boost_task__ provides a framework for asynchronous execution of tasks (small units of code that can be executed independently and parallel).
+
+* __task__, a __callable__ representing a fine-grained __work_item__:
+ * support of task synchron. via primitives like conditions, barriers, event-variables and channels (message exchange)
+ without blocking worker-thread in the __thread_pool__
+
+* __handle__, works as a __act__ associated with a task:
+ * __fn_interrupt__, __fn_interrupt_and_wait__, ... allow to cancel an cooperative task
+ * __fn_get__ retrieve value or exception of task execution
+ * __fn_is_ready__ test if task was executed
+ * __fn_wait__, __fn_wait_for__ and __fn_wait_until__ block until task is executed and the result is set
+ * functions __waitfor_all__ to wait for all handles
+
+* __async__, executes a task by means of __eps__
+ * executes task in current thread
+ * executes task in a newly created thread (thread will be destroyed after completion)
+ * task gets executed by a __worker_thread__ of a custom __thread_pool__ (for instance with priority or smart scheduling)
+ * executes task in newly created thread or in a pool of __worker_threads__ depending on whether the parent-task is already executed in a __thread_pool__
+
+* __thread_pools__ with __work_stealing__ algorithm and __fork_join__ semantics
+
+
+In order to use the classes and functions described here, you can either include the specific headers specified by the descriptions of each class or function,
+or include the master library header:
+
+ #include <boost/task.hpp>
+
+which includes all the other headers in turn.
+
+Used namespaces are:
+
+ namespace boost::tasks
+ namespace boost::this_task
+
+
+[heading Example]
+
+
+ long fibonacci( long n)
+ {
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ long k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ long tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ return k1;
+ }
+
+ void main()
+ {
+ // create a thread-pool
+ boost::tasks::static_pool< boost::tasks::unbounded_fifo > > pool( boost::tasks::poolsize( 5) );
+
+ // execute tasks in thread-pool
+ // move tasks ownership to executor
+ boost::tasks::handle< long > h1(
+ boost::tasks::async(
+ boost::tasks::make_task( fibonacci, 10),
+ pool);
+ boost::tasks::handle< long > h2(
+ boost::tasks::async(
+ boost::tasks::make_task( fibonacci, 5),
+ boost::move( t2),
+ pool);
+
+ std::cout << "h1: is ready == " << std::boolalpha << h1.is_ready() << "\n";
+ std::cout << "h2: is ready == " << std::boolalpha << h2.is_ready() << "\n";
+
+ // wait for completion of both tasks
+ boost::tasks::waitfor_all( h1, h2);
+
+ std::cout << "h1: is ready == " << std::boolalpha << h1.is_ready() << "\n";
+ std::cout << "h2: is ready == " << std::boolalpha << h2.is_ready() << "\n";
+ std::cout << "h1: has value == " << std::boolalpha << h1.has_value() << "\n";
+ std::cout << "h2: has value == " << std::boolalpha << h2.has_value() << "\n";
+ std::cout << "h1: has exception == " << std::boolalpha << h1.has_exception() << "\n";
+ std::cout << "h2: has exception == " << std::boolalpha << h2.has_exception() << "\n";
+
+ // get results
+ std::cout << "fibonacci(10) == " << h1.get() << std::endl;
+ std::cout << "fibonacci(5) == " << h2.get() << std::endl;
+ }
+
+
+[heading References]
+
+* [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2185.html N2185]: Proposed Text for Parallel Task Execution, written by Peter Dimov.
+
+* [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2276.html N2276]: Thread Pools and Futures, written by Anthony Williams.
+
+* [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2802.html N2802]: A plea to reconsider detach-on-destruction for thread objects, written by Hans-J. Boehm.
+
+* [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2880.html N2880]: C++ object lifetime interactions with the threads API, written by Hans-J. Boehm and Lawrence Crowl.
+
+* [@http://herbsutter.wordpress.com 'Sutter’s Mill'] by Herb Sutter
+
+* mailing list of C++ standard committee's Library Working Group
+
+[warning This library is NOT an official Boost library]
+
+[note Please note that __boost_task__ is not optimized yet.]
+
+__boost_task__ depends uppon __boost_atomic__, __boost_move__ and __boost_fiber__.
+
+
+[heading Tested Platforms]
+
+__boost_task__ has been tested on the following platforms and compilers:
+
+* Debian GNU/Linux 2.6.31.6 (x86_64), GCC 4.3.4
+* Ubuntu GNU/Linux 2.6.28.11 (x86), GCC 4.3.3
+* FreeBSD 8.0 (x86), GCC 4.2.1
+* OpenSolaris 2009.06 (x86_64), GCC 4.3.2
+* Windows XP Professional (x86), MSVC 9.0
+
+
+[heading How to build and install]
+
+* download the sources from
+[@http://www.boost-consulting.com/vault/index.php?directory=Concurrent%20Programming Boost Vault]
+* extract the archive into the boost-source directory
+* call [''bjam toolset=<compiler-name> --with-task install'] in order to build and install the library
+
+[endsect]

Added: sandbox/task/libs/task/doc/own_thread.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/own_thread.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,62 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:own_thread Execute in Current Thread]
+
+[heading Synopsis]
+
+__own_thread__ executes the task in the current thread (synchronous execution).
+
+ long fibonacci( long n)
+ {
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ long k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ long tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ return k1;
+ }
+
+ void main()
+ {
+ boost::task::task< long > t( fibonacci, 10);
+
+ boost::task::handle< long > h(
+ boost::task::async(
+ boost::move( t),
+ boost::task::own_thread() ) );
+
+ std::cout << "fibonacci(10) == " << h.get() << std::endl;
+ }
+
+
+[section:own_thread Class `own_thread`]
+
+ #include <boost/task/async.hpp>
+
+ struct own_thread
+ {
+ template< typename R >
+ handle< R > operator()( task< R > t);
+ };
+
+[section `template< typename R > handle< R > operator()( task< R > t)`]
+[variablelist
+[[Effects:] [moves task in the current thread an returns an handle associated with the task]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[endsect]
+
+[endsect]
+

Added: sandbox/task/libs/task/doc/processor_binding.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/processor_binding.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,30 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:processor_binding Processor binding]
+
+For some applications it is convenient to bind the __worker_threads__ to processors/cores of the system. For this purpose __fn_bind_to_processors__ must
+be given to constructor instead __pool_size__ so that a __worker_thread__ is created an bound the the core.
+
+``
+ typedef boost::task::static_pool<
+ boost::task::unbounded_queue< boost::tp::fifo >
+ > pool_type;
+
+ // constructs thread-pool with worker-threads as
+ // CPUs/Cores are available on the system
+ pool_type pool( pool_type::bind_to_processors() );
+``
+
+The constructor takes additional arguments for the [link_work_stealing work-stealing algorithm] and [link_queue high-] and [link_queue low-watermark] too.
+
+[note __boost_task__ does provide this feature only for Windows, Linux, AIX, HP-UX, Solaris and FreeBSD.]
+
+
+[endsect]
+

Added: sandbox/task/libs/task/doc/queue.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/queue.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,118 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:queue Global Queue]
+
+A __queue__ synchronizes the access between application threads and __worker_threads__ and implements policies for limitating the amount of queued tasks and how those tasks are scheduled ( first-in-first-out, priority ordering etc.)
+
+
+[heading Bounded Queues]
+
+__bounded_queue__ limits the number of queued (pending) tasks in order to prevent resource exhaustion.
+For this purpose a high- and low-watermark has to be passed at construction.
+__hwm__ sets the maximum of pending tasks. If this limited is reached all threads which submit a task will be set to sleep (blocked). If it is equal to __lwm__ everytime a
+sleeping producer thread will be woken up and puts its task if one worker thread has taken a task from the queue.
+__lwm__ sets the threshold when blocked threads get woken up. If it is less than __hwm__ all sleeping producer threads will be woken up if
+the amount of pending tasks reaches __lwm__.
+
+
+[heading Unbounded Queues]
+
+__unbounded_queue__ allows ann unlimited number of tasks to be queued.
+The insertion of an __task__ will never block. If the queue becomes empty __worker_threads__ will be set to sleep until new tasks are enqueued.
+
+
+[heading Task Scheduling]
+
+For scheduling of tasks inside the queue following strategies are available:
+
+* fifo: first enqueued task is dequeued first
+
+* priority: the next item dequeued from the queue depends on its associated priority attribute and sorting criterion applied to the queue (template arguments)
+
+ // thread-pool with priority scheduling
+ // tasks with higher priority are
+ // scheduled first
+ boost::task::static_pool< boost::task::unbounded_priority_queue< int > > pool( boost::task::poolsize( 5) );
+
+ boost::task::task< void > t1( some_fn);
+ boost::task::task< void > t2( another_fn);
+
+ // move task t1 with priority 5 to thread-pool
+ boost::task::async(
+ boost::move( t1),
+ 5,
+ pool);
+
+ // move task t2 with priority 3 to thread-pool
+ boost::task::async(
+ boost::move( t2),
+ 3,
+ pool);
+
+
+* smart: enqueue- and dequeue-operations are determined by the template arguments und the task-attribute. The library provides an default let only one kind of task stored inside the queue (gets replaced by new one)
+
+ long fibonacci_fn( long n)
+ {
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ long k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ long tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ return k1;
+ }
+
+ typedef boost::task::static_pool< boost::task::unbounded_smart_queue< int > > pool_type;
+
+ void main()
+ {
+ pool_type pool( boost::task::poolsize( 1) );
+
+ ...
+
+ boost::task::task< long > t1(
+ boost::bind( fibonacci_fn, 10) );
+ boost::task::task< long > t2(
+ boost::bind( fibonacci_fn, 5) );
+
+ // replaced by later task with same attribute == 2
+ // if still pending in pool
+ boost::task::async(
+ boost::move( t1),
+ 2,
+ pool);
+
+ // will replace previous pending task with attribute == 2
+ boost::task::async(
+ boost::move( t2),
+ 2,
+ pool);
+ }
+
+
+__boost_task__ provides following queues:
+
+* bounded_fifo
+
+* bounded_priority_queue< Attr, Comp = std::less< Attr > >
+
+* bounded_smart_queue< Attr, Comp, Enq = detail::replace_oldest, Deq = detail::take_oldest >
+
+
+* unbounded_fifo
+
+* unbounded_priority_queue< Attr, Comp = std::less< Attr > >
+
+* unbounded_smart_queue< Attr, Comp, Enq = detail::replace_oldest, Deq = detail::take_oldest >
+
+[endsect]

Added: sandbox/task/libs/task/doc/scheduler.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/scheduler.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,125 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:scheduling Scheduling]
+
+The scheduling policy determines how tasks are scheduled inside the __queue__.
+
+
+[heading fifo]
+
+First inserted pending __task__ gets taken first.
+
+
+[heading priority]
+
+Each __task__ is submitted to the pool with a priority attribute. The type and ordering of the priority is user-defined.
+
+``
+ // thread-pool with priority scheduling
+ // tasks with higher priority are
+ // scheduled first
+ boost::task::static_pool<
+ boost::task::unbounded_queue<
+ boost::task::priority< int > >
+ > pool( boost::task::poolsize( 5) );
+
+ boost::task::task< void > t1( some_fn);
+ boost::task::task< void > t2( another_fn);
+
+ // move task t1 with priority 5 to thread-pool
+ boost::task::async(
+ boost::move( t1),
+ 5,
+ pool);
+
+ // move task t2 with priority 3 to thread-pool
+ boost::task::async(
+ boost::move( t2),
+ 3,
+ pool);
+``
+
+In this example the tasks get scheduled by the assigned integer (third argument of __fn_async__). The __task__ with the
+lowest priority gets scheduled first (taken by a __worker_thread__). The ordering can be changed by the second argument
+of __priority__ (the default is `std::greater< Attr >`).
+
+``
+ // thread-pool with priority scheduling
+ // tasks with lower priority are
+ // scheduled first
+ boost::task::static_pool<
+ boost::task::unbounded_queue<
+ boost::task::priority< int, std::less< int > >
+ >
+ > pool( boost::task::poolsize( 5) );
+``
+
+
+[heading smart]
+
+Each inserted __task__ is associated with an attribute. The scheduler gets an put- and take-policy as template arguments.
+The corresponding policy gets applied for each insertion and removal.
+
+__boost_task__ provides __replace_oldest__ as put- policy and __take_oldest__ as take-policy. Both policies allow the
+replacement of older (pending) tasks in the scheduler by new ones.
+
+``
+ long fibonacci_fn( long n)
+ {
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ long k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ long tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ return k1;
+ }
+
+ typedef boost::task::static_pool<
+ boost::task::unbounded_queue<
+ boost::task::smart<
+ int,
+ std::less< int >,
+ boost::task::replace_oldest,
+ boost::task::take_oldest
+ >
+ >
+ > pool_type;
+
+ void main()
+ {
+ pool_type pool( boost::task::poolsize( 1) );
+
+ ...
+
+ boost::task::task< long > t1(
+ boost::bind( fibonacci_fn, 10) );
+ boost::task::task< long > t2(
+ boost::bind( fibonacci_fn, 5) );
+
+ // replaced by later task with same attribute == 2
+ // if still pending in pool
+ boost::task::async(
+ boost::move( t1),
+ 2,
+ pool);
+
+ // will replace previous pending task with attribute == 2
+ boost::task::async(
+ boost::move( t2),
+ 2,
+ pool);
+ }
+``
+
+
+[endsect]

Added: sandbox/task/libs/task/doc/shutdown.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/shutdown.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,106 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:pool_shutdown Shutdown]
+
+__boost_task__ allows to shutdown a __thread_pool__ explicitly via functions __fn_shutdown__ and __fn_shutdown_now__. The
+destructor of the pool calls __fn_shutdown__ if not already done so that all __worker_threads__ are joined.
+
+If __fn_shutdown__ is called - the the pool is set the closed state and all __worker_threads__ are joined until all pending tasks are processed.
+No futher tasks can be submitted.
+
+ long fibonacci_fn( long n)
+ {
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ long k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ long tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ return k1;
+ }
+
+ typedef boost::task::static_pool< boost::task::unbounded_fifo > pool_type;
+
+ void main()
+ {
+ pool_type pool( boost::task::poolsize( 1) );
+
+ ...
+
+ boost::task::task< long > t1( fibonacci_fn, 10);
+ boost::task::task< long > t2( fibonacci_fn, 5);
+
+ boost::task::handle< long > h1(
+ boost::task::async(
+ boost::move( t1),
+ pool) );
+ boost::task::handle< long > h2(
+ boost::task::async(
+ boost::move( t2),
+ pool) );
+
+ // waits until all pending tasks are finished
+ pool.shutdown();
+
+ std::cout << "fibonacci(10) == " << h1.get() << "\n";
+ std::cout << "fibonacci(5) == " << h2.get() << std::endl;
+ }
+
+[note The deconstructor calls __fn_shutdown__ if the pool was not shutdown yet.]
+
+
+The function __fn_shutdown_now__ closes the pool, interrupts and then joins all __worker_threads__. Pending tasks are unprocessed.
+
+ long fibonacci_fn( long n)
+ {
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ long k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ long tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+ return k1;
+ }
+
+ typedef boost::task::static_pool< boost::task::unbounded_fifo > pool_type;
+
+ void main()
+ {
+ pool_type pool( boost::task::poolsize( 1) );
+
+ ...
+
+ boost::task::task< long > t1( fibonacci_fn, 10);
+ boost::task::task< long > t2( fibonacci_fn, 5);
+
+ boost::task::handle< long > h1(
+ boost::task::async(
+ boost::move( t1),
+ pool) );
+ boost::task::handle< long > h2(
+ boost::task::async(
+ boost::move( t2),
+ pool) );
+
+ // requests task interruption and
+ // joins all worker-threads
+ pool.shutdown_now();
+
+ // accessing the result may throw task_interrupted
+ std::cout << "fibonacci(10) == " << h1.get() << "\n";
+ std::cout << "fibonacci(5) == " << h2.get() << std::endl;
+ }
+
+[endsect]

Added: sandbox/task/libs/task/doc/spin_barrier.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/spin_barrier.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,47 @@
+[/
+ (C) Copyright 2007-8 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).
+]
+
+[section:barriers Barriers]
+
+A barrier is a simple concept. Also known as a __rendezvous__, it is a synchronization point between multiple
+contexts of execution. The barrier is configured for a particular number of tasks (`n`), and as
+tasks reach the barrier they must wait until all `n` tasks have arrived. Once the `n`-th task has reached the
+barrier, all the waiting tasks can proceed, and the barrier is reset.
+
+[section:barrier Class `barrier`]
+
+ #include <boost/task/spin/barrier.hpp>
+
+ class barrier
+ {
+ public:
+ barrier( unsigned int initial);
+
+ bool wait();
+ };
+
+Instances of __spin_barrier__ are not copyable or movable.
+
+[section:constructor `barrier( unsigned int initial)`]
+[variablelist
+[[Effects:] [Construct a barrier for `initial` tasks.]]
+[[Throws:] [__invalid_argument__ if an error occurs.]]
+]
+[endsect]
+
+[section:wait `bool wait()`]
+[variablelist
+[[Effects:] [Block until `initial` tasks have called `wait` on `*this`. When the `initial`-th task calls `wait`,
+all waiting tasks are unblocked, and the barrier is reset. ]]
+[[Returns:] [`true` for exactly one task from each batch of waiting tasks, `false` otherwise.]]
+[[Throws:] [__task_error__ if an error occurs.]]
+]
+[endsect]
+
+[endsect]
+
+[endsect]

Added: sandbox/task/libs/task/doc/spin_condition_variables.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/spin_condition_variables.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,199 @@
+[/
+ (C) Copyright 2007-8 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).
+]
+
+[section:conditions Condition Variables]
+
+[heading Synopsis]
+
+The class `condition` provides a mechanism for one task to wait for notification `condition`. When the task is
+woken from the wait, then it checks to see if the appropriate condition is now true, and continues if so. If the
+condition is not true, then the task then calls `wait` again to resume waiting. In the simplest case, this
+condition is just a boolean variable:
+
+ boost::tasks::spin::condition cond;
+ boost::tasks::spin::mutex mtx;
+ bool data_ready;
+
+ void process_data();
+
+ void wait_for_data_to_process()
+ {
+ boost::unique_lock< boost::tasks::spin::mutex > lk( mtx);
+ while ( ! data_ready)
+ {
+ cond.wait( lk);
+ }
+ process_data();
+ }
+
+Notice that the `lk` is passed to `wait`: `wait` will atomically add the task to the set of tasks waiting on the
+condition variable, and unlock the mutex. When the task is woken, the mutex will be locked again before the call
+to `wait` returns. This allows other tasks to acquire the mutex in order to update the shared data, and ensures
+that the data associated with the condition is correctly synchronized.
+
+In the mean time, another task sets the condition to `true`, and then calls either `notify_one` or `notify_all` on
+the condition variable to wake one waiting task or all the waiting tasks respectively.
+
+ void retrieve_data();
+ void prepare_data();
+
+ void prepare_data_for_processing()
+ {
+ retrieve_data();
+ prepare_data();
+ {
+ boost::lock_guard< boost::tasks::spin::mutex > lk( mtx);
+ data_ready = true;
+ }
+ cond.notify_one();
+ }
+
+Note that the same mutex is locked before the shared data is updated, but that the mutex does not have to be locked
+across the call to `notify_one`.
+
+[section:condition Class `condition`]
+
+ #include <boost/task/spin/condition.hpp>
+
+ class condition
+ {
+ public:
+ condition();
+ ~condition();
+
+ void notify_one();
+ void notify_all();
+
+ void wait( boost::unique_lock< boost::tasks::spin::mutex > & lk);
+
+ template< typename Pred >
+ void wait( boost::unique_lock< boost::tasks::spin::mutex > & lk, Pred pred);
+
+ template< typename LockType >
+ void wait( LockType & lk);
+
+ template< typename LockType, typename Pred >
+ void wait( LockType & lk, Pred predicate);
+
+ void timed_wait( boost::unique_lock< boost::tasks::spin::mutex > & lk, system_time const& abs_time);
+
+ template< typename TimeDuration >
+ void timed_wait( boost::unique_lock< boost::tasks::spin::mutex > & lk, TimeDuration const& rel_time);
+
+ template< typename Pred >
+ void timed_wait( boost::unique_lock< boost::tasks::spin::mutex > & lk, system_time const& abs_time, Pred pred);
+
+ template< typename TimeDuration, typename Pred >
+ void timed_wait( boost::unique_lock< boost::tasks::spin::mutex > & lk, TimeDuration const& rel_time, Pred pred);
+
+ template< typename LockType >
+ void timed_wait( LockType & lk, system_time const& abs_time);
+
+ template< typename TimeDuration, typename LockType >
+ void timed_wait( LockType & lk, TimeDuration const& rel_time);
+
+ template< typename LockType, typename Pred >
+ void timed_wait( LockType & lk, system_time const& abs_time, Pred predicate);
+
+ template< typename LockType, typename TimeDuration, typename Pred >
+ void timed_wait( LockType & lk, TimeDuration const& rel_time, Pred predicate);
+ };
+
+[section:constructor `condition()`]
+[variablelist
+[[Effects:] [Constructs an object of class `condition`.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:destructor `~condition()`]
+[variablelist
+[[Precondition:] [All tasks waiting on `*this` have been notified by a call to `notify_one` or `notify_all`
+(though the respective calls to `wait` need not have returned).]]
+[[Effects:] [Destroys the object.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:notify_one `void notify_one()`]
+[variablelist
+[[Effects:] [If any tasks are currently __blocked__ waiting on `*this` in a call to `wait`, unblocks one of
+those tasks.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:notify_all `void notify_all()`]
+[variablelist
+[[Effects:] [If any tasks are currently __blocked__ waiting on `*this` in a call to `wait`, unblocks all of
+those tasks.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:wait `void wait( boost::unique_lock< boost::tasks::spin::mutex > & lk)`]
+[variablelist
+[[Precondition:] [`lk` is locked by the current task, and either no other
+task is currently waiting on `*this`, or the execution of the `mutex()` member
+function on the `lk` objects supplied in the calls to `wait` in all the tasks
+currently waiting on `*this` would return the same value as `lk->mutex()` for
+this call to `wait`.]]
+[[Effects:] [Atomically call `lk.unlock()` and blocks the current task. The
+task will unblock when notified by a call to `this->notify_one()` or
+`this->notify_all()`, or spuriously. When the task is unblocked (for whatever
+reason), the lock is reacquired by invoking `lk.lock()` before the call to
+`wait` returns. The lock is also reacquired by invoking `lk.lock()` if the
+function exits with an exception.]]
+[[Postcondition:] [`lk` is locked by the current task.]]
+[[Throws:] [__task_error__ if an error
+occurs. __task_interrupted__ if the wait was interrupted by a call to
+__interrupt__ on the __task__ object associated with the current task of execution.]]
+]
+[endsect]
+
+[section:wait_predicate `template< typename Pred > void wait( boost::unique_lock< boost::tasks::spin::mutex > & lk, Pred pred)`]
+[variablelist
+[[Effects:] [As-if ``
+while ( ! pred())
+{
+ wait( lk);
+}
+``]]
+
+]
+[endsect]
+
+[section:wait_t `template< typename LockType > void wait( LockType & lk)`]
+[variablelist
+[[Effects:] [Atomically call `lk.unlock()` and blocks the current task. The
+task will unblock when notified by a call to `this->notify_one()` or
+`this->notify_all()`, or spuriously. When the task is unblocked (for whatever
+reason), the lock is reacquired by invoking `lk.lock()` before the call to
+`wait` returns. The lock is also reacquired by invoking `lk.lock()` if the
+function exits with an exception.]]
+[[Postcondition:] [`lk` is locked by the current task.]]
+[[Throws:] [__task_error__ if an error
+occurs. __task_interrupted__ if the wait was interrupted by a call to
+__interrupt__ on the __task__ object associated with the current task of execution.]]
+]
+[endsect]
+
+[section:wait_predicate_t `template< typename LockType, typename Pred > void wait( LockType & lk, Pred pred)`]
+[variablelist
+[[Effects:] [As-if ``
+while ( ! pred())
+{
+ wait( lock);
+}
+``]]
+
+]
+[endsect]
+
+[endsect]
+
+[endsect]

Added: sandbox/task/libs/task/doc/spin_event_variables.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/spin_event_variables.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,289 @@
+[/
+ (C) Copyright 2009 Oliver Kowalke
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+]
+
+[section:eventvar_ref Event Variables]
+
+[heading Synopsis]
+
+__boost_task__ provides event variables to facilitate coordination between tasks.
+A event-variable has two states `set` (`signaled`) or `reset` (`nonsignaled`).
+
+ boost::tasks::spin::auto_reset_event ev;
+
+ void process_data();
+
+ void wait_for_data_to_process()
+ {
+ ev.wait();
+ process_data();
+ }
+
+`wait` will atomically add the task to the set of tasks waiting on the event
+variable. When the task is woken, the event variable will be reset again.
+
+In the mean time, another task signals the event variable by calling
+`set` on the event variable to wake one waiting task.
+
+ void retrieve_data();
+ void prepare_data();
+
+ void prepare_data_for_processing()
+ {
+ retrieve_data();
+ prepare_data();
+ ev.set();
+ }
+
+
+[section:auto_reset_event Class `auto_reset_event`]
+
+[heading Synopsis]
+
+When the ['auto_reset_event] gets signaled, any one task will see this particular signal. When a task observes
+the signal by waiting on the event, it is automatically transitioned back to non-signaled state. Any tasks can
+subsequently set the event.
+
+ #include <boost/task/spin/auto_reset_event.hpp>
+
+ class auto_reset_event : private boost::noncopyable
+ {
+ public:
+ explicit auto_reset_event( bool isset = false);
+
+ ~auto_reset_event();
+
+ void set();
+
+ void wait();
+
+ bool try_wait();
+
+ bool timed_wait( system_time const& abs_time);
+
+ templatey typename TimeDuration >
+ bool timed_wait( TimeDuration const& rel_time);
+ };
+
+[section:constructor `explicit auto_reset_event( bool isset = false)`]
+[variablelist
+[[Effects:] [Constructs an object of class `auto_reset_event`. If isset is `true`
+the variable is set.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:destructor `~auto_reset_event()`]
+[variablelist
+[[Precondition:] [All tasks waiting on `*this` have been notified by a call to
+`set` (though the respective calls to `wait` need not have returned).]]
+[[Effects:] [Destroys the object.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:set `void set()`]
+[variablelist
+[[Effects:] [If any tasks are currently __blocked__ waiting on `*this` in a call
+to `wait`, unblocks one of those tasks.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:wait `void wait()`]
+[variablelist
+[[Effects:] [Blocks the current task. The task will unblock when notified by a call
+to `this->set()`. When the task is unblocked, the variable is reset before `wait`
+returns.]]
+[[Throws:] [__task_interrupted__ if the wait was interrupted by a call to
+__interrupt__ on the __task__ object associated with the current task of execution.]]
+]
+[endsect]
+
+[section:try_wait `bool try_wait()`]
+[variablelist
+[[Effects:] [Returns `true` if the event variable is set otherwise `false`.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[endsect]
+
+
+[section:manual_reset_event Class `manual_reset_event`]
+
+[heading Synopsis]
+
+The ['manual_reset_event] remains signaled until it is manually reset. Multiple tasks
+wait on the same event and observe the same signal.
+
+ #include <boost/task/spin/manual_reset_event.hpp>
+
+ class manual_reset_event : private boost::noncopyable
+ {
+ public:
+ explicit manual_reset_event( bool isset = false);
+
+ ~manual_reset_event();
+
+ void set();
+
+ void reset();
+
+ void wait();
+
+ bool try_wait();
+
+ bool timed_wait( system_time const& abs_time);
+
+ templatey typename TimeDuration >
+ bool timed_wait( TimeDuration const& rel_time);
+ };
+
+[section:constructor `explicit manual_reset_event( bool isset = false)`]
+[variablelist
+[[Effects:] [Constructs an object of class `manual_reset_event`. If isset is `true`
+the variable is set.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:destructor `~manual_reset_event()`]
+[variablelist
+[[Precondition:] [All tasks waiting on `*this` have been notified by a call to
+`set` (though the respective calls to `wait` need not have returned).]]
+[[Effects:] [Destroys the object.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:set `void set()`]
+[variablelist
+[[Effects:] [If any tasks are currently __blocked__ waiting on `*this` in a call
+to `wait`, unblocks those tasks. The variable remains signaled until `this->reset()`
+gets called.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:reset `void reset()`]
+[variablelist
+[[Effects:] [The event variable gets nonsignaled and tasks calling `this->wait()`
+will block.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:wait `void wait()`]
+[variablelist
+[[Effects:] [Blocks the current task. The task will unblock when notified by a call
+to `this->set()`. When the task is unblocked, the variable remains set.]]
+[[Throws:] [__task_interrupted__ if the wait was interrupted by a call to
+__interrupt__ on the __task__ object associated with the current task of execution.]]
+]
+[endsect]
+
+[section:trywait `boo try_wait()`]
+[variablelist
+[[Effects:] [Returns `true` if the event variable is set otherwise `false`.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[endsect]
+
+
+[section:count_down_event Class `count_down_event`]
+
+[heading Synopsis]
+
+The ['count_down_event] decrements an internal counter (set in the constructor) and all
+waiting tasks are blocked until the count reaches zero.
+
+ #include <boost/task/spin/count_down_event.hpp>
+
+ class count_down_event : private boost::noncopyable
+ {
+ public:
+ explicit count_down_event( unsigned int initial);
+
+ ~count_down_event();
+
+ unsigned int initial() const;
+
+ unsigned int current() const;
+
+ bool is_set() const;
+
+ void set();
+
+ void wait();
+
+ bool timed_wait( system_time const& abs_time);
+
+ template< typename TimeDuration >
+ bool timed_wait( TimeDuration const& rel_time);
+ };
+
+[section:constructor `explicit count_down_event( unsigned int initial)`]
+[variablelist
+[[Effects:] [Constructs an object of class `count_down_event` with initial value.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:destructor `~count_down_event()`]
+[variablelist
+[[Precondition:] [All tasks waiting on `*this` have been notified by a call to
+`set` (though the respective calls to `wait` need not have returned).]]
+[[Effects:] [Destroys the object.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:initial `unsigned int initial()`]
+[variablelist
+[[Effects:] [Returns the initial value the event variable was initialized with.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:current `unsigned int current()`]
+[variablelist
+[[Effects:] [Returns the value the variable currently holds.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:is_set `bool is_set()`]
+[variablelist
+[[Effects:] [Returns `true` if the varaible has reached zero.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:set `void set()`]
+[variablelist
+[[Effects:] [Decrements the current count. If the count reaches zero and any tasks are
+currently __blocked__ waiting on `*this` in a call to `wait`, unblocks those tasks.
+The variable remains signaled.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:wait `void wait()`]
+[variablelist
+[[Effects:] [Blocks the current task. The task will unblock when notified by a call
+to `this->set()` and the count of the event variable reaches zero. When the task is
+unblocked, the variable remains set.]]
+[[Throws:] [__task_interrupted__ if the wait was interrupted by a call to
+__interrupt__ on the __task__ object associated with the current task of execution.]]
+]
+[endsect]
+
+[endsect]
+
+[endsect]

Added: sandbox/task/libs/task/doc/spin_fifos.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/spin_fifos.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,206 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+[section:fifos (Un)Bounded fifos]
+
+__boost_task__ provides a bounded and a unbounded fifo suitable to synchonize tasks via message passing.
+
+ typedef boost::tasks::spin::unbounded_channel< int > fifo_t;
+
+ void send( fifo_t fifo)
+ {
+ for ( int i = 0; i < 5; ++i)
+ fifo.put( i);
+ fifo.deactivate();
+ }
+
+ void recv( fifo_t fifo)
+ {
+ boost::optional< int > value;
+ while ( fifo.take( value) )
+ { std::cout << "received " << * value << std::endl; }
+ }
+
+ boost::tasks::scheduler<> sched;
+ fifo_t fifo;
+ sched.make_task( send, fifo);
+ sched.make_task( recv, fifo);
+
+ for (;;)
+ {
+ while ( sched.run() );
+ if ( sched.empty() ) break;
+ }
+
+
+[section:unbounded_channel Class template `unbounded_channel`]
+
+ #include <boost/task/spin/unbounded_channel.hpp>
+
+ template< typename T >
+ class unbounded_channel : private noncopyable
+ {
+ public:
+ unbounded_channel();
+
+ void deactivate();
+
+ bool empty();
+
+ void put( T const& t);
+
+ bool take( boost::optional< T > & va);
+
+ bool take( boost::optional< T > & va, system_time const& abs_time);
+
+ template< typename TimeDuration >
+ bool take( boost::optional< T > & va, TimeDuration const& rel_time);
+
+ bool try_take( boost::optional< T > & va);
+ };
+
+[section:constructor `unbounded_channel()`]
+[variablelist
+[[Effects:] [Constructs an object of class `unbounded_channel`.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:deactivate `void deactivate()`]
+[variablelist
+[[Effects:] [Deactivates the fifo. No values can be put after calling `this->deactivate`. tasks blocked in
+`this->take()` will be return.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:empty `bool empty()`]
+[variablelist
+[[Effects:] [Returns `true` if the fifo currently contains no data.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:put `void put( T const& t)`]
+[variablelist
+[[Effects:] [Enqueues the value in the fifo and wakes up a task waiting for new data available from the
+fifo.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:take `bool take( boost::optional< T > & va)`]
+[variablelist
+[[Effects:] [Dequeues a value from the fifo. If no data is available from the fifo the task gets suspended until
+new data are enqueued (return value `true` and va contains dequeued value) or the fifo gets deactiveted and
+the function returns `false`.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:try_take `bool try_take( boost::optional< T > & va)`]
+[variablelist
+[[Effects:] [Dequeues a value from the fifo. If no data is available from the fifo the function returns `false`.
+Otherwise it returns `true` and `va` contains the dequed value.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[endsect]
+
+
+[section:bounded_channel Class template `bounded_channel`]
+
+ #include <boost/task/spin/bounded_channel.hpp>
+
+ template< typename T >
+ class bounded_channel : private noncopyable
+ {
+ public:
+ bounded_channel( std::size_t wm);
+
+ bounded_channel( std::size_t hwm, std::size_t lwm);
+
+ void deactivate();
+
+ bool empty();
+
+ void put( T const& t);
+
+ void put( T const& t, system_time const& abs_time);
+
+ template< typename TimeDuration >
+ void put( T const& t, TimeDuration const& rel_time);
+
+ bool take( boost::optional< T > & va);
+
+ bool take( boost::optional< T > & va, system_time const& abs_time);
+
+ template< typename TimeDuration >
+ bool take( boost::optional< T > & va, TimeDuration const& rel_time);
+
+ bool try_take( boost::optional< T > & va);
+ };
+
+[section:constructor `bounded_channel( std::size_t wm)`]
+[variablelist
+[[Effects:] [Constructs an object of class `bounded_channel` which will contain a maximum of `wm` items.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:constructor2 `bounded_channel( std::size_t hwm, std::size_t lwm)`]
+[variablelist
+[[Effects:] [Constructs an object of class `bounded_channel` which will contain a maximum of `hwm` items.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:deactivate `void deactivate()`]
+[variablelist
+[[Effects:] [Deactivates the fifo. No values can be put after calling `this->deactivate`. tasks blocked in
+`this->take()` will be return.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:empty `bool empty()`]
+[variablelist
+[[Effects:] [Returns `true` if the fifo currently contains no data.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:put `void put( T const& t)`]
+[variablelist
+[[Effects:] [Enqueues the value in the fifo and wakes up a task waiting for new data available from the
+fifo. If the watermark has reached the task putting the value will be supended until at least one item
+was dequeued.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:take `bool take( boost::optional< T > & va)`]
+[variablelist
+[[Effects:] [Dequeues a value from the fifo. If no data is available from the fifo the task gets suspended until
+new data are enqueued (return value `true` and va contains dequeued value) or the fifo gets deactiveted and
+the function returns `false`.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[section:try_take `bool try_take( boost::optional< T > & va)`]
+[variablelist
+[[Effects:] [Dequeues a value from the fifo. If no data is available from the fifo the function returns `false`.
+Otherwise it returns `true` and `va` contains the dequed value.]]
+[[Throws:] [Nothing.]]
+]
+[endsect]
+
+[endsect]
+
+[endsect]

Added: sandbox/task/libs/task/doc/spin_future_ref.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/spin_future_ref.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,928 @@
+[/
+ (C) Copyright 2008-9 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).
+]
+
+[section:reference Futures Reference]
+
+[section:future_state `state` enum]
+
+ namespace future_state
+ {
+ enum state {uninitialized, waiting, ready};
+ }
+
+[endsect]
+
+[section:unique_future `unique_future` class template]
+
+ template <typename R>
+ class unique_future
+ {
+ unique_future(unique_future & rhs);// = delete;
+ unique_future& operator=(unique_future& rhs);// = delete;
+
+ public:
+ typedef future_state::state state;
+
+ unique_future();
+ ~unique_future();
+
+ // move support
+ unique_future(unique_future && other);
+ unique_future& operator=(unique_future && other);
+
+ void swap(unique_future& other);
+
+ // retrieving the value
+ R&& get();
+
+ // functions to check state
+ state get_state() const;
+ bool is_ready() const;
+ bool has_exception() const;
+ bool has_value() const;
+
+ // waiting for the result to be ready
+ void wait() const;
+ template<typename Duration>
+ bool timed_wait(Duration const& rel_time) const;
+ bool timed_wait_until(boost::system_time const& abs_time) const;
+ };
+
+[section:default_constructor Default Constructor]
+
+ unique_future();
+
+[variablelist
+
+[[Effects:] [Constructs an uninitialized future.]]
+
+[[Postconditions:] [[unique_future_is_ready_link `this->is_ready`] returns `false`. [unique_future_get_state_link
+`this->get_state()`] returns __uninitialized__.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:destructor Destructor]
+
+ ~unique_future();
+
+[variablelist
+
+[[Effects:] [Destroys `*this`.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:move_constructor Move Constructor]
+
+ unique_future(unique_future && other);
+
+[variablelist
+
+[[Effects:] [Constructs a new future, and transfers ownership of the asynchronous result associated with `other` to `*this`.]]
+
+[[Postconditions:] [[unique_future_get_state_link `this->get_state()`] returns the value of `other->get_state()` prior to the
+call. `other->get_state()` returns __uninitialized__. If `other` was associated with an asynchronous result, that result is now
+associated with `*this`. `other` is not associated with any asynchronous result.]]
+
+[[Throws:] [Nothing.]]
+
+[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
+
+]
+
+[endsect]
+
+[section:move_assignment Move Assignment Operator]
+
+ unique_future& operator=(unique_future && other);
+
+[variablelist
+
+[[Effects:] [Transfers ownership of the asynchronous result associated with `other` to `*this`.]]
+
+[[Postconditions:] [[unique_future_get_state_link `this->get_state()`] returns the value of `other->get_state()` prior to the
+call. `other->get_state()` returns __uninitialized__. If `other` was associated with an asynchronous result, that result is now
+associated with `*this`. `other` is not associated with any asynchronous result. If `*this` was associated with an asynchronous
+result prior to the call, that result no longer has an associated __unique_future__ instance.]]
+
+[[Throws:] [Nothing.]]
+
+[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
+
+]
+
+[endsect]
+
+[section:swap Member function `swap()`]
+
+ void swap(unique_future & other);
+
+[variablelist
+
+[[Effects:] [Swaps ownership of the asynchronous results associated with `other` and `*this`.]]
+
+[[Postconditions:] [[unique_future_get_state_link `this->get_state()`] returns the value of `other->get_state()` prior to the
+call. `other->get_state()` returns the value of `this->get_state()` prior to the call. If `other` was associated with an
+asynchronous result, that result is now associated with `*this`, otherwise `*this` has no associated result. If `*this` was
+associated with an asynchronous result, that result is now associated with `other`, otherwise `other` has no associated result.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+
+[section:get Member function `get()`]
+
+ R&& get();
+ R& unique_future<R&>::get();
+ void unique_future<void>::get();
+
+[variablelist
+
+[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready as-if by a call to
+__unique_future_wait__, and retrieves the result (whether that is a value or an exception).]]
+
+[[Returns:] [If the result type `R` is a reference, returns the stored reference. If `R` is `void`, there is no return
+value. Otherwise, returns an rvalue-reference to the value stored in the asynchronous result.]]
+
+[[Postconditions:] [[unique_future_is_ready_link `this->is_ready()`] returns `true`. [unique_future_get_state_link
+`this->get_state()`] returns __ready__.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
+associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception stored in the
+asynchronous result in place of a value.]]
+
+[[Notes:] [`get()` is an ['interruption point].]]
+
+]
+
+[endsect]
+
+[section:wait Member function `wait()`]
+
+ void wait();
+
+[variablelist
+
+[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready. If the result is not ready on
+entry, and the result has a ['wait callback] set, that callback is invoked prior to waiting.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
+associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
+['wait callback] if such a callback is called.]]
+
+[[Postconditions:] [[unique_future_is_ready_link `this->is_ready()`] returns `true`. [unique_future_get_state_link
+`this->get_state()`] returns __ready__.]]
+
+[[Notes:] [`wait()` is an ['interruption point].]]
+
+]
+
+[endsect]
+
+[section:timed_wait_duration Member function `timed_wait()`]
+
+ template<typename Duration>
+ bool timed_wait(Duration const& wait_duration);
+
+[variablelist
+
+[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time specified by
+`wait_duration` has elapsed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is
+invoked prior to waiting.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready before the specified time has
+elapsed, `false` otherwise.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
+associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
+['wait callback] if such a callback is called.]]
+
+[[Postconditions:] [If this call returned `true`, then [unique_future_is_ready_link `this->is_ready()`] returns `true` and
+[unique_future_get_state_link `this->get_state()`] returns __ready__.]]
+
+[[Notes:] [`timed_wait()` is an ['interruption point]. `Duration` must be a type that meets the Boost.DateTime time duration requirements.]]
+
+]
+
+[endsect]
+
+[section:timed_wait_absolute Member function `timed_wait()`]
+
+ bool timed_wait(boost::system_time const& wait_timeout);
+
+[variablelist
+
+[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time point specified by
+`wait_timeout` has passed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is invoked
+prior to waiting.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready before the specified time has
+passed, `false` otherwise.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
+associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
+['wait callback] if such a callback is called.]]
+
+[[Postconditions:] [If this call returned `true`, then [unique_future_is_ready_link `this->is_ready()`] returns `true` and
+[unique_future_get_state_link `this->get_state()`] returns __ready__.]]
+
+[[Notes:] [`timed_wait()` is an ['interruption point].]]
+
+]
+
+[endsect]
+
+
+[section:is_ready Member function `is_ready()`]
+
+ bool is_ready();
+
+[variablelist
+
+[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready for retrieval, `false`
+otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:has_value Member function `has_value()`]
+
+ bool has_value();
+
+[variablelist
+
+[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with a value rather than an exception.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
+stored value, `false` otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:has_exception Member function `has_exception()`]
+
+ bool has_exception();
+
+[variablelist
+
+[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with an exception rather than a value.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
+stored exception, `false` otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:get_state Member function `get_state()`]
+
+ future_state::state get_state();
+
+[variablelist
+
+[[Effects:] [Determine the state of the asynchronous result associated with `*this`, if any.]]
+
+[[Returns:] [__uninitialized__ if `*this` is not associated with an asynchronous result. __ready__ if the asynchronous result
+associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+
+[endsect]
+
+[section:shared_future `shared_future` class template]
+
+ template <typename R>
+ class shared_future
+ {
+ public:
+ typedef future_state::state state;
+
+ shared_future();
+ ~shared_future();
+
+ // copy support
+ shared_future(shared_future const& other);
+ shared_future& operator=(shared_future const& other);
+
+ // move support
+ shared_future(shared_future && other);
+ shared_future(unique_future<R> && other);
+ shared_future& operator=(shared_future && other);
+ shared_future& operator=(unique_future<R> && other);
+
+ void swap(shared_future& other);
+
+ // retrieving the value
+ R get();
+
+ // functions to check state, and wait for ready
+ state get_state() const;
+ bool is_ready() const;
+ bool has_exception() const;
+ bool has_value() const;
+
+ // waiting for the result to be ready
+ void wait() const;
+ template<typename Duration>
+ bool timed_wait(Duration const& rel_time) const;
+ bool timed_wait_until(boost::system_time const& abs_time) const;
+ };
+
+[section:default_constructor Default Constructor]
+
+ shared_future();
+
+[variablelist
+
+[[Effects:] [Constructs an uninitialized future.]]
+
+[[Postconditions:] [[shared_future_is_ready_link `this->is_ready`] returns `false`. [shared_future_get_state_link
+`this->get_state()`] returns __uninitialized__.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:get Member function `get()`]
+
+ const R& get();
+
+[variablelist
+
+[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready as-if by a call to
+__shared_future_wait__, and returns a `const` reference to the result.]]
+
+[[Returns:] [If the result type `R` is a reference, returns the stored reference. If `R` is `void`, there is no return
+value. Otherwise, returns a `const` reference to the value stored in the asynchronous result.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the
+result associated with `*this` is not ready at the point of the call, and the current thread is interrupted.]]
+
+[[Notes:] [`get()` is an ['interruption point].]]
+
+]
+
+[endsect]
+
+[section:wait Member function `wait()`]
+
+ void wait();
+
+[variablelist
+
+[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready. If the result is not ready on
+entry, and the result has a ['wait callback] set, that callback is invoked prior to waiting.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
+associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
+['wait callback] if such a callback is called.]]
+
+[[Postconditions:] [[shared_future_is_ready_link `this->is_ready()`] returns `true`. [shared_future_get_state_link
+`this->get_state()`] returns __ready__.]]
+
+[[Notes:] [`wait()` is an ['interruption point].]]
+
+]
+
+[endsect]
+
+[section:timed_wait_duration Member function `timed_wait()`]
+
+ template<typename Duration>
+ bool timed_wait(Duration const& wait_duration);
+
+[variablelist
+
+[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time specified by
+`wait_duration` has elapsed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is
+invoked prior to waiting.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready before the specified time has
+elapsed, `false` otherwise.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
+associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
+['wait callback] if such a callback is called.]]
+
+[[Postconditions:] [If this call returned `true`, then [shared_future_is_ready_link `this->is_ready()`] returns `true` and
+[shared_future_get_state_link `this->get_state()`] returns __ready__.]]
+
+[[Notes:] [`timed_wait()` is an ['interruption point]. `Duration` must be a type that meets the Boost.DateTime time duration requirements.]]
+
+]
+
+[endsect]
+
+[section:timed_wait_absolute Member function `timed_wait()`]
+
+ bool timed_wait(boost::system_time const& wait_timeout);
+
+[variablelist
+
+[[Effects:] [If `*this` is associated with an asynchronous result, waits until the result is ready, or the time point specified by
+`wait_timeout` has passed. If the result is not ready on entry, and the result has a ['wait callback] set, that callback is invoked
+prior to waiting.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready before the specified time has
+passed, `false` otherwise.]]
+
+[[Throws:] [__future_uninitialized__ if `*this` is not associated with an asynchronous result. __thread_interrupted__ if the result
+associated with `*this` is not ready at the point of the call, and the current thread is interrupted. Any exception thrown by the
+['wait callback] if such a callback is called.]]
+
+[[Postconditions:] [If this call returned `true`, then [shared_future_is_ready_link `this->is_ready()`] returns `true` and
+[shared_future_get_state_link `this->get_state()`] returns __ready__.]]
+
+[[Notes:] [`timed_wait()` is an ['interruption point].]]
+
+]
+
+[endsect]
+
+[section:is_ready Member function `is_ready()`]
+
+ bool is_ready();
+
+[variablelist
+
+[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, and that result is ready for retrieval, `false`
+otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:has_value Member function `has_value()`]
+
+ bool has_value();
+
+[variablelist
+
+[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with a value rather than an exception.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
+stored value, `false` otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:has_exception Member function `has_exception()`]
+
+ bool has_exception();
+
+[variablelist
+
+[[Effects:] [Checks to see if the asynchronous result associated with `*this` is set with an exception rather than a value.]]
+
+[[Returns:] [`true` if `*this` is associated with an asynchronous result, that result is ready for retrieval, and the result is a
+stored exception, `false` otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:get_state Member function `get_state()`]
+
+ future_state::state get_state();
+
+[variablelist
+
+[[Effects:] [Determine the state of the asynchronous result associated with `*this`, if any.]]
+
+[[Returns:] [__uninitialized__ if `*this` is not associated with an asynchronous result. __ready__ if the asynchronous result
+associated with `*this` is ready for retrieval, __waiting__ otherwise.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+
+[endsect]
+
+[section:promise `promise` class template]
+
+ template <typename R>
+ class promise
+ {
+ promise(promise & rhs);// = delete;
+ promise & operator=(promise & rhs);// = delete;
+ public:
+ // template <class Allocator> explicit promise(Allocator a);
+
+ promise();
+ ~promise();
+
+ // Move support
+ promise(promise && rhs);
+ promise & operator=(promise&& rhs);
+
+ void swap(promise& other);
+ // Result retrieval
+ unique_future<R> get_future();
+
+ // Set the value
+ void set_value(R& r);
+ void set_value(R&& r);
+ void set_exception(boost::exception_ptr e);
+
+ template<typename F>
+ void set_wait_callback(F f);
+ };
+
+[section:default_constructor Default Constructor]
+
+ promise();
+
+[variablelist
+
+[[Effects:] [Constructs a new __promise__ with no associated result.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:move_constructor Move Constructor]
+
+ promise(promise && other);
+
+[variablelist
+
+[[Effects:] [Constructs a new __promise__, and transfers ownership of the result associated with `other` to `*this`, leaving `other`
+with no associated result.]]
+
+[[Throws:] [Nothing.]]
+
+[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
+
+]
+
+[endsect]
+
+[section:move_assignment Move Assignment Operator]
+
+ promise& operator=(promise && other);
+
+[variablelist
+
+[[Effects:] [Transfers ownership of the result associated with `other` to `*this`, leaving `other` with no associated result. If there
+was already a result associated with `*this`, and that result was not ['ready], sets any futures associated with that result to
+['ready] with a __broken_promise__ exception as the result. ]]
+
+[[Throws:] [Nothing.]]
+
+[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
+
+]
+
+[endsect]
+
+[section:destructor Destructor]
+
+ ~promise();
+
+[variablelist
+
+[[Effects:] [Destroys `*this`. If there was a result associated with `*this`, and that result is not ['ready], sets any futures
+associated with that task to ['ready] with a __broken_promise__ exception as the result.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:get_future Member Function `get_future()`]
+
+ unique_future<R> get_future();
+
+[variablelist
+
+[[Effects:] [If `*this` was not associated with a result, allocate storage for a new asynchronous result and associate it with
+`*this`. Returns a __unique_future__ associated with the result associated with `*this`. ]]
+
+[[Throws:] [__future_already_retrieved__ if the future associated with the task has already been retrieved. `std::bad_alloc` if any
+memory necessary could not be allocated.]]
+
+]
+
+[endsect]
+
+[section:set_value Member Function `set_value()`]
+
+ void set_value(R&& r);
+ void set_value(const R& r);
+ void promise<R&>::set_value(R& r);
+ void promise<void>::set_value();
+
+[variablelist
+
+[[Effects:] [If `*this` was not associated with a result, allocate storage for a new asynchronous result and associate it with
+`*this`. Store the value `r` in the asynchronous result associated with `*this`. Any threads blocked waiting for the asynchronous
+result are woken.]]
+
+[[Postconditions:] [All futures waiting on the asynchronous result are ['ready] and __unique_future_has_value__ or
+__shared_future_has_value__ for those futures shall return `true`.]]
+
+[[Throws:] [__promise_already_satisfied__ if the result associated with `*this` is already ['ready]. `std::bad_alloc` if the memory
+required for storage of the result cannot be allocated. Any exception thrown by the copy or move-constructor of `R`.]]
+
+]
+
+[endsect]
+
+[section:set_exception Member Function `set_exception()`]
+
+ void set_exception(boost::exception_ptr e);
+
+[variablelist
+
+[[Effects:] [If `*this` was not associated with a result, allocate storage for a new asynchronous result and associate it with
+`*this`. Store the exception `e` in the asynchronous result associated with `*this`. Any threads blocked waiting for the asynchronous
+result are woken.]]
+
+[[Postconditions:] [All futures waiting on the asynchronous result are ['ready] and __unique_future_has_exception__ or
+__shared_future_has_exception__ for those futures shall return `true`.]]
+
+[[Throws:] [__promise_already_satisfied__ if the result associated with `*this` is already ['ready]. `std::bad_alloc` if the memory
+required for storage of the result cannot be allocated.]]
+
+]
+
+[endsect]
+
+[section:set_wait_callback Member Function `set_wait_callback()`]
+
+ template<typename F>
+ void set_wait_callback(F f);
+
+[variablelist
+
+[[Preconditions:] [The expression `f(t)` where `t` is a lvalue of type __packaged_task__ shall be well-formed. Invoking a copy of
+`f` shall have the same effect as invoking `f`]]
+
+[[Effects:] [Store a copy of `f` with the asynchronous result associated with `*this` as a ['wait callback]. This will replace any
+existing wait callback store alongside that result. If a thread subsequently calls one of the wait functions on a __unique_future__
+or __shared_future__ associated with this result, and the result is not ['ready], `f(*this)` shall be invoked.]]
+
+[[Throws:] [`std::bad_alloc` if memory cannot be allocated for the required storage.]]
+
+]
+
+[endsect]
+
+[endsect]
+
+[section:packaged_task `packaged_task` class template]
+
+ template<typename R>
+ class packaged_task
+ {
+ packaged_task(packaged_task&);// = delete;
+ packaged_task& operator=(packaged_task&);// = delete;
+
+ public:
+ // construction and destruction
+ template <class F>
+ explicit packaged_task(F const& f);
+
+ explicit packaged_task(R(*f)());
+
+ template <class F>
+ explicit packaged_task(F&& f);
+
+ // 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()
+ {}
+
+ // move support
+ packaged_task(packaged_task&& other);
+ packaged_task& operator=(packaged_task&& other);
+
+ void swap(packaged_task& other);
+ // result retrieval
+ unique_future<R> get_future();
+
+ // execution
+ void operator()();
+
+ template<typename F>
+ void set_wait_callback(F f);
+ };
+
+[section:task_constructor Task Constructor]
+
+ template<typename F>
+ packaged_task(F const &f);
+
+ packaged_task(R(*f)());
+
+ template<typename F>
+ packaged_task(F&&f);
+
+[variablelist
+
+[[Preconditions:] [`f()` is a valid expression with a return type convertible to `R`. Invoking a copy of `f` shall behave the same
+as invoking `f`.]]
+
+[[Effects:] [Constructs a new __packaged_task__ with a copy of `f` stored as the associated task.]]
+
+[[Throws:] [Any exceptions thrown by the copy (or move) constructor of `f`. `std::bad_alloc` if memory for the internal data
+structures could not be allocated.]]
+
+]
+
+[endsect]
+
+[section:move_constructor Move Constructor]
+
+ packaged_task(packaged_task && other);
+
+[variablelist
+
+[[Effects:] [Constructs a new __packaged_task__, and transfers ownership of the task associated with `other` to `*this`, leaving `other`
+with no associated task.]]
+
+[[Throws:] [Nothing.]]
+
+[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
+
+]
+
+[endsect]
+
+[section:move_assignment Move Assignment Operator]
+
+ packaged_task& operator=(packaged_task && other);
+
+[variablelist
+
+[[Effects:] [Transfers ownership of the task associated with `other` to `*this`, leaving `other` with no associated task. If there
+was already a task associated with `*this`, and that task has not been invoked, sets any futures associated with that task to
+['ready] with a __broken_promise__ exception as the result. ]]
+
+[[Throws:] [Nothing.]]
+
+[[Notes:] [If the compiler does not support rvalue-references, this is implemented using the boost.thread move emulation.]]
+
+]
+
+[endsect]
+
+[section:destructor Destructor]
+
+ ~packaged_task();
+
+[variablelist
+
+[[Effects:] [Destroys `*this`. If there was a task associated with `*this`, and that task has not been invoked, sets any futures
+associated with that task to ['ready] with a __broken_promise__ exception as the result.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:get_future Member Function `get_future()`]
+
+ unique_future<R> get_future();
+
+[variablelist
+
+[[Effects:] [Returns a __unique_future__ associated with the result of the task associated with `*this`. ]]
+
+[[Throws:] [__task_moved__ if ownership of the task associated with `*this` has been moved to another instance of
+__packaged_task__. __future_already_retrieved__ if the future associated with the task has already been retrieved.]]
+
+]
+
+[endsect]
+
+[section:call_operator Member Function `operator()()`]
+
+ void operator()();
+
+[variablelist
+
+[[Effects:] [Invoke the task associated with `*this` and store the result in the corresponding future. If the task returns normally,
+the return value is stored as the asynchronous result, otherwise the exception thrown is stored. Any threads blocked waiting for the
+asynchronous result associated with this task are woken.]]
+
+[[Postconditions:] [All futures waiting on the asynchronous result are ['ready]]]
+
+[[Throws:] [__task_moved__ if ownership of the task associated with `*this` has been moved to another instance of
+__packaged_task__. __task_already_started__ if the task has already been invoked.]]
+
+]
+
+[endsect]
+
+[section:set_wait_callback Member Function `set_wait_callback()`]
+
+ template<typename F>
+ void set_wait_callback(F f);
+
+[variablelist
+
+[[Preconditions:] [The expression `f(t)` where `t` is a lvalue of type __packaged_task__ shall be well-formed. Invoking a copy of
+`f` shall have the same effect as invoking `f`]]
+
+[[Effects:] [Store a copy of `f` with the task associated with `*this` as a ['wait callback]. This will replace any existing wait
+callback store alongside that task. If a thread subsequently calls one of the wait functions on a __unique_future__ or
+__shared_future__ associated with this task, and the result of the task is not ['ready], `f(*this)` shall be invoked.]]
+
+[[Throws:] [__task_moved__ if ownership of the task associated with `*this` has been moved to another instance of
+__packaged_task__.]]
+
+]
+
+[endsect]
+
+
+[endsect]
+
+[section:wait_for_all Non-member function `wait_for_all()`]
+
+ template<typename Iterator>
+ void wait_for_all(Iterator begin,Iterator end);
+
+ template<typename F1,typename F2>
+ void wait_for_all(F1& f1,F2& f2);
+
+ template<typename F1,typename F2,typename F3>
+ void wait_for_all(F1& f1,F2& f2,F3& f3);
+
+ template<typename F1,typename F2,typename F3,typename F4>
+ void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4);
+
+ 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);
+
+[variablelist
+
+[[Preconditions:] [The types `Fn` shall be specializations of
+__unique_future__ or __shared_future__, and `Iterator` shall be a
+forward iterator with a `value_type` which is a specialization of
+__unique_future__ or __shared_future__.]]
+
+[[Effects:] [Waits until all of the specified futures are ['ready].]]
+
+[[Throws:] [Any exceptions thrown by a call to `wait()` on the specified futures.]]
+
+[[Notes:] [`wait_for_all()` is an ['interruption point].]]
+
+]
+
+
+[endsect]
+
+
+[endsect]

Added: sandbox/task/libs/task/doc/spin_futures.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/spin_futures.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,181 @@
+[/
+ (C) Copyright 2008-9 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).
+]
+
+[section:futures Futures]
+
+[template future_state_link[link_text] [link task.spin_synchronization.futures.reference.future_state [link_text]]]
+[def __uninitialized__ [future_state_link `boost::future_state::uninitialized`]]
+[def __ready__ [future_state_link `boost::future_state::ready`]]
+[def __waiting__ [future_state_link `boost::future_state::waiting`]]
+
+[def __future_uninitialized__ `boost::future_uninitialized`]
+[def __broken_promise__ `boost::broken_promise`]
+[def __future_already_retrieved__ `boost::future_already_retrieved`]
+[def __task_moved__ `boost::task_moved`]
+[def __task_already_started__ `boost::task_already_started`]
+[def __promise_already_satisfied__ `boost::promise_already_satisfied`]
+
+[def __task_interrupted__ `boost::task_interrupted`]
+
+
+[template unique_future_link[link_text] [link task.spin_synchronization.futures.reference.unique_future [link_text]]]
+[def __unique_future__ [unique_future_link `boost::unique_future`]]
+
+[template unique_future_get_link[link_text] [link task.spin_synchronization.futures.reference.unique_future.get [link_text]]]
+[def __unique_future_get__ [unique_future_get_link `boost::unique_future<R>::get()`]]
+
+[template unique_future_wait_link[link_text] [link task.spin_synchronization.futures.reference.unique_future.wait [link_text]]]
+[def __unique_future_wait__ [unique_future_wait_link `boost::unique_future<R>::wait()`]]
+
+[template unique_future_is_ready_link[link_text] [link task.spin_synchronization.futures.reference.unique_future.is_ready [link_text]]]
+[def __unique_future_is_ready__ [unique_future_is_ready_link `boost::unique_future<R>::is_ready()`]]
+
+[template unique_future_has_value_link[link_text] [link task.spin_synchronization.futures.reference.unique_future.has_value [link_text]]]
+[def __unique_future_has_value__ [unique_future_has_value_link `boost::unique_future<R>::has_value()`]]
+
+[template unique_future_has_exception_link[link_text] [link task.spin_synchronization.futures.reference.unique_future.has_exception [link_text]]]
+[def __unique_future_has_exception__ [unique_future_has_exception_link `boost::unique_future<R>::has_exception()`]]
+
+[template unique_future_get_state_link[link_text] [link task.spin_synchronization.futures.reference.unique_future.get_state [link_text]]]
+[def __unique_future_get_state__ [unique_future_get_state_link `boost::unique_future<R>::get_state()`]]
+
+[template shared_future_link[link_text] [link task.spin_synchronization.futures.reference.shared_future [link_text]]]
+[def __shared_future__ [shared_future_link `boost::shared_future`]]
+
+[template shared_future_get_link[link_text] [link task.spin_synchronization.futures.reference.shared_future.get [link_text]]]
+[def __shared_future_get__ [shared_future_get_link `boost::shared_future<R>::get()`]]
+
+[template shared_future_wait_link[link_text] [link task.spin_synchronization.futures.reference.shared_future.wait [link_text]]]
+[def __shared_future_wait__ [shared_future_wait_link `boost::shared_future<R>::wait()`]]
+
+[template shared_future_is_ready_link[link_text] [link task.spin_synchronization.futures.reference.shared_future.is_ready [link_text]]]
+[def __shared_future_is_ready__ [shared_future_is_ready_link `boost::shared_future<R>::is_ready()`]]
+
+[template shared_future_has_value_link[link_text] [link task.spin_synchronization.futures.reference.shared_future.has_value [link_text]]]
+[def __shared_future_has_value__ [shared_future_has_value_link `boost::shared_future<R>::has_value()`]]
+
+[template shared_future_has_exception_link[link_text] [link task.spin_synchronization.futures.reference.shared_future.has_exception [link_text]]]
+[def __shared_future_has_exception__ [shared_future_has_exception_link `boost::shared_future<R>::has_exception()`]]
+
+[template shared_future_get_state_link[link_text] [link task.spin_synchronization.futures.reference.shared_future.get_state [link_text]]]
+[def __shared_future_get_state__ [shared_future_get_state_link `boost::shared_future<R>::get_state()`]]
+
+[template promise_link[link_text] [link task.spin_synchronization.futures.reference.promise [link_text]]]
+[def __promise__ [promise_link `boost::promise`]]
+
+[template packaged_task_link[link_text] [link task.spin_synchronization.futures.reference.packaged_task [link_text]]]
+[def __packaged_task__ [packaged_task_link `boost::packaged_task`]]
+[/
+[template wait_for_any_link[link_text] [link task.spin_synchronization.futures.reference.wait_for_any [link_text]]]
+[def __wait_for_any__ [wait_for_any_link `boost::wait_for_any()`]]
+]
+[template wait_for_all_link[link_text] [link task.spin_synchronization.futures.reference.wait_for_all [link_text]]]
+[def __wait_for_all__ [wait_for_all_link `boost::wait_for_all()`]]
+
+
+[section:overview Overview]
+
+The futures library provides a means of handling synchronous future values, whether those values are generated by another task, or
+on a single task in response to external stimuli, or on-demand.
+
+This is done through the provision of four class templates: __unique_future__ and __shared_future__ which are used to retrieve the
+asynchronous results, and __promise__ and __packaged_task__ which are used to generate the asynchronous results.
+
+An instance of __unique_future__ holds the one and only reference to a result. Ownership can be transferred between instances using
+the move constructor or move-assignment operator, but at most one instance holds a reference to a given asynchronous result. When
+the result is ready, it is returned from __unique_future_get__ by rvalue-reference to allow the result to be moved or copied as
+appropriate for the type.
+
+On the other hand, many instances of __shared_future__ may reference the same result. Instances can be freely copied and assigned,
+and __shared_future_get__ returns a `const` reference so that multiple calls to __shared_future_get__ are safe. You can move an
+instance of __unique_future__ into an instance of __shared_future__, thus transferring ownership of the associated asynchronous
+result, but not vice-versa.
+
+You can wait for futures either individually or with one of the __wait_for_any__ and __wait_for_all__ functions.
+
+[endsect]
+
+[section:creating Creating asynchronous values]
+
+You can set the value in a future with either a __promise__ or a __packaged_task__. A __packaged_task__ is a callable object that
+wraps a function or callable object. When the packaged task is invoked, it invokes the contained function in turn, and populates a
+future with the return value. This is an answer to the perennial question: "how do I return a value from a task?": package the
+function you wish to run as a __packaged_task__ and pass the packaged task to the task constructor. The future retrieved from the
+packaged task can then be used to obtain the return value. If the function throws an exception, that is stored in the future in
+place of the return value.
+
+ int calculate_the_answer_to_life_the_universe_and_everything()
+ { return 42; }
+
+ boost::tasks::spin::packaged_task< int > pt( calculate_the_answer_to_life_the_universe_and_everything);
+ boost::tasks::spin::unique_future< int > fi( pt.get_future() );
+
+ boost::task task( boost::move( pt) ); // launch task on a task
+
+ fi.wait(); // wait for it to finish
+
+ assert( fi.is_ready() );
+ assert( fi.has_value() );
+ assert( ! fi.has_exception() );
+ assert( fi.get_state() == boost::future_state::ready);
+ assert( fi.get() == 42);
+
+
+A __promise__ is a bit more low level: it just provides explicit functions to store a value or an exception in the associated
+future. A promise can therefore be used where the value may come from more than one possible source, or where a single operation may
+produce multiple values.
+
+ boost::tasks::spin::promise< int > pi;
+ boost::tasks::spin::unique_future< int > fi;
+ fi = pi.get_future();
+
+ pi.set_value( 42);
+
+ assert( fi.is_ready() );
+ assert( fi.has_value() );
+ assert( ! fi.has_exception() );
+ assert( fi.get_state() == boost::future_state::ready);
+ assert( fi.get() == 42);
+
+[endsect]
+
+[section:lazy_futures Wait Callbacks and Lazy Futures]
+
+Both __promise__ and __packaged_task__ support ['wait callbacks] that are invoked when a task blocks in a call to `wait()` or
+`timed_wait()` on a future that is waiting for the result from the __promise__ or __packaged_task__, in the task that is doing the
+waiting. These can be set using the `set_wait_callback()` member function on the __promise__ or __packaged_task__ in question.
+
+This allows ['lazy futures] where the result is not actually computed until it is needed by some task. In the example below, the
+call to `f.get()` invokes the callback `invoke_lazy_task`, which runs the task to set the value. If you remove the call to
+`f.get()`, the task is not ever run.
+
+ int calculate_the_answer_to_life_the_universe_and_everything()
+ { return 42; }
+
+ void invoke_lazy_task( boost::tasks::spin::packaged_task< int > & task)
+ {
+ try
+ { task(); }
+ catch( boost::task_already_started const&)
+ {}
+ }
+
+ int main()
+ {
+ boost::tasks::spin::packaged_task< int > task( calculate_the_answer_to_life_the_universe_and_everything);
+ task.set_wait_callback( invoke_lazy_task);
+ boost::tasks::spin::unique_future< int > f( task.get_future() );
+
+ assert( f.get() == 42);
+ }
+
+
+[endsect]
+
+[include spin_future_ref.qbk]
+
+[endsect]

Added: sandbox/task/libs/task/doc/spin_mutexes.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/spin_mutexes.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,43 @@
+[/
+ (C) Copyright 2007-8 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).
+]
+
+[section:mutex_types Mutex Types]
+
+[section:mutex Class `mutex`]
+
+ #include <boost/tasks/spin/mutex.hpp>
+
+ class mutex : private boost::noncopyable
+ {
+ public:
+ mutex();
+ ~mutex();
+
+ void lock();
+
+ bool timed_lock( system_time const& abs_time);
+
+ template< typename TimeDuration >
+ bool timed_lock( TimeDuration const& rel_time);
+
+ bool try_lock();
+
+ void unlock();
+
+ typedef unique_lock< mutex > scoped_lock;
+ };
+
+__spin_mutex__ implements the __lockable_concept__ to provide an exclusive-ownership mutex. At most one task can own the
+lock on a given instance of __spin_mutex__ at any time. Multiple concurrent calls to __lock__, __try_lock__ and
+__unlock__ shall be permitted.
+
+[note __spin_mutex__ is ['not] bound to a __scheduler__ and can only be used by tasks
+managed by different schedulers or code not running in a task.]
+
+[endsect]
+
+[endsect]

Added: sandbox/task/libs/task/doc/spin_synchronization.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/spin_synchronization.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,18 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+[section:spin_synchronization Synchronization]
+
+Synch. objects using spin-wait ops. reside in namespace `boost::tasks::spin`.
+
+[include spin_mutexes.qbk]
+[include spin_condition_variables.qbk]
+[include spin_barrier.qbk]
+[include spin_event_variables.qbk]
+[include spin_fifos.qbk]
+[include spin_futures.qbk]
+[endsect]

Added: sandbox/task/libs/task/doc/static_pool.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/static_pool.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,301 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:static_pool Thread-Pool with fixed ]
+
+__boost_task__ provides __static_pool__ - which contains an fixed set of pre-forked __worker_threads__ (the size of the pool doesn't change during its lifetime).
+__static_pool__ supports move semantics.
+
+ boost::task::_static_pool< // pool type
+ boost::task::unbounded_fifo // queue where application threads enqueue tasks
+ > pool(
+ boost::task::poolsize( 6), // pool with 6 pre-forked worker-threads
+ boost::posix_time::posix_time::milliseconds( 50), // time to sleep if no work-item available
+ boost::task::scanns( 10) ); // iterations over local-queues before sleep
+
+
+The first argument of the constructor specifies how many __worker_threads__ the pool will contain. The second
+and third argument are used by the [link_work_stealing __work_stealing__] algorithm.
+
+[note If __bounded_queue__ is used as queuing policy the constructor has two additional arguments . ]
+
+__static_pool__ provides functionality to check the status of the pool - __fn_closed__ returns true when the pool was
+shutdown and __fn_size__returns the number of __worker_threads__.
+
+[section:static_pool Class template `static_pool`]
+
+ #include <boost/task/static_pool.hpp>
+
+ template< typename Channel >
+ class static_pool : private noncopyable
+ {
+ public:
+ static_pool();
+
+ explicit static_pool(
+ poolsize const& psize,
+ posix_time::time_duration const& asleep = posix_time::microseconds( 10),
+ scanns const& scns = scanns( 20) );
+
+ explicit static_pool(
+ poolsize const& psize,
+ high_watermark const& hwm,
+ low_watermark const& lwm,
+ posix_time::time_duration const& asleep = posix_time::milliseconds( 100),
+ scanns const& scns = scanns( 20) );
+
+ static_pool( static_pool &&);
+
+ static_pool & operator=( static_pool &&);
+
+ # if defined(BOOST_HAS_PROCESSOR_BINDINGS)
+ explicit static_pool(
+ <<unspec-type>>,
+ posix_time::time_duration const& asleep = posix_time::microseconds( 10),
+ scanns const& scns = scanns( 20) );
+
+ explicit static_pool(
+ <<unspec-type>>,
+ high_watermark const& hwm,
+ low_watermark const& lwm,
+ posix_time::time_duration const& asleep = posix_time::milliseconds( 100),
+ scanns const& scns = scanns( 20) );
+
+ static <<unspec-type>> bind_to_processors();
+ # endif
+
+ ~static_pool();
+
+ std::size_t size();
+
+ void shutdown();
+ void shutdown_now();
+
+ bool closed();
+
+ void interrupt_all_worker();
+
+ const std::size_t upper_bound();
+ void upper_bound( high_watermark const& hwm);
+ const std::size_t lower_bound();
+ void lower_bound( low_watermark const& lwm);
+
+ template< typename R >
+ handle< R > submit( task< R > && t);
+
+ template< typename R, typename Attr >
+ handle< R > submit( task< R > && t, Attr const& attr);
+
+ void swap( static_pool & other);
+
+ operator unspecified_bool_type() const;
+ bool operator!() const;
+ };
+
+
+[section `static_pool()`]
+[variablelist
+[[Effects:] [constructs an unitialized pool]]
+[[Throws:] [nothing]]
+]
+[endsect]
+
+[section `explicit static_pool(
+ <<unspec-type>>,
+ posix_time::time_duration const& asleep = posix_time::microseconds( 10),
+ scanns const& scns = scanns( 20) )`]
+[variablelist
+[[Preconditions:] [operating system provides functionality for processor binding]]
+[[Effects:] [constructs a pool - for each processor a worker-thread is created and bound to one processor - global-queue can queue an unlimited number of tasks]]
+[[Throws:] [`boost::thread_resource_error`, `boost::task::invalid_scanns`, `boost::task::invalid_timeduration`]]
+[[Notes:] [constructor has to be called if a unbounded-queue is used and `bind_to_processors()` must be set as first argument]]
+]
+[endsect]
+
+[section `explicit static_pool(
+ poolsize const& psize,
+ posix_time::time_duration const& asleep = posix_time::microseconds( 10),
+ scanns const& scns = scanns( 20) )`]
+[variablelist
+[[Effects:] [constructs a pool containing psize worker-threads - global-queue can queue an unlimited number of tasks]]
+[[Throws:] [`boost::thread_resource_error`, `boost::task::invalid_scanns`, `boost::task::invalid_timeduration`]]
+[[Notes:] [constructor has to be called if a unbounded-queue is used]]
+]
+[endsect]
+
+[section `explicit static_pool(
+ <<unspec-type>>,
+ high_watermark const& hwm,
+ low_watermark const& lwm,
+ posix_time::time_duration const& asleep = posix_time::milliseconds( 100),
+ scanns const& scns = scanns( 20) )`]
+[variablelist
+[[Preconditions:] [operating system provides functionality for processor binding]]
+[[Effects:] [constructs a pool - for each processor a worker-thread is created and bound to one processor - global-queue can only queue a limited number of tasks]]
+[[Throws:] [`boost::thread_resource_error`, `boost::task::invalid_scanns`, `boost::task::invalid_timeduration`, `boost::task::invalid_watermark`]]
+[[Notes:] [constructor has to be called if a bounded-queue is used and `bind_to_processors()` must be set as first argument]]
+]
+[endsect]
+
+[section `explicit static_pool(
+ poolsize const& psize,
+ high_watermark const& hwm,
+ low_watermark const& lwm,
+ posix_time::time_duration const& asleep = posix_time::milliseconds( 100),
+ scanns const& scns = scanns( 20) )`]
+[variablelist
+[[Effects:] [constructs a pool containing psize worker-threads - global-queue can only queue a limited number of tasks]]
+[[Throws:] [`boost::thread_resource_error`, `boost::task::invalid_scanns`, `boost::task::invalid_timeduration`, `boost::task::invalid_watermark`]]
+[[Notes:] [constructor has to be called if a bounded-queue is used]]
+]
+[endsect]
+
+[section `static_pool( static_pool &&)`]
+[variablelist
+[[Effects:] [creates an pool out of another one which gets zeroed out]]
+[[Throws:] [nothing]]
+]
+[endsect]
+
+[section `static_pool & operator=( static_pool &&)`]
+[variablelist
+[[Effects:] [creates an pool out of another one which gets zeroed out]]
+[[Throws:] [nothing]]
+]
+[endsect]
+
+[section `~static_pool()`]
+[variablelist
+[[Effects:] [calls `shutdown()` if not already called]]
+[[Throws:] [nothing]]
+]
+[endsect]
+
+[section `<<unspec-type>> bind_to_processors()`]
+[variablelist
+[[Effects:] [used in order to let the pool create worker-threads as cores are available and bound the threads to the cores]]
+[[Throws:] [nothing]]
+]
+[endsect]
+
+[section `std::size_t size()`]
+[variablelist
+[[Effects:] [returns how many worker-threads are running in the pool]]
+[[Throws:] [`boost::task::pool_moved`]]
+]
+[endsect]
+
+[section `void shutdown()`]
+[variablelist
+[[Effects:] [deactivates the queue and joins all worker-threads - the pool is closed]]
+[[Throws:] [`boost::thread_interrupted`, `boost::system::system_error`, `boost::task::pool_moved`]]
+[[Notes:] [all pending tasks are processed]]
+]
+[endsect]
+
+[section `void shutdown_now()`]
+[variablelist
+[[Effects:] [deactivates the queue, send interruption request to all worker-threads and joins them - the pool is closed]]
+[[Throws:] [`boost::thread_interrupted`, `boost::system::system_error`, `boost::task::pool_moved`]]
+[[Notes:] [pending tasks are not processed but returned]]
+]
+[endsect]
+
+[section `void interrupt_all_worker()`]
+[variablelist
+[[Effects:] [interrupts all worker-threads without invalidating the pool]]
+[[Throws:] [nothing]]
+]
+[endsect]
+
+[section `bool closed()`]
+[variablelist
+[[Effects:] [queries if the pool is closed (pool is shutdown)]]
+[[Throws:] [`boost::task::pool_moved`]]
+]
+[endsect]
+
+[section `std::size_t upper_bound()`]
+[variablelist
+[[Preconditions:] [queue is of type bounded-queue]]
+[[Effects:] [returns the upper bound of the bounded-queue]]
+[[Throws:] [`boost::task::pool_moved`]]
+[[Notes:] [can only be used if a bounded-queue is used]]
+]
+[endsect]
+
+[section `void upper_bound( high_watermark const& hwm)`]
+[variablelist
+[[Preconditions:] [queue is of type bounded-queue]]
+[[Effects:] [sets the upper bound of the bounded-queue]]
+[[Postconditions:] [`this->upper_bound() == hwm`]]
+[[Throws:] [`boost::task::invalid_watermark`, `boost::task::pool_moved`]]
+[[Notes:] [can only be used if a bounded-queue is used]]
+]
+[endsect]
+
+[section `std::size_t lower_bound()`]
+[variablelist
+[[Preconditions:] [queue is of type bounded-queue]]
+[[Effects:] [returns the lower bound of the bounded-queue]]
+[[Throws:] [`boost::task::pool_moved`]]
+[[Notes:] [can only be used if a bounded-queue is used]]
+]
+[endsect]
+
+[section `void lower_bound( low_watermark const& lwm)`]
+[variablelist
+[[Preconditions:] [queue is of type bounded-queue]]
+[[Effects:] [sets the lower bound of the bounded-queue]]
+[[Postconditions:] [`this->lower_bound() == lwm`]]
+[[Throws:] [`boost::task::invalid_watermark`, `boost::task::pool_moved`]]
+[[Notes:] [can only be used if a bounded-queue is used]]
+]
+[endsect]
+
+[section `template< typename R > handle< R > submit( task< R > t)`]
+[variablelist
+[[Preconditions:] [has_attribute< pool >::value == false && ! closed()]]
+[[Effects:] [moves an task to the pool and returns an associated handle]]
+[[Throws:] [`boost::task::task_rejected`, `boost::task::pool_moved`]]
+]
+[endsect]
+
+[section `template< typename R, typename Attr > handle< R > submit( task< R > t, Attr const& attr)`]
+[variablelist
+[[Preconditions:] [has_attribute< pool >::value == true && ! closed()]]
+[[Effects:] [moves an task to the pool and returns an associated handle - task is scheduled by the attribute]]
+[[Throws:] [`boost::task::task_rejected`, `boost::task::pool_moved`]]
+]
+[endsect]
+
+[section `void swap( static_pool & other)`]
+[variablelist
+[[Effects:] [swaps pool]]
+[[Throws:] [nothing]]
+]
+[endsect]
+
+[section `operator unspecified_bool_type() const`]
+[variablelist
+[[Effects:] [is static_pool valid == does static_pool own ownership]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section `bool operator!() const`]
+[variablelist
+[[Effects:] [is static_pool invalid == static_pool does not have ownership]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[endsect]
+
+[endsect]
+

Added: sandbox/task/libs/task/doc/task.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/task.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,126 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+[article Task
+ [quickbook 1.4]
+ [authors [Kowalke, Oliver]]
+ [copyright 2009 Oliver Kowalke]
+ [purpose C++ Library for asynchronous execution of tasks]
+ [category text]
+ [license
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ [@http://www.boost.org/LICENSE_1_0.txt])
+ ]
+]
+
+
+[def __boost_atomic__ [@http://www.chaoticmind.net/~hcb/projects/boost.atomic [*Boost.Atomic]]]
+[def __boost_fiber__ [@http://http://www.boostpro.com/vault/index.php?&direction=0&order=&directory=Concurrent%20Programming [*Boost.Fiber]]]
+[def __boost_move__ [@http://svn.boost.org/svn/boost/sandbox/move [*Boost.Move]]]
+[def __boost_task__ [*Boost.Task]]
+[def __boost_thread__ [@http://www.boost.org/libs/thread [*Boost.Thread]]]
+
+[template link_act[link_text] [link task.async_execution.async_completion_token [link_text]]]
+[template link_as_subtask[link_text] [link task.async_execution.execution_policy.as_subtask [link_text]]]
+[template link_async[link_text] [link task.async_execution.async [link_text]]]
+[template link_ep[link_text] [link task.async_execution.execution_policy [link_text]]]
+[template link_forkjoin[link_text] [link task.async_execution.execution_policy.threadpool.forkjoin [link_text]]]
+[template link_handle[link_text] [link task.async_execution.async_completion_token.handle [link_text]]]
+[template link_new_thread[link_text] [link task.async_execution.execution_policy.new_thread [link_text]]]
+[template link_own_thread[link_text] [link task.async_execution.execution_policy.own_thread [link_text]]]
+[template link_queue[link_text] [link task.async_execution.execution_policy.threadpool.queue [link_text]]]
+[template link_task[link_text] [link task.task_management.task [link_text]]]
+[template link_threadpool[link_text] [link task.async_execution.execution_policy.threadpool [link_text]]]
+[template link_work_stealing[link_text] [link task.async_execution.execution_policy.threadpool.workstealing [link_text]]]
+
+[def __hardware_concurrency__ `boost::thread::hardware_concurrency()`]
+
+[def __as_sub_task__ `boost::tasks::as_sub_task`]
+[def __attribute_type__ `boost::tasks::attribute_type`]
+[def __bounded_queue__ `boost::tasks::bounded_queue`]
+[def __dynamic_pool__ `boost::tasks::dynamic_pool`]
+[def __has_attribute__ `boost::tasks::has_attribute`]
+[def __hwm__ `boost::tasks::high_watermark`]
+[def __lwm__ `boost::tasks::low_watermark`]
+[def __pool_size__ `boost::tasks::poolsize`]
+[def __priority__ `boost::tasks::priority`]
+[def __replace_oldest__ `boost::tasks::replace_oldest`]
+[def __static_pool__ `boost::tasks::static_pool`]
+[def __system_time__ `boost::tasks::system_time`]
+[def __take_oldest__ `boost::tasks::take_oldest`]
+[def __task_interrupted__ `boost::tasks::task_interrupted`]
+[def __unbounded_queue__ `boost::tasks::unbounded_queue`]
+
+[def __make_task__ `boost::tasks::make_task()`]
+[def __waitfor_all__ `boost::tasks::waitfor_all()`]
+
+[def __fn_tt_interrupt__ `boost::this_task::interrupt()`]
+[def __fn_interruption_requested__ `boost::this_thread::interruption_requested()`]
+[def __fn_make_task__ `boost::tasks::make_task()`]
+[def __fn_runs_in_pool__ `boost::this_task::runs_in_pool()`]
+[def __fn_worker_id__ `boost::this_task::worker_id()`]
+[def __fn_yield__ `boost::this_task::yield()`]
+
+[def __fn_async__ `boost::tasks::async()`]
+[def __fn_make_task__ `boost::tasks::make_task()`]
+
+[def __fn_bind_to_processors__ `bind_to_processors()`]
+[def __fn_closed__ `close()`]
+[def __fn_get__ `get()`]
+[def __fn_has_value__ `has_value()`]
+[def __fn_has_exception__ `has_exception()`]
+[def __fn_interrupt__ `interrupt()`]
+[def __fn_interrupt_and_wait__ `interrupt_and_wait()`]
+[def __fn_interrupt_and_wait_for__ `interrupt_and_wait_for()`]
+[def __fn_interrupt_and_wait_until__ `interrupt_and_wait_until()`]
+[def __fn_interruption_requested__ `interruption_requested()`]
+[def __fn_is_ready__ `is_ready()`]
+[def __fn_operator__ `operator()()`]
+[def __fn_size__ `size()`]
+[def __fn_shutdown__ `shutdown()`]
+[def __fn_shutdown_now__ `shutdown_now()`]
+[def __fn_wait__ `wait()`]
+[def __fn_wait_for__ `wait_for()`]
+[def __fn_wait_until__ `wait_until()`]
+
+
+[def __act__ [link_act ['asynchronous-completion-token]]]
+[def __async__ [link_async ['async()]]]
+[def __ep__ [link_ep ['execution-policy]]]
+[def __eps__ [link_ep ['execution-policies]]]
+[def __blocked__ ['blocked]]
+[def __callable__ ['callable]]
+[def __coop_task__ ['cooperative task]]
+[def __duration__ ['Duration]]
+[def __fork_join__ [link_forkjoin ['fork/join]]]
+[def __handle__ [link_handle ['handle]]]
+[def __interruption_point__ ['interruption-point]]
+[def __interruption_points__ ['interruption-points]]
+[def __new_thread__ [link_new_thread ['new_thread]]]
+[def __own_thread__ [link_own_thread ['own_thread]]]
+[def __queue__ [link_queue ['queue]]]
+[def __task__ [link_task ['task]]]
+[def __thread_pool__ [link_threadpool ['thread-pool]]]
+[def __thread_pools__ [link_threadpool ['thread-pools]]]
+[def __sub_task__ ['sub-task]]
+[def __sub_tasks__ ['sub-tasks]]
+[def __work_item__ ['work-item]]
+[def __work_items__ ['work-items]]
+[def __work_stealing__ [link_work_stealing ['work-stealing]]]
+[def __worker_queue__ ['worker-queue]]
+[def __worker_thread__ ['worker-thread]]
+[def __worker_threads__ ['worker-threads]]
+
+
+
+[include overview.qbk]
+[include task_ref.qbk]
+[include async_execution.qbk]
+[include spin_synchronization.qbk]
+[include todo.qbk]
+[include acknowledgements.qbk]

Added: sandbox/task/libs/task/doc/task_ref.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/task_ref.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,407 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:task_management Task Management]
+
+[heading Synopsis]
+
+A task is a chunk of code that can be executed independently and parallel.
+
+__task__ represents a __callable__ (provides __fn_operator__) object containing
+the unit of code to be execute by a __ep__. Function __fn_async__ accepts a
+__task__ and an __ep__ and returns a __act__ allowing to wait for the completion
+of the computation of the task, for getting the result of a computation or for
+transfering exceptions.
+Objects of type __task__ are moveable.
+
+ boost::task< int > t1( parallel_fib, 10);
+ boost::task< int > t2; // not-a-task
+ t2 = boost::move( t1);
+
+
+[heading Launching]
+
+A new task is launched by passing an object of a callable type that can be invoked with no parameters to the
+constructor and passing the task to function __fn_async__. The object is then copied into internal storage
+of the __ep__, and invoked on the newly created task.
+
+ struct callable
+ { void operator()(); };
+
+ boost::task copies_are_safe()
+ {
+ callable x;
+ return boost::task( x);
+ } // x is destroyed, but the newly-created task has a copy, so this is OK
+
+ boost::task oops()
+ {
+ callable x;
+ return boost::task( boost::ref( x) );
+ } // x is destroyed, but the newly-created task still has a reference
+ // this leads to undefined behaviour
+
+If you wish to construct an instance of __task__ with a function or callable object that requires arguments to be
+supplied, this can be done by passing additional arguments to the __task__ constructor:
+
+ void find_the_question( int the_answer);
+
+ boost::task deep_thought_2( find_the_question, 42);
+
+ // asynchr. execution
+ boost::tasks::async( boost::move( depp_thought_2) );
+
+The arguments are ['copied] into the internal task structure: if a reference is required, use `boost::ref`, just as
+for references to callable functions.
+
+For convinience `boost::tasks::make_task()` is provided:
+
+ // asynchr. execution
+ boost::tasks::async(
+ boost::move( boost::tasks::make_task( find_the_question, 42) ),
+ boost::tasks::new_thread() );
+
+
+[heading Completion]
+
+In order to wait for the completion `boost::tasks::handle< R >::wait()` as to be called
+on the __handle__ associated with the task. The fucntion returns if the task has completed.
+The result of the task can be accessed via `boost::tasks::handle< R >::get()`.
+
+
+[heading Interruption]
+
+Sometimes it is desired to stop a running task if it is no longer needed. In this case the thread is not killed - it
+stops only at well-defined points (__interruption_points__) its execution.
+A task can be ['interrupted] by invoking the __fn_interrupt__ member function from __act__ . When the interrupted
+task next executes one of the specified __interruption_points__ (or if it is currently __blocked__ whilst executing
+one) with interruption enabled, then a __task_interrupted__ exception will be thrown in the interrupted task.
+In the context of ['task-interruption] a task is known as cooperative if it checks for an interruption request between
+two __interruption_points__ via __fn_interruption_requested__ [footnote see [@http://www.ddj.com/architect/207100682
+'Interrupt Politely'], Herb Sutter].
+
+
+[heading Predefined Interruption Points]
+
+The following functions are ['interruption points], which will throw __task_interrupted__ if interruption is
+enabled for the current fiber, and interruption is requested for the current fiber:
+
+* `boost::thread::join()`
+* `boost::thread::timed_join()`
+* `boost::condition_variable::wait()`
+* `boost::condition_variable::timed_wait()`
+* `boost::condition_variable_any::wait()`
+* `boost::condition_variable_any::timed_wait()`
+* `boost::tasks::spin::condition::wait()`
+* `boost::tasks::spin::condition::timed_wait()`
+* `boost::tasks::spin::auto_reset_event::wait()`
+* `boost::tasks::spin::auto_reset_event::timed_wait()`
+* `boost::tasks::spin::manual_reset_event::wait()`
+* `boost::tasks::spin::manual_reset_event::timed_wait()`
+* `boost::tasks::spin::count_down_event::wait()`
+* `boost::tasks::spin::count_down_event::timed_wait()`
+* `boost::thread::sleep()`
+* `boost::this_thread::sleep()`
+* `boost::this_thread::interruption_point()`
+
+A __interruption_point__ throws __task_interrupted__ if an interruption was requested.
+
+ long cooperative( long n)
+ {
+ // interruption point
+ boost::this_thread::interruption_point();
+
+ if ( n == 0) return 0;
+ if ( n == 1) return 1;
+ long k1( 1), k2( 0);
+ for ( int i( 2); i <= n; ++i)
+ {
+ // check if interruption was requested
+ if ( boost::this_thread::interruption_requested() )
+ return;
+
+ long tmp( k1);
+ k1 = k1 + k2;
+ k2 = tmp;
+ }
+
+ // interruption point
+ boost::this_thread::interruption_point();
+
+ return k1;
+ }
+
+ void main()
+ {
+ // task for computing fibonacci-number
+ boost::task< long > t( cooperative, 10) );
+
+ // execute task in new thread
+ // move task ownership to executor
+ boost::tasks::handle< long > h(
+ boost::tasks::async(
+ boost::move( t),
+ boost::tasks::new_thread() ) );
+
+ // interrupt task an wait until
+ // the task is removed by the worker-thread
+ h.interrupt_and_wait();
+
+ // access the result
+ // throws boost::task_interrupted
+ std::cout << "fibonacci(10) == " << h.get() << std::endl;
+ }
+
+If a task wishes to avoid being interrupted, it can create an instance of `boost::disable_interruption`.
+The effects of an instance of `boost::disable_interruption` can be temporarily reversed by constructing an instance of
+`boost::restore_interruption`, passing in the `boost::disable_interruption` object in question. This will restore the
+interruption state to what it was when the `boost::disable_interruption` object was constructed, and then disable
+interruption again when the `boost::restore_interruption` object is destroyed.
+
+
+[heading Exceptions]
+
+Exceptions thrown by the function or callable object passed to the __task__ constructor are consumed by the thes
+associated __act__. The exception will be re-thrown by the associated __handle__.
+
+ void throwing()
+ {
+ ...
+ throw std::domain_error("domain error");
+ ...
+ }
+
+ void main()
+ {
+ // create task throwing std::domain_error
+ boost::task void > t( throwing);
+
+ // execute task asynchron
+ // move task ownership to executor
+ boost::tasks::handle< void > h(
+ boost::tasks::async(
+ boost::move( t),
+ boost::tasks::new_thread() ) );
+
+ // wait for task completion
+ // throws std::domain_error
+ std::cout << h.wait() << std::endl;
+ }
+
+Exceptions rethrown by type are:
+
+* `std::bad_alloc`
+* `std::bad_cast`
+* `std::bad_exception`
+* `std::bad_typeid`
+* `std::domain_error`
+* `std::invalid_argument`
+* `std::ios_base::failure`
+* `std::length_error`
+* `std::logic_error`
+* `std::out_of_range`
+* `std::overflow_error`
+* `std::range_error`
+* `std::runtime_error`
+* `std::underflow_error`
+* `boost::exception`
+* `boost::future_already_set`
+* `boost::future_cancel`
+* `boost::invalid_thread_argument`
+* `boost::lock_error`
+* `boost::broken_task`
+* `boost::pool_moved`
+* `boost::task_already_executed`
+* `boost::task_interrupted`
+* `boost::task_moved`
+* `boost::task_interrupted`
+* `boost::task_task_rejected`
+* `boost::task_unitialized`
+
+[warning Don't use the sjlj exception model.]
+
+
+[heading Parent Task]
+
+Top-level tasks have no parent. A parent task can create child tasks when it creates another task by using
+__as_sub_task__ as __ep__. These children are implicitly treated as __sub_tasks__ of the parent task. It is
+assumed that that __sub_tasks__ can be executed in any order because only overall operation speed matters
+(enabling strategies for fast execution of unordered __work_items__ as [link_work_stealing __work_stealing__]).
+
+ long serial_fib( long n)
+ {
+ if( n < 2) return n;
+ else return serial_fib( n - 1) + serial_fib( n - 2);
+ }
+
+ long parallel_fib( long n, long cutof)
+ {
+ if ( n < cutof) return serial_fib( n);
+ else
+ {
+ // sub-task for computing fibonacci(n-1)
+ boost::task< long > t1(
+ parallel_fib,
+ n - 1,
+ cutof);
+ // sub-task for computing fibonacci(n-2)
+ boost::task< long > t2(
+ parallel_fib,
+ n - 2,
+ cutof);
+
+ // submit a sub-tasks to thread-pool
+ // move task ownership to executor
+ boost::tasks::handle< long > h1(
+ boost::tasks::async(
+ boost::move( t1) );
+ boost::tasks::handle< long > h2(
+ boost::tasks::async(
+ boost::move( t2) );
+
+ // computing fibonacci(n) by
+ // joining results of both sub-tasks
+ return h1.get() + h2.get();
+ }
+ }
+
+ void main()
+ {
+ // create thread-pool with five worker-threads
+ boost::tasks::static_pool< boost::tasks::unbounded_fifo > pool( boost::tasks::poolsize( 5) );
+
+ // create task computing fibonacci-number for 10
+ boost::task< long > t(
+ parallel_fib,
+ 10,
+ 5);
+
+ // execute task asynchron in thread-pool
+ // move task ownership to executor
+ boost::tasks::handle< long > h(
+ boost::tasks::async(
+ boost::move( t),
+ pool) );
+
+ // access result
+ std::cout << "fibonacci(10) == " << h.get() << std::endl;
+ }
+
+
+[section:task Class template `task`]
+
+ #include <boost/task/task.hpp>
+
+ template< typename R >
+ class task : private noncopyable
+ {
+ public:
+ task();
+
+ task( R( * fn)());
+
+ template< typename Fn >
+ task( Fn fn);
+
+ template< typename Fn, typename A0, ... >
+ task( Fn fn, A0 a0, ...);
+
+ task( task && x);
+ task & operator=( task && x);
+
+ void operator()();
+
+ void swap( task< R > & other);
+
+ operator unspecified_bool_type() const;
+ bool operator!() const;
+ };
+
+ template< typename Fn >
+ task< R > make_task( Fn fn);
+ template< typename Fn, typename A0, ... >
+ task< R > make_task( Fn fn, A0 a0, ...);
+
+
+[section:default_constructor `task()`]
+[variablelist
+[[Effects:] [constructs a __task__ instance that refers to __not_a_task__.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section:constructor `task( R( * fn)())`]
+[variablelist
+[[Effects:] [constructs a __task__ from a function pointer]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section:constructor_2 `template< typename Fn > task( Fn const& fn)`]
+[variablelist
+[[Effects:] [constructs a __task__ from a function object]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section:multi_argument_constructor `template< typename Fn, typename A0, ... > task( Fn fn, A0 a0, ...)`]
+[variablelist
+[[Effects:] [constructs a `boost::task::task< R >` from a function object and its arguments]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section:operator `operator()()`]
+[variablelist
+[[Effects:] [executes task's internal function object]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section:swap `swap( task< R > & other)`]
+[variablelist
+[[Effects:] [Exchanges the tasks associated with `*this` and `other`, so `*this` is associated with the task
+associated with `other` prior to the call, and vice-versa.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section:unspec_operator `operator unspecified_bool_type() const`]
+[variablelist
+[[Returns:] [If `*this` refers to a task, the function returns true. Otherwise false.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section:not_operator `operator!()`]
+[variablelist
+[[Returns:] [If `*this` refers not to a task, the function returns true. Otherwise false.]]
+[[Throws:] [Nothing]]
+]
+[endsect]
+
+[section:non_member_make_task Non-member template function `make_task()`]
+
+ #include <boost/task/task.hpp>
+
+ template< typename Fn >
+ fiber make_task( Fn fn);
+
+ template< typename Fn, typename A0, ... >
+ fiber make_task( Fn fn, A0 a0, ..., std::size_t stack_size);
+
+[variablelist
+[[Effects:] [Creates a task.]]
+]
+[endsect]
+
+[endsect]
+
+[include this_task.qbk]
+
+[endsect]

Added: sandbox/task/libs/task/doc/this_task.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/this_task.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,63 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+[section:this_task Namespace `this_task`]
+
+[heading Synopsis]
+
+The non-member function in namespace `this_task` provide functionality to ['yield] the current task or
+test if the task is executed inside a __thread_pool__.
+
+[section:block Non-member function `yield()`]
+
+ #include <boost/task/utility.hpp>
+
+ namespace this_task
+ {
+ void yield()
+ }
+
+[variablelist
+[[Effects:] [Blocks the current task and lets the worker-thread of the pool process another task.
+The blocked task will be scheduled and return from this method.]]
+[[Throws:] [nothing]]
+]
+[endsect]
+
+[section:runs_in_pool Non-member function `runs_in_pool()`]
+
+ #include <boost/task/utility.hpp>
+
+ namespace this_task
+ {
+ bool runs_in_pool()
+ }
+
+[variablelist
+[[Effects:] [Returns true if the current task is executed in a thread-pool.]]
+[[Throws:] [nothing]]
+[[Note:] [this function resides in namespace `boost::this_task`]]
+]
+[endsect]
+
+
+[section:worker_id Non-member function `worker_id()`]
+
+ #include <boost/task/utility.hpp>
+
+ namespace this_task
+ {
+ id worker_id()
+ }
+
+[variablelist
+[[Effects:] [Returns returns the thread-id of the worker-thread form the thread-pool.]]
+[[Throws:] [nothing]]
+]
+[endsect]
+
+[endsect]

Added: sandbox/task/libs/task/doc/threadpool.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/threadpool.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,63 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:threadpool Execute in Thread-Pool]
+
+[heading Synopsis]
+
+Instead of creating a new thread and quickly throwing it away after the task is done, the overhead related to thread
+creation and destruction can be avoided by running the __work_items__ on a __thread_pool__ (reusing an existing
+__worker_thread__ instead).
+
+A __thread_pool__ maintains a global queue of __work_items__ to be processed, and a pool of __worker_threads__ which execute __work_items__ from the global queue.
+
+__boost_task__ provides __fn_async__ with support of executing an __task__ in __thread_pool__:
+
+
+ std::string echo( std::string const& msg)
+ { return msg; }
+
+ void main()
+ {
+ // create a thread-pool with
+ // five worker-threads
+ // FIFO schduling of queued tasks
+ // and unlimited size of internal queue
+ boost::tasks::static_pool< boost::tasks::unbounded_fifo > pool( boost::tasks::poolsize( 5) );
+
+ // create task
+ boost::tasks::task< std::string > t( echo, "Hello World!");
+
+ // move task to executor
+ // let the task be executed by the thread-pool
+ boost::tasks::handle< std::string > h(
+ boost::tasks::async(
+ boost::move( t),
+ pool) );
+
+ // access the result
+ std::cout << h.get() << std::endl;
+ }
+
+
+[important Tasks should not be too small (performance overhead dominates) and avoid blocking
+tasks[footnote see [@http://www.ddj.com/go-parallel/article/showArticle.jhtml?articleID=216500409
+'Use Thread Pools Correctly'], Herb Sutter].]
+
+
+[include static_pool.qbk]
+[include meta_functions.qbk]
+[include queue.qbk]
+[include shutdown.qbk]
+[include processor_binding.qbk]
+[include work_stealing.qbk]
+[include fork_join.qbk]
+
+
+[endsect]
+

Added: sandbox/task/libs/task/doc/todo.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/todo.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,22 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:todo Todo]
+
+* optimize memory ordering in atomic ops.
+
+* replace thread_specific_ptr by an specialiced implementation for `boost::tasks::detail::worker`
+
+* __dynamic_pool__ adds or removes __worker_threads__ from the __thread_pool__
+ depending on the work-load (undersubscription/oversubscription).
+
+* task group defines a graph of interdependent tasks that can mostly be run in
+ parallel. The tasks in the group have dependencies or communicate with each
+ other.
+
+[endsect]

Added: sandbox/task/libs/task/doc/work_stealing.qbk
==============================================================================
--- (empty file)
+++ sandbox/task/libs/task/doc/work_stealing.qbk 2010-01-09 10:08:55 EST (Sat, 09 Jan 2010)
@@ -0,0 +1,50 @@
+[/
+ Copyright Oliver Kowalke 2009.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+]
+
+
+[section:workstealing Work-Stealing]
+
+Traditional __thread_pools__ do not scale because they use a single global-queue protected by a global-lock. The frequency at which
+__worker_threads__ aquire the global-lock becomes a limiting factor for the throughput if:
+
+* the tasks become smaller
+
+* more processors are added
+
+
+A __work_stealing__ algorithm can be used to solve this problem. It uses a special kind of queue which has two ends, and allows
+lock-free pushes and pops from the ['private end] (accessed by the __worker_thread__ owning the queue), but requires synchronization
+from the ['public end] (accessed by the other __worker_threads__). Synchronization is necessary when the queue is sufficiently small
+that private and public operations could conflict.
+
+The pool contains one global-queue (__bounded_queue__ or __unbounded_queue__) protected by a global-lock and each __worker_thread__
+has its own private local worker-queue. If work is enqueued by a __worker_thread__ the __task__ is stored in the worker queue. If the
+work is enqueued by a application thread it goes into the global queue. When __worker_threads__ are looking for work, they have
+following search order:
+
+* look into the private worker-queue - tasks can be dequeued without locks
+
+* look in the global-queue - locks are used for synchronization
+
+* check other worker-queues ('stealing' tasks from private worker queues of other __worker_threads__) - requires locks
+
+
+For a lot of recursively queued tasks (so called __sub_tasks__), the use of a worker-queue per thread substantially reduces the
+synchronization necessary to complete the work. There are also fewer cache effects due to sharing of the global-queue information.
+
+Operations on the private worker queue are executed in LIFO order and operations on worker queues of other __worker_threads__ in
+FIFO order (steals).
+
+* There are chances that memory is still hot in the cache, if the tasks are pushed in LIFO order into the private worker queue.
+
+* If a __worker_thread__ steals work in FIFO order, increases the chances that a larger 'chunk' of work will be stolen (the need
+for other steals will be possibly reduced). Because the __sub_tasks__ are stored in LIFO order, the oldest items are closer to the
+['public end] of the queue (forming a tree). Stealing such an older __task__ also steals a (probably) larger subtree of tasks
+unfolded if the stolen work item get executed. Since a __sub_task__ is just part of a larger __task__, we don’t need to worry about
+execution order.
+
+[endsect]


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