00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef __TBB_parallel_for_H
00022 #define __TBB_parallel_for_H
00023
00024 #include "task.h"
00025 #include "partitioner.h"
00026 #include <new>
00027
00028 namespace tbb {
00029
00031 namespace internal {
00032
00034
00035 template<typename Range, typename Body, typename Partitioner>
00036 class start_for: public task {
00037 Range my_range;
00038 const Body my_body;
00039 typename Partitioner::partition_type my_partition;
00040 task* execute();
00041
00043 start_for( const Range& range, const Body& body, Partitioner& partitioner ) :
00044 my_range(range),
00045 my_body(body),
00046 my_partition(partitioner)
00047 {
00048 }
00050
00051 start_for( start_for& parent, split ) :
00052 my_range(parent.my_range,split()),
00053 my_body(parent.my_body),
00054 my_partition(parent.my_partition,split())
00055 {
00056 my_partition.set_affinity(*this);
00057 }
00059 void note_affinity( affinity_id id ) {
00060 my_partition.note_affinity( id );
00061 }
00062 public:
00063 static void run( const Range& range, const Body& body, const Partitioner& partitioner ) {
00064 if( !range.empty() ) {
00065 #if !__TBB_EXCEPTIONS || TBB_JOIN_OUTER_TASK_GROUP
00066 start_for& a = *new(task::allocate_root()) start_for(range,body,const_cast<Partitioner&>(partitioner));
00067 #else
00068
00069
00070 task_group_context context;
00071 start_for& a = *new(task::allocate_root(context)) start_for(range,body,const_cast<Partitioner&>(partitioner));
00072 #endif
00073 task::spawn_root_and_wait(a);
00074 }
00075 }
00076 #if __TBB_EXCEPTIONS
00077 static void run( const Range& range, const Body& body, const Partitioner& partitioner, task_group_context& context ) {
00078 if( !range.empty() ) {
00079 start_for& a = *new(task::allocate_root(context)) start_for(range,body,const_cast<Partitioner&>(partitioner));
00080 task::spawn_root_and_wait(a);
00081 }
00082 }
00083 #endif
00084 };
00085
00086 template<typename Range, typename Body, typename Partitioner>
00087 task* start_for<Range,Body,Partitioner>::execute() {
00088 if( !my_range.is_divisible() || my_partition.should_execute_range(*this) ) {
00089 my_body( my_range );
00090 return my_partition.continue_after_execute_range(*this);
00091 } else {
00092 empty_task& c = *new( this->allocate_continuation() ) empty_task;
00093 recycle_as_child_of(c);
00094 c.set_ref_count(2);
00095 bool delay = my_partition.decide_whether_to_delay();
00096 start_for& b = *new( c.allocate_child() ) start_for(*this,split());
00097 my_partition.spawn_or_delay(delay,*this,b);
00098 return this;
00099 }
00100 }
00101 }
00103
00104
00105
00106
00117
00119
00120 template<typename Range, typename Body>
00121 void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner=simple_partitioner() ) {
00122 internal::start_for<Range,Body,simple_partitioner>::run(range,body,partitioner);
00123 }
00124
00126
00127 template<typename Range, typename Body>
00128 void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner ) {
00129 internal::start_for<Range,Body,auto_partitioner>::run(range,body,partitioner);
00130 }
00131
00133
00134 template<typename Range, typename Body>
00135 void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner ) {
00136 internal::start_for<Range,Body,affinity_partitioner>::run(range,body,partitioner);
00137 }
00138
00139 #if __TBB_EXCEPTIONS
00141
00142 template<typename Range, typename Body>
00143 void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner, task_group_context& context ) {
00144 internal::start_for<Range,Body,simple_partitioner>::run(range, body, partitioner, context);
00145 }
00146
00148
00149 template<typename Range, typename Body>
00150 void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner, task_group_context& context ) {
00151 internal::start_for<Range,Body,auto_partitioner>::run(range, body, partitioner, context);
00152 }
00153
00155
00156 template<typename Range, typename Body>
00157 void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner, task_group_context& context ) {
00158 internal::start_for<Range,Body,affinity_partitioner>::run(range,body,partitioner, context);
00159 }
00160 #endif
00161
00162
00163 }
00164
00165 #endif
00166