Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r53059 - in sandbox/task: boost/task libs/task/doc
From: oliver.kowalke_at_[hidden]
Date: 2009-05-16 18:25:12


Author: olli
Date: 2009-05-16 18:25:11 EDT (Sat, 16 May 2009)
New Revision: 53059
URL: http://svn.boost.org/trac/boost/changeset/53059

Log:
* documentation update related to task

Text files modified:
   sandbox/task/boost/task/handle.hpp | 2
   sandbox/task/libs/task/doc/boost_task.qbk | 4
   sandbox/task/libs/task/doc/introduction.qbk | 2
   sandbox/task/libs/task/doc/task.qbk | 205 ++++++++++++++++++++++++++-------------
   4 files changed, 145 insertions(+), 68 deletions(-)

Modified: sandbox/task/boost/task/handle.hpp
==============================================================================
--- sandbox/task/boost/task/handle.hpp (original)
+++ sandbox/task/boost/task/handle.hpp 2009-05-16 18:25:11 EDT (Sat, 16 May 2009)
@@ -205,6 +205,8 @@
                 { fut_.get(); }
                 catch ( broken_promise const&)
                 { throw broken_task(); }
+ catch ( promise_already_satisfied const&)
+ { throw task_already_executed(); }
         }
 
         bool is_ready() const

Modified: sandbox/task/libs/task/doc/boost_task.qbk
==============================================================================
--- sandbox/task/libs/task/doc/boost_task.qbk (original)
+++ sandbox/task/libs/task/doc/boost_task.qbk 2009-05-16 18:25:11 EDT (Sat, 16 May 2009)
@@ -45,6 +45,7 @@
 [def __new_thread__ `boost::task::new_thread`]
 [def __own_thread__ `boost::task::own_thread`]
 [def __task__ `boost::task::task`]
+[def __task_interrupted__ `boost::task::task_interrupted`]
 [def __static_pool__ `boost::task::static_pool`]
 [def __system_time__ `boost::task::system_time`]
 [def __unbounded_channel__ `boost::task::unbounded_channel`]
@@ -52,6 +53,7 @@
 [def __fn_delay__ `boost::this_task::delay()`]
 [def __fn_get_pool__ `boost::this_task::get_pool()`]
 [def __fn_tt_interrupt__ `boost::this_task::interrupt()`]
+[def __fn__interruption_requested__ `boost::this_thread::interruption_requested()`]
 [def __fn_make_task__ `boost::task::make_task()`]
 [def __fn_reschedule_until__ `boost::this_task::reschedule_until()`]
 [def __fn_runs_in_pool__ `boost::this_task::runs_in_pool()`]
@@ -63,6 +65,7 @@
 
 [def __fn_get__ `get()`]
 [def __fn_get_id__ `get_id()`]
+[def __fn_get_future__ `get_future()`]
 [def __fn_has_value__ `has_value()`]
 [def __fn_has_exception__ `has_exception()`]
 [def __fn_interrupt__ `interrupt()`]
