2 Copyright 2005-2011 Intel Corporation. All Rights Reserved.
4 This file is part of Threading Building Blocks.
6 Threading Building Blocks is free software; you can redistribute it
7 and/or modify it under the terms of the GNU General Public License
8 version 2 as published by the Free Software Foundation.
10 Threading Building Blocks is distributed in the hope that it will be
11 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with Threading Building Blocks; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 As a special exception, you may use this file as part of a free software
20 library without restriction. Specifically, if other files instantiate
21 templates or use macros or inline functions from this file, or you compile
22 this file and link it with other files to produce an executable, this
23 file does not by itself cause the resulting executable to be covered by
24 the GNU General Public License. This exception does not however
25 invalidate any other reasons why the executable file might be covered by
26 the GNU General Public License.
29 #ifndef __TBB_parallel_for_H
30 #define __TBB_parallel_for_H
34 #include "partitioner.h"
35 #include "blocked_range.h"
36 #include "tbb_exception.h"
40 namespace interface6 {
44 //! Task type used in parallel_for
45 /** @ingroup algorithms */
46 template<typename Range, typename Body, typename Partitioner>
47 class start_for: public task {
50 typename Partitioner::task_partition_type my_partition;
51 /*override*/ task* execute();
54 //! Constructor for root task.
55 start_for( const Range& range, const Body& body, Partitioner& partitioner ) :
58 my_partition(partitioner)
61 //! Splitting constructor used to generate children.
62 /** parent_ becomes left child. Newly constructed object is right child. */
63 start_for( start_for& parent_, split ) :
64 my_range(parent_.my_range,split()),
65 my_body(parent_.my_body),
66 my_partition(parent_.my_partition, split())
68 my_partition.set_affinity(*this);
70 //! Construct right child from the given range as response to the demand.
71 /** parent_ remains left child. Newly constructed object is right child. */
72 start_for( start_for& parent_, const Range& r, depth_t d ) :
74 my_body(parent_.my_body),
75 my_partition(parent_.my_partition,split())
77 my_partition.set_affinity(*this);
78 my_partition.align_depth( d );
80 //! Update affinity info, if any.
81 /*override*/ void note_affinity( affinity_id id ) {
82 my_partition.note_affinity( id );
84 static void run( const Range& range, const Body& body, const Partitioner& partitioner ) {
85 if( !range.empty() ) {
86 #if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP
87 start_for& a = *new(task::allocate_root()) start_for(range,body,const_cast<Partitioner&>(partitioner));
89 // Bound context prevents exceptions from body to affect nesting or sibling algorithms,
90 // and allows users to handle exceptions safely by wrapping parallel_for in the try-block.
91 task_group_context context;
92 start_for& a = *new(task::allocate_root(context)) start_for(range,body,const_cast<Partitioner&>(partitioner));
93 #endif /* __TBB_TASK_GROUP_CONTEXT && !TBB_JOIN_OUTER_TASK_GROUP */
94 task::spawn_root_and_wait(a);
97 #if __TBB_TASK_GROUP_CONTEXT
98 static void run( const Range& range, const Body& body, const Partitioner& partitioner, task_group_context& context ) {
99 if( !range.empty() ) {
100 start_for& a = *new(task::allocate_root(context)) start_for(range,body,const_cast<Partitioner&>(partitioner));
101 task::spawn_root_and_wait(a);
104 #endif /* __TBB_TASK_GROUP_CONTEXT */
105 //! create a continuation task, serve as callback for partitioner
106 flag_task *create_continuation() {
107 return new( allocate_continuation() ) flag_task();
109 //! Run body for range
110 void run_body( Range &r ) { my_body( r ); }
113 template<typename Range, typename Body, typename Partitioner>
114 task* start_for<Range,Body,Partitioner>::execute() {
115 my_partition.check_being_stolen( *this );
116 my_partition.execute(*this, my_range);
119 } // namespace internal
121 } // namespace interfaceX
125 using interface6::internal::start_for;
127 //! Calls the function with values from range [begin, end) with a step provided
128 template<typename Function, typename Index>
129 class parallel_for_body : internal::no_assign {
130 const Function &my_func;
131 const Index my_begin;
134 parallel_for_body( const Function& _func, Index& _begin, Index& _step)
135 : my_func(_func), my_begin(_begin), my_step(_step) {}
137 void operator()( tbb::blocked_range<Index>& r ) const {
138 for( Index i = r.begin(), k = my_begin + i * my_step; i < r.end(); i++, k = k + my_step)
142 } // namespace internal
145 // Requirements on Range concept are documented in blocked_range.h
147 /** \page parallel_for_body_req Requirements on parallel_for body
148 Class \c Body implementing the concept of parallel_for body must define:
149 - \code Body::Body( const Body& ); \endcode Copy constructor
150 - \code Body::~Body(); \endcode Destructor
151 - \code void Body::operator()( Range& r ) const; \endcode Function call operator applying the body to range \c r.
154 /** \name parallel_for
155 See also requirements on \ref range_req "Range" and \ref parallel_for_body_req "parallel_for Body". **/
158 //! Parallel iteration over range with default partitioner.
159 /** @ingroup algorithms **/
160 template<typename Range, typename Body>
161 void parallel_for( const Range& range, const Body& body ) {
162 internal::start_for<Range,Body,__TBB_DEFAULT_PARTITIONER>::run(range,body,__TBB_DEFAULT_PARTITIONER());
165 //! Parallel iteration over range with simple partitioner.
166 /** @ingroup algorithms **/
167 template<typename Range, typename Body>
168 void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner ) {
169 internal::start_for<Range,Body,simple_partitioner>::run(range,body,partitioner);
172 //! Parallel iteration over range with auto_partitioner.
173 /** @ingroup algorithms **/
174 template<typename Range, typename Body>
175 void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner ) {
176 internal::start_for<Range,Body,auto_partitioner>::run(range,body,partitioner);
179 //! Parallel iteration over range with affinity_partitioner.
180 /** @ingroup algorithms **/
181 template<typename Range, typename Body>
182 void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner ) {
183 internal::start_for<Range,Body,affinity_partitioner>::run(range,body,partitioner);
186 #if __TBB_TASK_GROUP_CONTEXT
187 //! Parallel iteration over range with simple partitioner and user-supplied context.
188 /** @ingroup algorithms **/
189 template<typename Range, typename Body>
190 void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner, task_group_context& context ) {
191 internal::start_for<Range,Body,simple_partitioner>::run(range, body, partitioner, context);
194 //! Parallel iteration over range with auto_partitioner and user-supplied context.
195 /** @ingroup algorithms **/
196 template<typename Range, typename Body>
197 void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner, task_group_context& context ) {
198 internal::start_for<Range,Body,auto_partitioner>::run(range, body, partitioner, context);
201 //! Parallel iteration over range with affinity_partitioner and user-supplied context.
202 /** @ingroup algorithms **/
203 template<typename Range, typename Body>
204 void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner, task_group_context& context ) {
205 internal::start_for<Range,Body,affinity_partitioner>::run(range,body,partitioner, context);
207 #endif /* __TBB_TASK_GROUP_CONTEXT */
210 namespace strict_ppl {
213 //! Parallel iteration over a range of integers with a step provided
214 template <typename Index, typename Function>
215 void parallel_for(Index first, Index last, Index step, const Function& f) {
217 internal::throw_exception(internal::eid_nonpositive_step); // throws std::invalid_argument
218 else if (last > first) {
219 // Above "else" avoids "potential divide by zero" warning on some platforms
220 Index end = (last - first - Index(1)) / step + Index(1);
221 tbb::blocked_range<Index> range(static_cast<Index>(0), end);
222 internal::parallel_for_body<Function, Index> body(f, first, step);
223 tbb::parallel_for(range, body, tbb::auto_partitioner());
226 //! Parallel iteration over a range of integers with a default step value
227 template <typename Index, typename Function>
228 void parallel_for(Index first, Index last, const Function& f) {
229 parallel_for(first, last, static_cast<Index>(1), f);
232 #if __TBB_TASK_GROUP_CONTEXT
233 //! Parallel iteration over a range of integers with explicit step and task group context
234 template <typename Index, typename Function>
235 void parallel_for(Index first, Index last, Index step, const Function& f, tbb::task_group_context &context) {
237 internal::throw_exception(internal::eid_nonpositive_step); // throws std::invalid_argument
238 else if (last > first) {
239 // Above "else" avoids "potential divide by zero" warning on some platforms
240 Index end = (last - first - Index(1)) / step + Index(1);
241 tbb::blocked_range<Index> range(static_cast<Index>(0), end);
242 internal::parallel_for_body<Function, Index> body(f, first, step);
243 tbb::parallel_for(range, body, tbb::auto_partitioner(), context);
246 //! Parallel iteration over a range of integers with a default step value and explicit task group context
247 template <typename Index, typename Function>
248 void parallel_for(Index first, Index last, const Function& f, tbb::task_group_context &context) {
249 parallel_for(first, last, static_cast<Index>(1), f, context);
251 #endif /* __TBB_TASK_GROUP_CONTEXT */
254 } // namespace strict_ppl
256 using strict_ppl::parallel_for;
260 #if TBB_PREVIEW_SERIAL_SUBSET
261 #define __TBB_NORMAL_EXECUTION
262 #include "../serial/tbb/parallel_for.h"
263 #undef __TBB_NORMAL_EXECUTION
266 #endif /* __TBB_parallel_for_H */