]> git.sesse.net Git - casparcg/blob - dependencies64/tbb/include/tbb/parallel_for.h
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches...
[casparcg] / dependencies64 / tbb / include / tbb / parallel_for.h
1 /*
2     Copyright 2005-2011 Intel Corporation.  All Rights Reserved.
3
4     This file is part of Threading Building Blocks.
5
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.
9
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.
14
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
18
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.
27 */
28
29 #ifndef __TBB_parallel_for_H
30 #define __TBB_parallel_for_H
31
32 #include <new>
33 #include "task.h"
34 #include "partitioner.h"
35 #include "blocked_range.h"
36 #include "tbb_exception.h"
37
38 namespace tbb {
39
40 namespace interface6 {
41 //! @cond INTERNAL
42 namespace internal {
43
44     //! Task type used in parallel_for
45     /** @ingroup algorithms */
46     template<typename Range, typename Body, typename Partitioner>
47     class start_for: public task {
48         Range my_range;
49         const Body my_body;
50         typename Partitioner::task_partition_type my_partition;
51         /*override*/ task* execute();
52
53     public:
54         //! Constructor for root task.
55         start_for( const Range& range, const Body& body, Partitioner& partitioner ) :
56             my_range(range),    
57             my_body(body),
58             my_partition(partitioner)
59         {
60         }
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())
67         {
68             my_partition.set_affinity(*this);
69         }
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 ) :
73             my_range(r),
74             my_body(parent_.my_body),
75             my_partition(parent_.my_partition,split())
76         {
77             my_partition.set_affinity(*this);
78             my_partition.align_depth( d );
79         }
80         //! Update affinity info, if any.
81         /*override*/ void note_affinity( affinity_id id ) {
82             my_partition.note_affinity( id );
83         }
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));
88 #else
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);
95             }
96         }
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);
102             }
103         }
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();
108         }
109         //! Run body for range
110         void run_body( Range &r ) { my_body( r ); }
111     };
112
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);
117         return NULL;
118     } 
119 } // namespace internal
120 //! @endcond
121 } // namespace interfaceX
122
123 //! @cond INTERNAL
124 namespace internal {
125     using interface6::internal::start_for;
126     
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;
132         const Index my_step; 
133     public:
134         parallel_for_body( const Function& _func, Index& _begin, Index& _step) 
135             : my_func(_func), my_begin(_begin), my_step(_step) {}
136         
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)
139                 my_func( k );
140         }
141     };
142 } // namespace internal
143 //! @endcond
144
145 // Requirements on Range concept are documented in blocked_range.h
146
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.
152 **/
153
154 /** \name parallel_for
155     See also requirements on \ref range_req "Range" and \ref parallel_for_body_req "parallel_for Body". **/
156 //@{
157
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());
163 }
164
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);
170 }
171
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);
177 }
178
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);
184 }
185
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);
192 }
193
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);
199 }
200
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);
206 }
207 #endif /* __TBB_TASK_GROUP_CONTEXT */
208 //@}
209
210 namespace strict_ppl {
211
212 //@{
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) {
216     if (step <= 0 )
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());
224     }
225 }
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);
230 }
231
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) {
236     if (step <= 0 )
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);
244     }
245 }
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);
250 }
251 #endif /* __TBB_TASK_GROUP_CONTEXT */
252 //@}
253
254 } // namespace strict_ppl
255
256 using strict_ppl::parallel_for;
257
258 } // namespace tbb
259
260 #if TBB_PREVIEW_SERIAL_SUBSET
261 #define __TBB_NORMAL_EXECUTION
262 #include "../serial/tbb/parallel_for.h"
263 #undef __TBB_NORMAL_EXECUTION
264 #endif
265
266 #endif /* __TBB_parallel_for_H */
267