@@ -82,6 +85,7 @@
 [def __duration__ `Duration`]
 [def __fork_join__ ['fork/join]]
 [def __interruption_point__ ['interruption-point]]
+[def __interruption_points__ ['interruption-points]]
 [def __task_id__ ['task-id]]
 [def __thread_pool__ ['thread-pool]]
 [def __thread_pools__ ['thread-pools]]

Modified: sandbox/task/libs/task/doc/introduction.qbk
==============================================================================
--- sandbox/task/libs/task/doc/introduction.qbk (original)
+++ sandbox/task/libs/task/doc/introduction.qbk 2009-05-16 18:25:11 EDT (Sat, 16 May 2009)
@@ -115,7 +115,7 @@
                                         5) ) );
                 std::cout << h.get() << std::endl;
         }
-};
+
 
 With function __fn_runs_in_pool__ a task can detect if it is executed inside a __thread_pool__.
 __sub_tasks__ arecreated by __as_sub_task__. Where the __sub_task__ is executed by a new thread if the parent task

Modified: sandbox/task/libs/task/doc/task.qbk
==============================================================================
--- sandbox/task/libs/task/doc/task.qbk (original)
+++ sandbox/task/libs/task/doc/task.qbk 2009-05-16 18:25:11 EDT (Sat, 16 May 2009)
@@ -10,23 +10,56 @@
 
 A task is a chunk of code that can be executed independently.
 
-__task__ represents a __callable__ object containing the unit of code to be execute by a link_ae[__ae__]. It returns a link_act[__act__] allowing to wait for the completion of the computation of the task, for getting the result of a computation or for transfering exceptions.
+__task__ represents a __callable__ object containing the unit of code to be execute by a link_ae[__ae__]. Function __fn_get_future__ returns a link_act[__act__] allowing to wait for the completion of the computation of the task, for getting the result of a computation or for transfering exceptions.
+Each __task__ has a unique identifier
 
 
 [heading:create_task Creation]
 
-__fn_make_task__ can be used to create __task__.
-The __task__ object acts as a proxy for a result that is initially not known and gets evaluated later by a __worker_thread__. It transports the result (value or exception) of the __action__ back to the caller.
+__fn_make_task__ can be used to create __task__ by passing free-functions or member-functions of objects and its arguments: __fn_make_task__ accepts up to ten
+arguments per default (can be overriden by defining BOOST_TASK_MAKE_TASK_MAX_ARITY with the new value).
 
- boost::task::task< int > t1(
+* create task from free-function with arguments:
+
+ boost::task::task< int > t(
       boost::task::make_task(
           parallel_fib,
- 10) );
+ 10) );
+
+* create task from member-function with arguments:
 
-[heading:cooperative_task Interruption]
+ struct X
+ {
+ void f( int i);
+ };
+
+ X x;
+ boost::task::task< int > t(
+ boost::task::make_task(
+ & X::f,
+ x,
+ 10) );
+
+It is possible to create __task__ from a __callable__ too:
+
+ struct Y
+ {
+ std::string operator()();
+ };
+
+ Y y;
+ boost::task::task< std::string > t( y);
+
+
+[heading:cooperative_task Cooperative task amd 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.
+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].
 
-__task__ object provides the possiblity to interrupt an __action__ if it is cooperative.
-An __action__ is known as cooperative if it includes interruption points in its code:
+__interruption__points__ are:
 
 * `boost::thread::join()`
 * `boost::thread::timed_join()`
@@ -38,49 +71,64 @@
 * `boost::this_thread::sleep()`
 * `boost::this_thread::interruption_point()`
 
-[important Interruption must not be disabled for the __worker_thread__ (class ['boost::this_thread::disable_interruption]).]
+A __interruption__point__ throws __task_interrupted__ if an interruption was requested.
 
-The __action__ will be interrupted even if it is pending (interruption is remembered).
-A ['boost::thread_interrupted] exception will be thrown by `boost::tp::task< T >::get()` if the __action__ was interrupted.
-``
- boost::tp::pool<
- boost::tp::unbounded_channel< boost::tp::fifo >
- > pool( boost::tp::poolsize( 10) );
-
- // submit a long running task
- boost::tp::task< int > t(
- pool.submit(
- boost::bind(
- long_running_fn) ) );
-
- // interrupt task
- t.interrupt();
-
- // throws boost::thread_interrupted exception
- std::cout << t.get() << std::endl;
-``
-
- boost::tp::pool<
- boost::tp::unbounded_channel< boost::tp::fifo >
- > pool( boost::tp::poolsize( 10) );
-
- // submit a long running task
- boost::tp::task< int > t(
- pool.submit(
- boost::bind(
- long_running_fn) ) );
+ 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()
+ {
+ boost::task::handle< long > h( // get handle associated with the task
+ boost::task::async(
+ boost::task::new_thread(), // asynchronous executor
+ boost::task::make_task( // task, to be executed asynchronously
+ cooperative,
+ 10) ) );
+ std::cout << h.get() << std::endl; // throws boost::task::task_interrupted
+ }
 
- // interrupt task and wait for its termination
- t.interrupt_and_wait();
 
- // throws boost::thread_interrupted exception
- std::cout << t.get() << std::endl;
+[heading:task_exceptions Exceptions]
 
+Exceptions thrown by __task__ are transported by the __act__.
 
-[heading:task_exceptions Exceptions]
+ void throwing()
+ {
+ ...
+ throw std::domain_error("domain error");
+ ...
+ }
+
+ void main()
+ {
+ boost::task::handle< void > h( // get handle associated with the task
+ boost::task::async(
+ boost::task::new_thread(), // asynchronous executor
+ boost::task::make_task( // task, to be executed asynchronously
+ throwing) ) );
+ std::cout << h.wait() << std::endl; // throws std::domain_error
+ }
 
-Exceptions thrown inside an __action__ are transported by the associated task object.
-Exceptions rethrown by type:
+Exceptions rethrown by type are:
 
 * `std::bad_alloc`
 * `std::bad_cast`
@@ -96,37 +144,60 @@
 * `std::range_error`
 * `std::runtime_error`
 * `std::underflow_error`
-* `boost::broken_promise`
 * `boost::future_already_set`
 * `boost::future_cancel`
 * `boost::exception`
 * `boost::invalid_thread_argument`
 * `boost::lock_error`
-* `boost::thread_exception`
-* `boost::thread_interrupted`
-* `boost::thread_permission_error`
-* `boost::thread_resource_error`
-* `boost::unsupported_thread_option`
-
-Exceptions derived from `std::exception` will be rethrown as `std::runtime_error` in all other cases a `std::bad_exception` is thrown.
-
- boost::tp::pool<
- boost::tp::unbounded_channel< boost::tp::fifo >
- > pool( boost::tp::poolsize( 10) );
-
- // task will throw an exception derived from std::exception
- boost::tp::task< int > t(
- pool.submit(
- boost::bind(
- throwing_fn) ) );
+* `boost::task::task_interrupted`
+* `boost::broken_task`
 
- std::cout << t.get() << std::endl; // will rethrow an std::runtime_error
 
 [heading:parent_tasks Parent-tasks]
 
-Top-level Tasks have no parent. These are Tasks created by non-thread-pool threads, or with certain options specified at Task-creation time. These tasks are queued to the same FIFO queue we use for QUWI, and thus benefit from the improvements we’ve made there – but they are also subject to the same limitations. Tasks queued in this way are simply a better QUWI – but now the fun starts: A parent task can create child tasks. This happens whenever a Task creates another Task (unless it overrides this behavior). These children are implicitly treated as sub-tasks of the larger task. We assume that sub-tasks can be executed in any order – fairness is not necessary – because all that matters is that the overall operation be completed as fast as possible. This lets us throw those FIFO restrictions out the window, and opens up the possibility for much more efficient work scheduling strategies.
-
-Since a child task is just a piece of a larger task, we don’t need to worry about execution order. We just need to execute these things quickly. One well-known strategy for fast execution of unordered work items is link_work_stealing[__work_stealing__].
+Top-level tasks have no parent. A parent task can create child tasks when it creates another task by using __as_sub_task__ as __ae__. These children are implicitly treated as __sub_tasks__ of the larger 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
+ {
+ // submit a sub-task to pool calculating fibonacci(n-1)
+ h1 = boost::task::async(
+ boost::task::as_sub_task(), // execute a sub-task
+ boost::task::make_task(
+ parallel_fib,
+ n - 1,
+ cutof) );
+ // submit a sub-task to pool calculating fibonacci(n-2)
+ h2 = boost::task::async(
+ boost::task::as_sub_task(), // execute a sub-task
+ boost::task::make_task(
+ parallel_fib,
+ n - 2,
+ cutof) );
+ // calculate fibonacci(n) from the results of both sub-tasks
+ return h1.get() + h2.get();
+ }
+ }
+
+ void main()
+ {
+ boost::task::handle< long > h( // handle for fibonacci calculation
+ boost::task::async(
+ boost::task::default_pool(), // access the default thread-pool
+ boost::task::make_task( // calculate fibonacci number 10
+ parallel_fib, // for numbers < 5 do inline recursive calculation
+ 10,
+ 5) ) );
+ std::cout << h.get() << std::endl;
+ }
 
 [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