![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
00001 /* 00002 Copyright 2005-2010 Intel Corporation. All Rights Reserved. 00003 00004 This file is part of Threading Building Blocks. 00005 00006 Threading Building Blocks is free software; you can redistribute it 00007 and/or modify it under the terms of the GNU General Public License 00008 version 2 as published by the Free Software Foundation. 00009 00010 Threading Building Blocks is distributed in the hope that it will be 00011 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00012 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with Threading Building Blocks; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 00019 As a special exception, you may use this file as part of a free software 00020 library without restriction. Specifically, if other files instantiate 00021 templates or use macros or inline functions from this file, or you compile 00022 this file and link it with other files to produce an executable, this 00023 file does not by itself cause the resulting executable to be covered by 00024 the GNU General Public License. This exception does not however 00025 invalidate any other reasons why the executable file might be covered by 00026 the GNU General Public License. 00027 */ 00028 00029 #ifndef __TBB_parallel_invoke_H 00030 #define __TBB_parallel_invoke_H 00031 00032 #include "task.h" 00033 00034 namespace tbb { 00035 00037 namespace internal { 00038 // Simple task object, executing user method 00039 template<typename function> 00040 class function_invoker : public task{ 00041 public: 00042 function_invoker(const function& _function) : my_function(_function) {} 00043 private: 00044 const function &my_function; 00045 /*override*/ 00046 task* execute() 00047 { 00048 my_function(); 00049 return NULL; 00050 } 00051 }; 00052 00053 // The class spawns two or three child tasks 00054 template <size_t N, typename function1, typename function2, typename function3> 00055 class spawner : public task { 00056 private: 00057 const function1& my_func1; 00058 const function2& my_func2; 00059 const function3& my_func3; 00060 bool is_recycled; 00061 00062 task* execute (){ 00063 if(is_recycled){ 00064 return NULL; 00065 }else{ 00066 __TBB_ASSERT(N==2 || N==3, "Number of arguments passed to spawner is wrong"); 00067 set_ref_count(N); 00068 recycle_as_safe_continuation(); 00069 internal::function_invoker<function2>* invoker2 = new (allocate_child()) internal::function_invoker<function2>(my_func2); 00070 __TBB_ASSERT(invoker2, "Child task allocation failed"); 00071 spawn(*invoker2); 00072 size_t n = N; // To prevent compiler warnings 00073 if (n>2) { 00074 internal::function_invoker<function3>* invoker3 = new (allocate_child()) internal::function_invoker<function3>(my_func3); 00075 __TBB_ASSERT(invoker3, "Child task allocation failed"); 00076 spawn(*invoker3); 00077 } 00078 my_func1(); 00079 is_recycled = true; 00080 return NULL; 00081 } 00082 } // execute 00083 00084 public: 00085 spawner(const function1& _func1, const function2& _func2, const function3& _func3) : my_func1(_func1), my_func2(_func2), my_func3(_func3), is_recycled(false) {} 00086 }; 00087 00088 // Creates and spawns child tasks 00089 class parallel_invoke_helper : public empty_task { 00090 public: 00091 // Dummy functor class 00092 class parallel_invoke_noop { 00093 public: 00094 void operator() () const {} 00095 }; 00096 // Creates a helper object with user-defined number of children expected 00097 parallel_invoke_helper(int number_of_children) 00098 { 00099 set_ref_count(number_of_children + 1); 00100 } 00101 // Adds child task and spawns it 00102 template <typename function> 00103 void add_child (const function &_func) 00104 { 00105 internal::function_invoker<function>* invoker = new (allocate_child()) internal::function_invoker<function>(_func); 00106 __TBB_ASSERT(invoker, "Child task allocation failed"); 00107 spawn(*invoker); 00108 } 00109 00110 // Adds a task with multiple child tasks and spawns it 00111 // two arguments 00112 template <typename function1, typename function2> 00113 void add_children (const function1& _func1, const function2& _func2) 00114 { 00115 // The third argument is dummy, it is ignored actually. 00116 parallel_invoke_noop noop; 00117 internal::spawner<2, function1, function2, parallel_invoke_noop>& sub_root = *new(allocate_child())internal::spawner<2, function1, function2, parallel_invoke_noop>(_func1, _func2, noop); 00118 spawn(sub_root); 00119 } 00120 // three arguments 00121 template <typename function1, typename function2, typename function3> 00122 void add_children (const function1& _func1, const function2& _func2, const function3& _func3) 00123 { 00124 internal::spawner<3, function1, function2, function3>& sub_root = *new(allocate_child())internal::spawner<3, function1, function2, function3>(_func1, _func2, _func3); 00125 spawn(sub_root); 00126 } 00127 00128 // Waits for all child tasks 00129 template <typename F0> 00130 void run_and_finish(const F0& f0) 00131 { 00132 internal::function_invoker<F0>* invoker = new (allocate_child()) internal::function_invoker<F0>(f0); 00133 __TBB_ASSERT(invoker, "Child task allocation failed"); 00134 spawn_and_wait_for_all(*invoker); 00135 } 00136 }; 00137 // The class destroys root if exception occured as well as in normal case 00138 class parallel_invoke_cleaner: internal::no_copy { 00139 public: 00140 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)) 00141 {} 00142 ~parallel_invoke_cleaner(){ 00143 root.destroy(root); 00144 } 00145 internal::parallel_invoke_helper& root; 00146 }; 00147 } // namespace internal 00149 00153 00154 00156 // parallel_invoke with user-defined context 00157 // two arguments 00158 template<typename F0, typename F1 > 00159 void parallel_invoke(const F0& f0, const F1& f1, tbb::task_group_context& context) { 00160 internal::parallel_invoke_cleaner cleaner(2, context); 00161 internal::parallel_invoke_helper& root = cleaner.root; 00162 00163 root.add_child(f1); 00164 00165 root.run_and_finish(f0); 00166 } 00167 00168 // three arguments 00169 template<typename F0, typename F1, typename F2 > 00170 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, tbb::task_group_context& context) { 00171 internal::parallel_invoke_cleaner cleaner(3, context); 00172 internal::parallel_invoke_helper& root = cleaner.root; 00173 00174 root.add_child(f2); 00175 root.add_child(f1); 00176 00177 root.run_and_finish(f0); 00178 } 00179 00180 // four arguments 00181 template<typename F0, typename F1, typename F2, typename F3> 00182 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, 00183 tbb::task_group_context& context) 00184 { 00185 internal::parallel_invoke_cleaner cleaner(4, context); 00186 internal::parallel_invoke_helper& root = cleaner.root; 00187 00188 root.add_child(f3); 00189 root.add_child(f2); 00190 root.add_child(f1); 00191 00192 root.run_and_finish(f0); 00193 } 00194 00195 // five arguments 00196 template<typename F0, typename F1, typename F2, typename F3, typename F4 > 00197 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, 00198 tbb::task_group_context& context) 00199 { 00200 internal::parallel_invoke_cleaner cleaner(3, context); 00201 internal::parallel_invoke_helper& root = cleaner.root; 00202 00203 root.add_children(f4, f3); 00204 root.add_children(f2, f1); 00205 00206 root.run_and_finish(f0); 00207 } 00208 00209 // six arguments 00210 template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5> 00211 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, const F5& f5, 00212 tbb::task_group_context& context) 00213 { 00214 internal::parallel_invoke_cleaner cleaner(3, context); 00215 internal::parallel_invoke_helper& root = cleaner.root; 00216 00217 root.add_children(f5, f4, f3); 00218 root.add_children(f2, f1); 00219 00220 root.run_and_finish(f0); 00221 } 00222 00223 // seven arguments 00224 template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6> 00225 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, 00226 const F5& f5, const F6& f6, 00227 tbb::task_group_context& context) 00228 { 00229 internal::parallel_invoke_cleaner cleaner(3, context); 00230 internal::parallel_invoke_helper& root = cleaner.root; 00231 00232 root.add_children(f6, f5, f4); 00233 root.add_children(f3, f2, f1); 00234 00235 root.run_and_finish(f0); 00236 } 00237 00238 // eight arguments 00239 template<typename F0, typename F1, typename F2, typename F3, typename F4, 00240 typename F5, typename F6, typename F7> 00241 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, 00242 const F5& f5, const F6& f6, const F7& f7, 00243 tbb::task_group_context& context) 00244 { 00245 internal::parallel_invoke_cleaner cleaner(4, context); 00246 internal::parallel_invoke_helper& root = cleaner.root; 00247 00248 root.add_children(f7, f6, f5); 00249 root.add_children(f4, f3); 00250 root.add_children(f2, f1); 00251 00252 root.run_and_finish(f0); 00253 } 00254 00255 // nine arguments 00256 template<typename F0, typename F1, typename F2, typename F3, typename F4, 00257 typename F5, typename F6, typename F7, typename F8> 00258 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, 00259 const F5& f5, const F6& f6, const F7& f7, const F8& f8, 00260 tbb::task_group_context& context) 00261 { 00262 internal::parallel_invoke_cleaner cleaner(4, context); 00263 internal::parallel_invoke_helper& root = cleaner.root; 00264 00265 root.add_children(f8, f7, f6); 00266 root.add_children(f5, f4, f3); 00267 root.add_children(f2, f1); 00268 00269 root.run_and_finish(f0); 00270 } 00271 00272 // ten arguments 00273 template<typename F0, typename F1, typename F2, typename F3, typename F4, 00274 typename F5, typename F6, typename F7, typename F8, typename F9> 00275 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, 00276 const F5& f5, const F6& f6, const F7& f7, const F8& f8, const F9& f9, 00277 tbb::task_group_context& context) 00278 { 00279 internal::parallel_invoke_cleaner cleaner(4, context); 00280 internal::parallel_invoke_helper& root = cleaner.root; 00281 00282 root.add_children(f9, f8, f7); 00283 root.add_children(f6, f5, f4); 00284 root.add_children(f3, f2, f1); 00285 00286 root.run_and_finish(f0); 00287 } 00288 00289 // two arguments 00290 template<typename F0, typename F1> 00291 void parallel_invoke(const F0& f0, const F1& f1) { 00292 task_group_context context; 00293 parallel_invoke<F0, F1>(f0, f1, context); 00294 } 00295 // three arguments 00296 template<typename F0, typename F1, typename F2> 00297 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2) { 00298 task_group_context context; 00299 parallel_invoke<F0, F1, F2>(f0, f1, f2, context); 00300 } 00301 // four arguments 00302 template<typename F0, typename F1, typename F2, typename F3 > 00303 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3) { 00304 task_group_context context; 00305 parallel_invoke<F0, F1, F2, F3>(f0, f1, f2, f3, context); 00306 } 00307 // five arguments 00308 template<typename F0, typename F1, typename F2, typename F3, typename F4> 00309 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4) { 00310 task_group_context context; 00311 parallel_invoke<F0, F1, F2, F3, F4>(f0, f1, f2, f3, f4, context); 00312 } 00313 // six arguments 00314 template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5> 00315 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, const F5& f5) { 00316 task_group_context context; 00317 parallel_invoke<F0, F1, F2, F3, F4, F5>(f0, f1, f2, f3, f4, f5, context); 00318 } 00319 // seven arguments 00320 template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6> 00321 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, 00322 const F5& f5, const F6& f6) 00323 { 00324 task_group_context context; 00325 parallel_invoke<F0, F1, F2, F3, F4, F5, F6>(f0, f1, f2, f3, f4, f5, f6, context); 00326 } 00327 // eigth arguments 00328 template<typename F0, typename F1, typename F2, typename F3, typename F4, 00329 typename F5, typename F6, typename F7> 00330 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, 00331 const F5& f5, const F6& f6, const F7& f7) 00332 { 00333 task_group_context context; 00334 parallel_invoke<F0, F1, F2, F3, F4, F5, F6, F7>(f0, f1, f2, f3, f4, f5, f6, f7, context); 00335 } 00336 // nine arguments 00337 template<typename F0, typename F1, typename F2, typename F3, typename F4, 00338 typename F5, typename F6, typename F7, typename F8> 00339 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, 00340 const F5& f5, const F6& f6, const F7& f7, const F8& f8) 00341 { 00342 task_group_context context; 00343 parallel_invoke<F0, F1, F2, F3, F4, F5, F6, F7, F8>(f0, f1, f2, f3, f4, f5, f6, f7, f8, context); 00344 } 00345 // ten arguments 00346 template<typename F0, typename F1, typename F2, typename F3, typename F4, 00347 typename F5, typename F6, typename F7, typename F8, typename F9> 00348 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, 00349 const F5& f5, const F6& f6, const F7& f7, const F8& f8, const F9& f9) 00350 { 00351 task_group_context context; 00352 parallel_invoke<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9>(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, context); 00353 } 00354 00356 00357 } // namespace 00358 00359 #endif /* __TBB_parallel_invoke_H */
Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.