21 #ifndef __TBB_parallel_invoke_H 22 #define __TBB_parallel_invoke_H 26 #if __TBB_VARIADIC_PARALLEL_INVOKE 32 #if !__TBB_TASK_GROUP_CONTEXT 34 struct task_group_context {};
40 template<
typename function>
41 class function_invoker :
public task{
43 function_invoker(
const function& _function) : my_function(_function) {}
45 const function &my_function;
55 template <
size_t N,
typename function1,
typename function2,
typename function3>
56 class spawner :
public task {
58 const function1& my_func1;
59 const function2& my_func2;
60 const function3& my_func3;
67 __TBB_ASSERT(N==2 || N==3,
"Number of arguments passed to spawner is wrong");
69 recycle_as_safe_continuation();
70 internal::function_invoker<function2>* invoker2 =
new (allocate_child()) internal::function_invoker<function2>(my_func2);
71 __TBB_ASSERT(invoker2,
"Child task allocation failed");
75 internal::function_invoker<function3>* invoker3 =
new (allocate_child()) internal::function_invoker<function3>(my_func3);
76 __TBB_ASSERT(invoker3,
"Child task allocation failed");
86 spawner(
const function1& _func1,
const function2& _func2,
const function3& _func3) : my_func1(_func1), my_func2(_func2), my_func3(_func3), is_recycled(false) {}
90 class parallel_invoke_helper :
public empty_task {
93 class parallel_invoke_noop {
95 void operator() ()
const {}
98 parallel_invoke_helper(
int number_of_children)
100 set_ref_count(number_of_children + 1);
103 #if __TBB_VARIADIC_PARALLEL_INVOKE 104 void add_children() {}
105 void add_children(tbb::task_group_context&) {}
107 template <
typename function>
108 void add_children(
function&& _func)
110 internal::function_invoker<function>* invoker =
new (allocate_child()) internal::function_invoker<function>(std::forward<function>(_func));
111 __TBB_ASSERT(invoker,
"Child task allocation failed");
115 template<
typename function>
116 void add_children(
function&& _func, tbb::task_group_context&)
118 add_children(std::forward<function>(_func));
122 template <
typename function1,
typename function2,
typename...
function>
123 void add_children(function1&& _func1, function2&& _func2,
function&&... _func)
126 parallel_invoke_noop noop;
127 typedef internal::spawner<2, function1, function2, parallel_invoke_noop> spawner_type;
128 spawner_type & sub_root = *
new(allocate_child()) spawner_type(std::forward<function1>(_func1), std::forward<function2>(_func2), noop);
130 add_children(std::forward<function>(_func)...);
134 template <
typename function>
135 void add_children (
const function &_func)
137 internal::function_invoker<function>* invoker =
new (allocate_child()) internal::function_invoker<function>(_func);
138 __TBB_ASSERT(invoker,
"Child task allocation failed");
144 template <
typename function1,
typename function2>
145 void add_children (
const function1& _func1,
const function2& _func2)
148 parallel_invoke_noop noop;
149 internal::spawner<2, function1, function2, parallel_invoke_noop>& sub_root = *
new(allocate_child())internal::spawner<2, function1, function2, parallel_invoke_noop>(_func1, _func2, noop);
153 template <
typename function1,
typename function2,
typename function3>
154 void add_children (
const function1& _func1,
const function2& _func2,
const function3& _func3)
156 internal::spawner<3, function1, function2, function3>& sub_root = *
new(allocate_child())internal::spawner<3, function1, function2, function3>(_func1, _func2, _func3);
159 #endif // __TBB_VARIADIC_PARALLEL_INVOKE 162 template <
typename F0>
163 void run_and_finish(
const F0& f0)
165 internal::function_invoker<F0>* invoker =
new (allocate_child()) internal::function_invoker<F0>(f0);
166 __TBB_ASSERT(invoker,
"Child task allocation failed");
167 spawn_and_wait_for_all(*invoker);
171 class parallel_invoke_cleaner: internal::no_copy {
173 #if __TBB_TASK_GROUP_CONTEXT 174 parallel_invoke_cleaner(
int number_of_children, tbb::task_group_context& context)
175 : root(*new(task::allocate_root(context))
internal::parallel_invoke_helper(number_of_children))
177 parallel_invoke_cleaner(int number_of_children,
tbb::task_group_context&)
178 : root(*new(task::allocate_root())
internal::parallel_invoke_helper(number_of_children))
182 ~parallel_invoke_cleaner(){
185 internal::parallel_invoke_helper& root;
188 #if __TBB_VARIADIC_PARALLEL_INVOKE 190 template<
typename... T>
struct impl_selector;
192 template<
typename T1,
typename... T>
struct impl_selector<T1, T...> {
193 typedef typename impl_selector<T...>::type type;
196 template<
typename T>
struct impl_selector<T> {
197 typedef false_type type;
199 template<>
struct impl_selector<task_group_context&> {
200 typedef true_type type;
204 inline task_group_context& get_context( task_group_context& tgc ) {
return tgc; }
206 template<
typename T1,
typename... T>
207 task_group_context& get_context( T1&& , T&&... t )
208 {
return get_context( std::forward<T>(t)... ); }
211 template<
typename F0,
typename F1,
typename... F>
212 void parallel_invoke_impl(true_type, F0&& f0, F1&& f1, F&&... f) {
213 __TBB_STATIC_ASSERT(
sizeof...(F)>0,
"Variadic parallel_invoke implementation broken?");
215 const size_t number_of_children = 2 +
sizeof...(F)/2;
216 parallel_invoke_cleaner cleaner(number_of_children, get_context(std::forward<F>(f)...));
217 parallel_invoke_helper& root = cleaner.root;
219 root.add_children(std::forward<F>(f)...);
220 root.add_children(std::forward<F1>(f1));
221 root.run_and_finish(std::forward<F0>(f0));
225 template<
typename F0,
typename F1,
typename... F>
226 void parallel_invoke_impl(false_type, F0&& f0, F1&& f1, F&&... f) {
227 tbb::task_group_context context;
229 parallel_invoke_impl(true_type(), std::forward<F0>(f0), std::forward<F1>(f1), std::forward<F>(f)..., context);
241 #if __TBB_VARIADIC_PARALLEL_INVOKE 245 template<
typename F0,
typename F1,
typename... F>
247 typedef typename internal::impl_selector<internal::false_type, F...>::type selector_type;
248 internal::parallel_invoke_impl(selector_type(), std::forward<F0>(f0), std::forward<F1>(f1), std::forward<F>(f)...);
255 template<
typename F0,
typename F1 >
257 internal::parallel_invoke_cleaner cleaner(2, context);
258 internal::parallel_invoke_helper& root = cleaner.root;
260 root.add_children(f1);
262 root.run_and_finish(f0);
266 template<
typename F0,
typename F1,
typename F2 >
267 void parallel_invoke(
const F0& f0,
const F1& f1,
const F2& f2, tbb::task_group_context& context) {
268 internal::parallel_invoke_cleaner cleaner(3, context);
269 internal::parallel_invoke_helper& root = cleaner.root;
271 root.add_children(f2);
272 root.add_children(f1);
274 root.run_and_finish(f0);
278 template<
typename F0,
typename F1,
typename F2,
typename F3>
279 void parallel_invoke(
const F0& f0,
const F1& f1,
const F2& f2,
const F3& f3,
280 tbb::task_group_context& context)
282 internal::parallel_invoke_cleaner cleaner(4, context);
283 internal::parallel_invoke_helper& root = cleaner.root;
285 root.add_children(f3);
286 root.add_children(f2);
287 root.add_children(f1);
289 root.run_and_finish(f0);
293 template<
typename F0,
typename F1,
typename F2,
typename F3,
typename F4 >
294 void parallel_invoke(
const F0& f0,
const F1& f1,
const F2& f2,
const F3& f3,
const F4& f4,
295 tbb::task_group_context& context)
297 internal::parallel_invoke_cleaner cleaner(3, context);
298 internal::parallel_invoke_helper& root = cleaner.root;
300 root.add_children(f4, f3);
301 root.add_children(f2, f1);
303 root.run_and_finish(f0);
307 template<
typename F0,
typename F1,
typename F2,
typename F3,
typename F4,
typename F5>
308 void parallel_invoke(
const F0& f0,
const F1& f1,
const F2& f2,
const F3& f3,
const F4& f4,
const F5& f5,
309 tbb::task_group_context& context)
311 internal::parallel_invoke_cleaner cleaner(3, context);
312 internal::parallel_invoke_helper& root = cleaner.root;
314 root.add_children(f5, f4, f3);
315 root.add_children(f2, f1);
317 root.run_and_finish(f0);
321 template<
typename F0,
typename F1,
typename F2,
typename F3,
typename F4,
typename F5,
typename F6>
322 void parallel_invoke(
const F0& f0,
const F1& f1,
const F2& f2,
const F3& f3,
const F4& f4,
323 const F5& f5,
const F6& f6,
324 tbb::task_group_context& context)
326 internal::parallel_invoke_cleaner cleaner(3, context);
327 internal::parallel_invoke_helper& root = cleaner.root;
329 root.add_children(f6, f5, f4);
330 root.add_children(f3, f2, f1);
332 root.run_and_finish(f0);
336 template<
typename F0,
typename F1,
typename F2,
typename F3,
typename F4,
337 typename F5,
typename F6,
typename F7>
338 void parallel_invoke(
const F0& f0,
const F1& f1,
const F2& f2,
const F3& f3,
const F4& f4,
339 const F5& f5,
const F6& f6,
const F7& f7,
340 tbb::task_group_context& context)
342 internal::parallel_invoke_cleaner cleaner(4, context);
343 internal::parallel_invoke_helper& root = cleaner.root;
345 root.add_children(f7, f6, f5);
346 root.add_children(f4, f3);
347 root.add_children(f2, f1);
349 root.run_and_finish(f0);
353 template<
typename F0,
typename F1,
typename F2,
typename F3,
typename F4,
354 typename F5,
typename F6,
typename F7,
typename F8>
355 void parallel_invoke(
const F0& f0,
const F1& f1,
const F2& f2,
const F3& f3,
const F4& f4,
356 const F5& f5,
const F6& f6,
const F7& f7,
const F8& f8,
357 tbb::task_group_context& context)
359 internal::parallel_invoke_cleaner cleaner(4, context);
360 internal::parallel_invoke_helper& root = cleaner.root;
362 root.add_children(f8, f7, f6);
363 root.add_children(f5, f4, f3);
364 root.add_children(f2, f1);
366 root.run_and_finish(f0);
370 template<
typename F0,
typename F1,
typename F2,
typename F3,
typename F4,
371 typename F5,
typename F6,
typename F7,
typename F8,
typename F9>
372 void parallel_invoke(
const F0& f0,
const F1& f1,
const F2& f2,
const F3& f3,
const F4& f4,
373 const F5& f5,
const F6& f6,
const F7& f7,
const F8& f8,
const F9& f9,
374 tbb::task_group_context& context)
376 internal::parallel_invoke_cleaner cleaner(4, context);
377 internal::parallel_invoke_helper& root = cleaner.root;
379 root.add_children(f9, f8, f7);
380 root.add_children(f6, f5, f4);
381 root.add_children(f3, f2, f1);
383 root.run_and_finish(f0);
387 template<
typename F0,
typename F1>
389 task_group_context context;
390 parallel_invoke<F0, F1>(f0, f1, context);
393 template<
typename F0,
typename F1,
typename F2>
395 task_group_context context;
396 parallel_invoke<F0, F1, F2>(f0, f1, f2, context);
399 template<
typename F0,
typename F1,
typename F2,
typename F3 >
400 void parallel_invoke(
const F0& f0,
const F1& f1,
const F2& f2,
const F3& f3) {
401 task_group_context context;
402 parallel_invoke<F0, F1, F2, F3>(f0, f1, f2, f3, context);
405 template<
typename F0,
typename F1,
typename F2,
typename F3,
typename F4>
406 void parallel_invoke(
const F0& f0,
const F1& f1,
const F2& f2,
const F3& f3,
const F4& f4) {
407 task_group_context context;
408 parallel_invoke<F0, F1, F2, F3, F4>(f0, f1, f2, f3, f4, context);
411 template<
typename F0,
typename F1,
typename F2,
typename F3,
typename F4,
typename F5>
412 void parallel_invoke(
const F0& f0,
const F1& f1,
const F2& f2,
const F3& f3,
const F4& f4,
const F5& f5) {
413 task_group_context context;
414 parallel_invoke<F0, F1, F2, F3, F4, F5>(f0, f1, f2, f3, f4, f5, context);
417 template<
typename F0,
typename F1,
typename F2,
typename F3,
typename F4,
typename F5,
typename F6>
418 void parallel_invoke(
const F0& f0,
const F1& f1,
const F2& f2,
const F3& f3,
const F4& f4,
419 const F5& f5,
const F6& f6)
421 task_group_context context;
422 parallel_invoke<F0, F1, F2, F3, F4, F5, F6>(f0, f1, f2, f3, f4, f5, f6, context);
425 template<
typename F0,
typename F1,
typename F2,
typename F3,
typename F4,
426 typename F5,
typename F6,
typename F7>
427 void parallel_invoke(
const F0& f0,
const F1& f1,
const F2& f2,
const F3& f3,
const F4& f4,
428 const F5& f5,
const F6& f6,
const F7& f7)
430 task_group_context context;
431 parallel_invoke<F0, F1, F2, F3, F4, F5, F6, F7>(f0, f1, f2, f3, f4, f5, f6, f7, context);
434 template<
typename F0,
typename F1,
typename F2,
typename F3,
typename F4,
435 typename F5,
typename F6,
typename F7,
typename F8>
436 void parallel_invoke(
const F0& f0,
const F1& f1,
const F2& f2,
const F3& f3,
const F4& f4,
437 const F5& f5,
const F6& f6,
const F7& f7,
const F8& f8)
439 task_group_context context;
440 parallel_invoke<F0, F1, F2, F3, F4, F5, F6, F7, F8>(f0, f1, f2, f3, f4, f5, f6, f7, f8, context);
443 template<
typename F0,
typename F1,
typename F2,
typename F3,
typename F4,
444 typename F5,
typename F6,
typename F7,
typename F8,
typename F9>
445 void parallel_invoke(
const F0& f0,
const F1& f1,
const F2& f2,
const F3& f3,
const F4& f4,
446 const F5& f5,
const F6& f6,
const F7& f7,
const F8& f8,
const F9& f9)
448 task_group_context context;
449 parallel_invoke<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9>(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, context);
451 #endif // __TBB_VARIADIC_PARALLEL_INVOKE */
Definition: material.h:665
Definition: _flow_graph_async_msg_impl.h:32
void parallel_invoke(const F0 &f0, const F1 &f1, tbb::task_group_context &context)
Executes a list of tasks in parallel and waits for all tasks to complete.
Definition: parallel_invoke.h:256
The namespace tbb contains all components of the library.
Definition: parallel_for.h:44