00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00038 task* execute()
00039 {
00040 my_function();
00041 return NULL;
00042 }
00043 };
00044
00045
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;
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 }
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
00081 class parallel_invoke_helper : public empty_task {
00082 public:
00083
00084 class parallel_invoke_noop {
00085 public:
00086 void operator() () const {}
00087 };
00088
00089 parallel_invoke_helper(int number_of_children)
00090 {
00091 set_ref_count(number_of_children + 1);
00092 }
00093
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
00103
00104 template <typename function1, typename function2>
00105 void add_children (const function1& _func1, const function2& _func2)
00106 {
00107
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
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
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
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 }
00141
00145
00146
00148
00149
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
00350
00351 #endif