PFUNC
1.0
|
00001 #ifndef PFUNC_HPP 00002 #define PFUNC_HPP 00003 00015 #include <pfunc/pfunc_common.h> 00016 #include <pfunc/exception.hpp> 00017 #include <pfunc/mutex.hpp> 00018 #include <pfunc/event.hpp> 00019 #include <pfunc/thread.hpp> 00020 #include <pfunc/trampolines.hpp> 00021 #include <pfunc/group.hpp> 00022 #include <pfunc/attribute.hpp> 00023 #include <pfunc/task.hpp> 00024 #include <pfunc/taskmgr.hpp> 00025 #include <pfunc/generator.hpp> 00026 00027 namespace pfunc { 00028 00029 /* Convenience */ 00030 using detail::group; 00031 00036 template <typename Attribute> 00037 static inline void attr_priority_set (Attribute& attr, 00038 const typename Attribute::priority_type& pri) { 00039 attr.set_priority (pri); 00040 } 00041 00046 template <typename Attribute> 00047 static inline void attr_priority_get (const Attribute& attr, 00048 typename Attribute::priority_type& pri) { 00049 pri = attr.get_priority (); 00050 } 00051 00056 template <typename Attribute> 00057 static inline void attr_qnum_set (Attribute& attr, 00058 const typename Attribute::qnum_type& qnum) { 00059 attr.set_queue_number (qnum); 00060 } 00061 00066 template <typename Attribute> 00067 static inline void attr_qnum_get (const Attribute& attr, 00068 typename Attribute::qnum_type& qnum) { 00069 qnum = attr.get_queue_number (); 00070 } 00071 00076 template <typename Attribute> 00077 static inline void attr_num_waiters_set (Attribute& attr, 00078 const typename Attribute::num_waiters_type& nwait) { 00079 attr.set_num_waiters (nwait); 00080 } 00081 00086 template <typename Attribute> 00087 static inline void attr_num_waiters_get (const Attribute& attr, 00088 typename Attribute::num_waiters_type& nwait) { 00089 nwait = attr.get_num_waiters (); 00090 } 00091 00096 template <typename Attribute> 00097 static inline void attr_nested_set (Attribute& attr, 00098 const typename Attribute::nested_type& nested) { 00099 attr.set_nested (nested); 00100 } 00101 00106 template <typename Attribute> 00107 static inline void attr_nested_get (const Attribute& attr, 00108 typename Attribute::nested_type& nested) { 00109 nested = attr.get_nested (); 00110 } 00111 00116 template <typename Attribute> 00117 static inline void attr_level_set (Attribute& attr, 00118 const typename Attribute::level_type& level) { 00119 attr.set_level (level); 00120 } 00121 00126 template <typename Attribute> 00127 static inline void attr_level_get (Attribute& attr, 00128 typename Attribute::level_type& level) { 00129 level = attr.get_level (); 00130 } 00131 00136 template <typename Attribute> 00137 static inline void attr_grouped_set (Attribute& attr, 00138 const typename Attribute::grouped_type& grouped) { 00139 attr.set_grouped (grouped); 00140 } 00141 00146 template <typename Attribute> 00147 static inline void attr_grouped_get (const Attribute& attr, 00148 typename Attribute::grouped_type& grouped) { 00149 grouped= attr.get_grouped (); 00150 } 00155 static inline void group_id_set (group& grp, 00156 const unsigned int& id) { 00157 grp.set_id (id); 00158 } 00159 00164 static inline void group_id_get (const group& grp, 00165 unsigned int& id) { 00166 id = grp.get_id (); 00167 } 00168 00173 static inline void group_size_set (group& grp, 00174 const unsigned int& size) { 00175 grp.set_size (size); 00176 } 00177 00182 static inline void group_size_get (const group& grp, 00183 unsigned int& size) { 00184 size = grp.get_size (); 00185 } 00186 00191 static inline void group_barrier_set (group& grp, 00192 const unsigned int& barr) { 00193 grp.set_barrier (barr); 00194 } 00195 00200 static inline void group_barrier_get (const group& grp, 00201 unsigned int& barr) { 00202 barr = grp.get_barrier (); 00203 } 00204 00205 /**************************************************************************** 00206 * All the above functions make use of the taskmanager as a parameter. As 00207 * a result, we have two versions of these functions. A global version that 00208 * uses as default task manager object and the (preferred) version that uses 00209 * a user supplied task manager object. Users are allowed to mix and match the 00210 * two calls, as long as they are consistent. That is, if you spawned a task 00211 * using the global task manager, please also wait on the task using the 00212 * global task manager 00213 ***************************************************************************/ 00214 00215 /************************************************************************** 00216 * Here are the local versions of the functions that use task manager 00217 *************************************************************************/ 00218 00223 template <typename TaskManager> 00224 static inline unsigned int thread_id (const TaskManager& tmanager) { 00225 unsigned int id; 00226 00227 PFUNC_START_TRY_BLOCK() 00228 id = const_cast<TaskManager&>(tmanager).current_thread_id (); 00229 PFUNC_END_TRY_BLOCK() 00230 PFUNC_CXX_CATCH_AND_RETHROW() 00231 00232 return id; 00233 } 00234 00239 template <typename TaskManager> 00240 static inline void group_rank (const TaskManager& tmanager, 00241 unsigned int& rank) { 00242 PFUNC_START_TRY_BLOCK() 00243 rank = const_cast<TaskManager&>(tmanager).current_task_group_rank (); 00244 PFUNC_END_TRY_BLOCK() 00245 PFUNC_CXX_CATCH_AND_RETHROW() 00246 } 00247 00252 template <typename TaskManager> 00253 static inline void group_size (const TaskManager& tmanager, 00254 unsigned int& size) { 00255 PFUNC_START_TRY_BLOCK() 00256 size = const_cast<TaskManager&>(tmanager).current_task_group_size (); 00257 PFUNC_END_TRY_BLOCK() 00258 PFUNC_CXX_CATCH_AND_RETHROW() 00259 } 00260 00265 template <typename TaskManager, typename TaskType> 00266 static inline void wait (TaskManager& tmanager, TaskType* task) { 00267 PFUNC_START_TRY_BLOCK() 00268 task->wait (tmanager); 00269 PFUNC_END_TRY_BLOCK() 00270 PFUNC_CXX_CATCH_AND_RETHROW() 00271 } 00272 00277 template <typename TaskManager, typename TaskType> 00278 static inline void wait (TaskManager& tmanager, TaskType& task) { 00279 PFUNC_START_TRY_BLOCK() 00280 task.wait (tmanager); 00281 PFUNC_END_TRY_BLOCK() 00282 PFUNC_CXX_CATCH_AND_RETHROW() 00283 } 00284 00295 template <typename TaskManager, typename ForwardIterator> 00296 static inline void wait_any (TaskManager& tmanager, 00297 ForwardIterator first, 00298 ForwardIterator last, 00299 int* completion_arr) { 00300 PFUNC_START_TRY_BLOCK() 00301 unsigned int loop_count = 1; 00302 while (!pfunc_test_all (tmanager, first, last, completion_arr)) { 00311 pfunc::detail::thread::yield (); 00312 loop_count = 1; 00313 } 00314 PFUNC_END_TRY_BLOCK() 00315 PFUNC_CXX_CATCH_AND_RETHROW() 00316 } 00317 00325 template <typename TaskManager, typename ForwardIterator> 00326 static inline void wait_all (TaskManager& tmanager, 00327 ForwardIterator first, 00328 ForwardIterator last) { 00329 PFUNC_START_TRY_BLOCK() 00330 while (first != last) wait (tmanager, *first++); 00331 PFUNC_END_TRY_BLOCK() 00332 PFUNC_CXX_CATCH_AND_RETHROW() 00333 } 00334 00342 template <typename TaskManager, typename TaskType> 00343 static inline bool test (TaskManager& tmanager, TaskType& task) { 00344 bool return_value = false; 00345 00346 PFUNC_START_TRY_BLOCK() 00347 return_value = task.test (tmanager); 00348 PFUNC_END_TRY_BLOCK() 00349 PFUNC_CXX_CATCH_AND_RETHROW() 00350 00351 return return_value; 00352 } 00353 00362 template <typename TaskManager, typename ForwardIterator> 00363 static inline bool test_all (TaskManager& tmanager, 00364 ForwardIterator first, 00365 ForwardIterator last, 00366 int* completion_arr) { 00367 bool return_value = false; 00368 00369 PFUNC_START_TRY_BLOCK() 00370 int i = 0; 00371 while (first != last) 00372 completion_arr[i] = return_value = test (tmanager, *first++); 00373 PFUNC_END_TRY_BLOCK() 00374 PFUNC_CXX_CATCH_AND_RETHROW() 00375 00376 return return_value; 00377 } 00378 00387 template <typename TaskManager> 00388 static inline void barrier (TaskManager& tmanager) { 00389 PFUNC_START_TRY_BLOCK() 00390 return tmanager.current_task_group_barrier (); 00391 PFUNC_END_TRY_BLOCK() 00392 PFUNC_CXX_CATCH_AND_RETHROW() 00393 } 00394 00406 template <typename TaskManager> 00407 static inline void spawn (TaskManager& tmanager, 00408 typename TaskManager::task& task, 00409 const typename TaskManager::attribute& attr, 00410 group& grp, 00411 typename TaskManager::functor& func) { 00412 PFUNC_START_TRY_BLOCK() 00413 tmanager.spawn_task (task, attr, grp, func); 00414 PFUNC_END_TRY_BLOCK() 00415 PFUNC_CXX_CATCH_AND_RETHROW() 00416 } 00417 00427 template <typename TaskManager> 00428 static inline void spawn (TaskManager& tmanager, 00429 typename TaskManager::task& task, 00430 typename TaskManager::functor& func) { 00431 PFUNC_START_TRY_BLOCK() 00432 tmanager.spawn_task (task, func); 00433 PFUNC_END_TRY_BLOCK() 00434 PFUNC_CXX_CATCH_AND_RETHROW() 00435 } 00436 00447 template <typename TaskManager> 00448 static inline void spawn (TaskManager& tmanager, 00449 typename TaskManager::task& task, 00450 const typename TaskManager::attribute& attr, 00451 typename TaskManager::functor& func) { 00452 PFUNC_START_TRY_BLOCK() 00453 tmanager.spawn_task (task, attr, func); 00454 PFUNC_END_TRY_BLOCK() 00455 PFUNC_CXX_CATCH_AND_RETHROW() 00456 } 00457 00458 /* 00459 * Set the maximum number of attempts before yielding for the specified 00460 * task manager. 00461 * 00462 * \param [out] tmanager The task manager in question. 00463 * \param [out] attempts Contains the value of max attempts. 00464 */ 00465 template <typename TaskManager> 00466 static inline void taskmgr_max_attempts_set (TaskManager& tmanager, 00467 const unsigned int& attempts) { 00468 PFUNC_START_TRY_BLOCK() 00469 tmanager.set_max_attempts (attempts); 00470 PFUNC_END_TRY_BLOCK() 00471 PFUNC_CXX_CATCH_AND_RETHROW() 00472 } 00473 00474 /* 00475 * Get the maximum number of attempts before yielding for the specified 00476 * task manager. 00477 * 00478 * \param [out] tmanager The task manager in question. 00479 * \param [out] attempts Contains the value of max attempts. 00480 */ 00481 template <typename TaskManager> 00482 static inline void taskmgr_max_attempts_get (TaskManager& tmanager, 00483 unsigned int& attempts) { 00484 PFUNC_START_TRY_BLOCK() 00485 attempts = tmanager.get_max_attempts (); 00486 PFUNC_END_TRY_BLOCK() 00487 PFUNC_CXX_CATCH_AND_RETHROW() 00488 } 00489 00490 /* 00491 * @param[in] taskmgr The task manager. 00492 * @param[out] num_queues The number of task queues in the global task 00493 * manager. 00494 */ 00495 template <typename TaskMgr> 00496 static inline void get_num_queues (const TaskMgr& tmanager, 00497 unsigned int& num_queues) { 00498 PFUNC_START_TRY_BLOCK() 00499 num_queues = tmanager.get_num_queues (); 00500 PFUNC_END_TRY_BLOCK() 00501 PFUNC_CXX_CATCH_AND_RETHROW() 00502 } 00503 00504 /* 00505 * @param[in] taskmgr The task manager. 00506 * @param[out] num_threads The total number of threads in the global task 00507 * manager. 00508 */ 00509 template <typename TaskMgr> 00510 static inline void get_num_threads (const TaskMgr& tmanager, 00511 unsigned int& num_threads) { 00512 PFUNC_START_TRY_BLOCK() 00513 num_threads = tmanager.get_num_threads (); 00514 PFUNC_END_TRY_BLOCK() 00515 PFUNC_CXX_CATCH_AND_RETHROW() 00516 } 00517 00518 /************************************************************************** 00519 * Here are the global versions of the functions that use task manager 00520 * All these are under the 'global' namespace to avoid confusion. 00521 *************************************************************************/ 00522 namespace global { 00523 00525 detail::taskmgr_virtual_base* global_tmanager = NULL; 00526 00542 template <typename TaskManager> 00543 void init (TaskManager& tmanager) { 00544 global_tmanager = &tmanager; 00545 } 00546 00551 void clear () { 00552 global_tmanager = NULL; 00553 } 00554 00558 static inline unsigned int thread_id () { 00559 unsigned int id; 00560 00561 PFUNC_START_TRY_BLOCK() 00562 id = pfunc::thread_id (*global_tmanager); 00563 PFUNC_END_TRY_BLOCK() 00564 PFUNC_CXX_CATCH_AND_RETHROW() 00565 00566 return id; 00567 } 00568 00572 static inline void group_rank (unsigned int& rank) { 00573 PFUNC_START_TRY_BLOCK() 00574 return pfunc::group_rank (*global_tmanager, rank); 00575 PFUNC_END_TRY_BLOCK() 00576 PFUNC_CXX_CATCH_AND_RETHROW() 00577 } 00578 00582 static inline void group_size (unsigned int& size) { 00583 PFUNC_START_TRY_BLOCK() 00584 return pfunc::group_size (*global_tmanager, size); 00585 PFUNC_END_TRY_BLOCK() 00586 PFUNC_CXX_CATCH_AND_RETHROW() 00587 } 00588 00592 template <typename TaskType> 00593 static inline void wait (TaskType& task) { 00594 PFUNC_START_TRY_BLOCK() 00595 return pfunc::wait (*global_tmanager, task); 00596 PFUNC_END_TRY_BLOCK() 00597 PFUNC_CXX_CATCH_AND_RETHROW() 00598 } 00599 00609 template <typename ForwardIterator> 00610 static inline void wait_any (ForwardIterator first, 00611 ForwardIterator last, 00612 int* completion_arr) { 00613 PFUNC_START_TRY_BLOCK() 00614 return pfunc::wait_any (*global_tmanager, first, last, completion_arr); 00615 PFUNC_END_TRY_BLOCK() 00616 PFUNC_CXX_CATCH_AND_RETHROW() 00617 } 00618 00625 template <typename ForwardIterator> 00626 static inline void wait_all (ForwardIterator first, 00627 ForwardIterator last) { 00628 PFUNC_START_TRY_BLOCK() 00629 return pfunc::wait_all (*global_tmanager, first, last); 00630 PFUNC_END_TRY_BLOCK() 00631 PFUNC_CXX_CATCH_AND_RETHROW() 00632 } 00633 00640 template <typename TaskType> 00641 static inline bool test (TaskType& task) { 00642 bool ret_val; 00643 00644 PFUNC_START_TRY_BLOCK() 00645 ret_val = pfunc::test (*global_tmanager, task); 00646 PFUNC_END_TRY_BLOCK() 00647 PFUNC_CXX_CATCH_AND_RETHROW() 00648 00649 return ret_val; 00650 } 00651 00659 template <typename ForwardIterator> 00660 static inline bool test_all (ForwardIterator first, 00661 ForwardIterator last, 00662 int* completion_arr) { 00663 bool ret_val; 00664 00665 PFUNC_START_TRY_BLOCK() 00666 ret_val = pfunc::test_all (*global_tmanager, first, last, completion_arr); 00667 PFUNC_END_TRY_BLOCK() 00668 PFUNC_CXX_CATCH_AND_RETHROW() 00669 00670 return ret_val; 00671 } 00672 00677 static inline void barrier () { 00678 PFUNC_START_TRY_BLOCK() 00679 return pfunc::barrier (*global_tmanager); 00680 PFUNC_END_TRY_BLOCK() 00681 PFUNC_CXX_CATCH_AND_RETHROW() 00682 } 00683 00692 template <typename Task, 00693 typename Functor> 00694 static inline void spawn (Task& task, Functor& func) { 00695 PFUNC_START_TRY_BLOCK() 00696 global_tmanager->spawn_task(reinterpret_cast<void*>(&task), 00697 reinterpret_cast<void*>(&func)); 00698 PFUNC_END_TRY_BLOCK() 00699 PFUNC_CXX_CATCH_AND_RETHROW() 00700 } 00701 00711 template <typename Task, 00712 typename Attribute, 00713 typename Functor> 00714 static inline void spawn (Task& task, 00715 const Attribute& attr, 00716 Functor& func) { 00717 PFUNC_START_TRY_BLOCK() 00718 global_tmanager->spawn_task(reinterpret_cast<void*>(&task), 00719 reinterpret_cast<void*>( 00720 &(const_cast<Attribute&>(attr))), 00721 reinterpret_cast<void*>(&func)); 00722 PFUNC_END_TRY_BLOCK() 00723 PFUNC_CXX_CATCH_AND_RETHROW() 00724 } 00725 00736 template <typename Task, 00737 typename Attribute, 00738 typename Functor> 00739 static inline void spawn (Task& task, 00740 const Attribute& attr, 00741 group& grp, 00742 Functor& func) { 00743 PFUNC_START_TRY_BLOCK() 00744 global_tmanager->spawn_task(reinterpret_cast<void*>(&task), 00745 reinterpret_cast<void*>( 00746 &(const_cast<Attribute&>(attr))), 00747 reinterpret_cast<void*>(&grp), 00748 reinterpret_cast<void*>(&func)); 00749 PFUNC_END_TRY_BLOCK() 00750 PFUNC_CXX_CATCH_AND_RETHROW() 00751 } 00752 00753 /* 00754 * Get the maximum number of attempts before yielding for teh global runtime 00755 * 00756 * \param [out] attempts Contains the value of max attempts. 00757 */ 00758 static inline void taskmgr_max_attempts_set (const unsigned int& attempts) { 00759 PFUNC_START_TRY_BLOCK() 00760 global_tmanager->set_max_attempts (attempts); 00761 PFUNC_END_TRY_BLOCK() 00762 PFUNC_CXX_CATCH_AND_RETHROW() 00763 } 00764 00765 /* 00766 * Get the maximum number of attempts before yielding for teh global runtime 00767 * 00768 * \param [out] attempts Contains the value of max attempts. 00769 */ 00770 static inline void taskmgr_max_attempts_get (unsigned int& attempts) { 00771 PFUNC_START_TRY_BLOCK() 00772 attempts = global_tmanager->get_max_attempts (); 00773 PFUNC_END_TRY_BLOCK() 00774 PFUNC_CXX_CATCH_AND_RETHROW() 00775 } 00776 00777 /* 00778 * @param[out] num_queues The number of task queues in the global task 00779 * manager. 00780 */ 00781 static inline void get_num_queues (unsigned int& num_queues) { 00782 PFUNC_START_TRY_BLOCK() 00783 num_queues = global_tmanager->get_num_queues (); 00784 PFUNC_END_TRY_BLOCK() 00785 PFUNC_CXX_CATCH_AND_RETHROW() 00786 } 00787 00788 /* 00789 * @param[out] num_threads The total number of threads in the global task 00790 * manager. 00791 */ 00792 static inline void get_num_threads (unsigned int& num_threads) { 00793 PFUNC_START_TRY_BLOCK() 00794 num_threads = global_tmanager->get_num_threads (); 00795 PFUNC_END_TRY_BLOCK() 00796 PFUNC_CXX_CATCH_AND_RETHROW() 00797 } 00798 } // namespace global 00799 } // namespace pfunc 00800 #endif // PFUNC_HPP