parallel_invoke.h Source File

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# parallel_invoke.h

    00001 /*
    00002     Copyright 2005-2010 Intel Corporation.  All Rights Reserved.
    00003
    00004     The source code contained or described herein and all documents related
    00005     to the source code ("Material") are owned by Intel Corporation or its
    00006     suppliers or licensors.  Title to the Material remains with Intel
    00007     Corporation or its suppliers and licensors.  The Material is protected
    00008     by worldwide copyright laws and treaty provisions.  No part of the
    00009     Material may be used, copied, reproduced, modified, published, uploaded,
    00010     posted, transmitted, distributed, or disclosed in any way without
    00011     Intel's prior express written permission.
    00012
    00013     No license under any patent, copyright, trade secret or other
    00014     intellectual property right is granted to or conferred upon you by
    00015     disclosure or delivery of the Materials, either expressly, by
    00016     implication, inducement, estoppel or otherwise.  Any license under such
    00017     intellectual property rights must be express and approved by Intel in
    00018     writing.
    00019 */
    00020
    00021 #ifndef __TBB_parallel_invoke_H
    00022 #define __TBB_parallel_invoke_H
    00023
    00024 #include "task.h"
    00025
    00026 namespace tbb {
    00027
    00029 namespace internal {
    00030     // Simple task object, executing user method
    00031     template<typename function>
    00032     class function_invoker : public task{
    00033     public:
    00034         function_invoker(const function& _function) : my_function(_function) {}
    00035     private:
    00036         const function &my_function;
    00037         /*override*/
    00038         task* execute()
    00039         {
    00040             my_function();
    00041             return NULL;
    00042         }
    00043     };
    00044
    00045     // The class spawns two or three child tasks
    00046     template <size_t N, typename function1, typename function2, typename function3>
    00047     class spawner : public task {
    00048     private:
    00049         const function1& my_func1;
    00050         const function2& my_func2;
    00051         const function3& my_func3;
    00052         bool is_recycled;
    00053
    00054         task* execute (){
    00055             if(is_recycled){
    00056                 return NULL;
    00057             }else{
    00058                 __TBB_ASSERT(N==2 || N==3, "Number of arguments passed to spawner is wrong");
    00059                 set_ref_count(N);
    00060                 recycle_as_safe_continuation();
    00061                 internal::function_invoker<function2>* invoker2 = new (allocate_child()) internal::function_invoker<function2>(my_func2);
    00062                 __TBB_ASSERT(invoker2, "Child task allocation failed");
    00063                 spawn(*invoker2);
    00064                 size_t n = N; // To prevent compiler warnings
    00065                 if (n>2) {
    00066                     internal::function_invoker<function3>* invoker3 = new (allocate_child()) internal::function_invoker<function3>(my_func3);
    00067                     __TBB_ASSERT(invoker3, "Child task allocation failed");
    00068                     spawn(*invoker3);
    00069                 }
    00070                 my_func1();
    00071                 is_recycled = true;
    00072                 return NULL;
    00073             }
    00074         } // execute
    00075
    00076     public:
    00077         spawner(const function1& _func1, const function2& _func2, const function3& _func3) : my_func1(_func1), my_func2(_func2), my_func3(_func3), is_recycled(false) {}
    00078     };
    00079
    00080     // Creates and spawns child tasks
    00081     class parallel_invoke_helper : public empty_task {
    00082     public:
    00083         // Dummy functor class
    00084         class parallel_invoke_noop {
    00085         public:
    00086             void operator() () const {}
    00087         };
    00088         // Creates a helper object with user-defined number of children expected
    00089         parallel_invoke_helper(int number_of_children)
    00090         {
    00091             set_ref_count(number_of_children + 1);
    00092         }
    00093         // Adds child task and spawns it
    00094         template <typename function>
    00095         void add_child (const function &_func)
    00096         {
    00097             internal::function_invoker<function>* invoker = new (allocate_child()) internal::function_invoker<function>(_func);
    00098             __TBB_ASSERT(invoker, "Child task allocation failed");
    00099             spawn(*invoker);
    00100         }
    00101
    00102         // Adds a task with multiple child tasks and spawns it
    00103         // two arguments
    00104         template <typename function1, typename function2>
    00105         void add_children (const function1& _func1, const function2& _func2)
    00106         {
    00107             // The third argument is dummy, it is ignored actually.
    00108             parallel_invoke_noop noop;
    00109             internal::spawner<2, function1, function2, parallel_invoke_noop>& sub_root = *new(allocate_child())internal::spawner<2, function1, function2, parallel_invoke_noop>(_func1, _func2, noop);
    00110             spawn(sub_root);
    00111         }
    00112         // three arguments
    00113         template <typename function1, typename function2, typename function3>
    00114         void add_children (const function1& _func1, const function2& _func2, const function3& _func3)
    00115         {
    00116             internal::spawner<3, function1, function2, function3>& sub_root = *new(allocate_child())internal::spawner<3, function1, function2, function3>(_func1, _func2, _func3);
    00117             spawn(sub_root);
    00118         }
    00119
    00120         // Waits for all child tasks
    00121         template <typename F0>
    00122         void run_and_finish(const F0& f0)
    00123         {
    00124             internal::function_invoker<F0>* invoker = new (allocate_child()) internal::function_invoker<F0>(f0);
    00125             __TBB_ASSERT(invoker, "Child task allocation failed");
    00126             spawn_and_wait_for_all(*invoker);
    00127         }
    00128     };
    00129     // The class destroys root if exception occured as well as in normal case
    00130     class parallel_invoke_cleaner: internal::no_copy {
    00131     public:
    00132         parallel_invoke_cleaner(int number_of_children, tbb::task_group_context& context) : root(*new(task::allocate_root(context)) internal::parallel_invoke_helper(number_of_children))
    00133         {}
    00134         ~parallel_invoke_cleaner(){
    00135             root.destroy(root);
    00136         }
    00137         internal::parallel_invoke_helper& root;
    00138     };
    00139 } // namespace internal
    00141
    00145
    00146
    00148 // parallel_invoke with user-defined context
    00149 // two arguments
    00150 template<typename F0, typename F1 >
    00151 void parallel_invoke(const F0& f0, const F1& f1, tbb::task_group_context& context) {
    00152     internal::parallel_invoke_cleaner cleaner(2, context);
    00153     internal::parallel_invoke_helper& root = cleaner.root;
    00154
    00155     root.add_child(f1);
    00156
    00157     root.run_and_finish(f0);
    00158 }
    00159
    00160 // three arguments
    00161 template<typename F0, typename F1, typename F2 >
    00162 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, tbb::task_group_context& context) {
    00163     internal::parallel_invoke_cleaner cleaner(3, context);
    00164     internal::parallel_invoke_helper& root = cleaner.root;
    00165
    00166     root.add_child(f2);
    00167     root.add_child(f1);
    00168
    00169     root.run_and_finish(f0);
    00170 }
    00171
    00172 // four arguments
    00173 template<typename F0, typename F1, typename F2, typename F3>
    00174 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3,
    00175                      tbb::task_group_context& context)
    00176 {
    00177     internal::parallel_invoke_cleaner cleaner(4, context);
    00178     internal::parallel_invoke_helper& root = cleaner.root;
    00179
    00180     root.add_child(f3);
    00181     root.add_child(f2);
    00182     root.add_child(f1);
    00183
    00184     root.run_and_finish(f0);
    00185 }
    00186
    00187 // five arguments
    00188 template<typename F0, typename F1, typename F2, typename F3, typename F4 >
    00189 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
    00190                      tbb::task_group_context& context)
    00191 {
    00192     internal::parallel_invoke_cleaner cleaner(3, context);
    00193     internal::parallel_invoke_helper& root = cleaner.root;
    00194
    00195     root.add_children(f4, f3);
    00196     root.add_children(f2, f1);
    00197
    00198     root.run_and_finish(f0);
    00199 }
    00200
    00201 // six arguments
    00202 template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5>
    00203 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, const F5& f5,
    00204                      tbb::task_group_context& context)
    00205 {
    00206     internal::parallel_invoke_cleaner cleaner(3, context);
    00207     internal::parallel_invoke_helper& root = cleaner.root;
    00208
    00209     root.add_children(f5, f4, f3);
    00210     root.add_children(f2, f1);
    00211
    00212     root.run_and_finish(f0);
    00213 }
    00214
    00215 // seven arguments
    00216 template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6>
    00217 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
    00218                      const F5& f5, const F6& f6,
    00219                      tbb::task_group_context& context)
    00220 {
    00221     internal::parallel_invoke_cleaner cleaner(3, context);
    00222     internal::parallel_invoke_helper& root = cleaner.root;
    00223
    00224     root.add_children(f6, f5, f4);
    00225     root.add_children(f3, f2, f1);
    00226
    00227     root.run_and_finish(f0);
    00228 }
    00229
    00230 // eight arguments
    00231 template<typename F0, typename F1, typename F2, typename F3, typename F4,
    00232          typename F5, typename F6, typename F7>
    00233 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
    00234                      const F5& f5, const F6& f6, const F7& f7,
    00235                      tbb::task_group_context& context)
    00236 {
    00237     internal::parallel_invoke_cleaner cleaner(4, context);
    00238     internal::parallel_invoke_helper& root = cleaner.root;
    00239
    00240     root.add_children(f7, f6, f5);
    00241     root.add_children(f4, f3);
    00242     root.add_children(f2, f1);
    00243
    00244     root.run_and_finish(f0);
    00245 }
    00246
    00247 // nine arguments
    00248 template<typename F0, typename F1, typename F2, typename F3, typename F4,
    00249          typename F5, typename F6, typename F7, typename F8>
    00250 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
    00251                      const F5& f5, const F6& f6, const F7& f7, const F8& f8,
    00252                      tbb::task_group_context& context)
    00253 {
    00254     internal::parallel_invoke_cleaner cleaner(4, context);
    00255     internal::parallel_invoke_helper& root = cleaner.root;
    00256
    00257     root.add_children(f8, f7, f6);
    00258     root.add_children(f5, f4, f3);
    00259     root.add_children(f2, f1);
    00260
    00261     root.run_and_finish(f0);
    00262 }
    00263
    00264 // ten arguments
    00265 template<typename F0, typename F1, typename F2, typename F3, typename F4,
    00266          typename F5, typename F6, typename F7, typename F8, typename F9>
    00267 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
    00268                      const F5& f5, const F6& f6, const F7& f7, const F8& f8, const F9& f9,
    00269                      tbb::task_group_context& context)
    00270 {
    00271     internal::parallel_invoke_cleaner cleaner(4, context);
    00272     internal::parallel_invoke_helper& root = cleaner.root;
    00273
    00274     root.add_children(f9, f8, f7);
    00275     root.add_children(f6, f5, f4);
    00276     root.add_children(f3, f2, f1);
    00277
    00278     root.run_and_finish(f0);
    00279 }
    00280
    00281 // two arguments
    00282 template<typename F0, typename F1>
    00283 void parallel_invoke(const F0& f0, const F1& f1) {
    00284     task_group_context context;
    00285     parallel_invoke<F0, F1>(f0, f1, context);
    00286 }
    00287 // three arguments
    00288 template<typename F0, typename F1, typename F2>
    00289 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2) {
    00290     task_group_context context;
    00291     parallel_invoke<F0, F1, F2>(f0, f1, f2, context);
    00292 }
    00293 // four arguments
    00294 template<typename F0, typename F1, typename F2, typename F3 >
    00295 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3) {
    00296     task_group_context context;
    00297     parallel_invoke<F0, F1, F2, F3>(f0, f1, f2, f3, context);
    00298 }
    00299 // five arguments
    00300 template<typename F0, typename F1, typename F2, typename F3, typename F4>
    00301 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4) {
    00302     task_group_context context;
    00303     parallel_invoke<F0, F1, F2, F3, F4>(f0, f1, f2, f3, f4, context);
    00304 }
    00305 // six arguments
    00306 template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5>
    00307 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, const F5& f5) {
    00308     task_group_context context;
    00309     parallel_invoke<F0, F1, F2, F3, F4, F5>(f0, f1, f2, f3, f4, f5, context);
    00310 }
    00311 // seven arguments
    00312 template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6>
    00313 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
    00314                      const F5& f5, const F6& f6)
    00315 {
    00316     task_group_context context;
    00317     parallel_invoke<F0, F1, F2, F3, F4, F5, F6>(f0, f1, f2, f3, f4, f5, f6, context);
    00318 }
    00319 // eigth arguments
    00320 template<typename F0, typename F1, typename F2, typename F3, typename F4,
    00321          typename F5, typename F6, typename F7>
    00322 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
    00323                      const F5& f5, const F6& f6, const F7& f7)
    00324 {
    00325     task_group_context context;
    00326     parallel_invoke<F0, F1, F2, F3, F4, F5, F6, F7>(f0, f1, f2, f3, f4, f5, f6, f7, context);
    00327 }
    00328 // nine arguments
    00329 template<typename F0, typename F1, typename F2, typename F3, typename F4,
    00330          typename F5, typename F6, typename F7, typename F8>
    00331 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
    00332                      const F5& f5, const F6& f6, const F7& f7, const F8& f8)
    00333 {
    00334     task_group_context context;
    00335     parallel_invoke<F0, F1, F2, F3, F4, F5, F6, F7, F8>(f0, f1, f2, f3, f4, f5, f6, f7, f8, context);
    00336 }
    00337 // ten arguments
    00338 template<typename F0, typename F1, typename F2, typename F3, typename F4,
    00339          typename F5, typename F6, typename F7, typename F8, typename F9>
    00340 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
    00341                      const F5& f5, const F6& f6, const F7& f7, const F8& f8, const F9& f9)
    00342 {
    00343     task_group_context context;
    00344     parallel_invoke<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9>(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, context);
    00345 }
    00346
    00348
    00349 } // namespace
    00350
    00351 #endif /* __TBB_parallel_invoke_H */

Copyright © 2005-2010 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.