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 #if PFUNC_LINUX == 1 00312 pthread_yield(); 00313 #elif PFUNC_DARWIN == 1 00314 pthread_yield_np(); 00315 #elif PFUNC_WINDOWS == 1 00316 SwitchToThread(); 00317 #elif PFUNC_AIX == 1 && PFUNC_HAVE_SCHED_H 00318 sched_yield(); 00319 #else 00320 00321 #endif 00322 loop_count = 1; 00323 } 00324 PFUNC_END_TRY_BLOCK() 00325 PFUNC_CXX_CATCH_AND_RETHROW() 00326 } 00327 00335 template <typename TaskManager, typename ForwardIterator> 00336 static inline void wait_all (TaskManager& tmanager, 00337 ForwardIterator first, 00338 ForwardIterator last) { 00339 PFUNC_START_TRY_BLOCK() 00340 while (first != last) wait (tmanager, *first++); 00341 PFUNC_END_TRY_BLOCK() 00342 PFUNC_CXX_CATCH_AND_RETHROW() 00343 } 00344 00352 template <typename TaskManager, typename TaskType> 00353 static inline bool test (TaskManager& tmanager, TaskType& task) { 00354 bool return_value = false; 00355 00356 PFUNC_START_TRY_BLOCK() 00357 return_value = task.test (tmanager); 00358 PFUNC_END_TRY_BLOCK() 00359 PFUNC_CXX_CATCH_AND_RETHROW() 00360 00361 return return_value; 00362 } 00363 00372 template <typename TaskManager, typename ForwardIterator> 00373 static inline bool test_all (TaskManager& tmanager, 00374 ForwardIterator first, 00375 ForwardIterator last, 00376 int* completion_arr) { 00377 bool return_value = false; 00378 00379 PFUNC_START_TRY_BLOCK() 00380 int i = 0; 00381 while (first != last) 00382 completion_arr[i] = return_value = test (tmanager, *first++); 00383 PFUNC_END_TRY_BLOCK() 00384 PFUNC_CXX_CATCH_AND_RETHROW() 00385 00386 return return_value; 00387 } 00388 00397 template <typename TaskManager> 00398 static inline void barrier (TaskManager& tmanager) { 00399 PFUNC_START_TRY_BLOCK() 00400 return tmanager.current_task_group_barrier (); 00401 PFUNC_END_TRY_BLOCK() 00402 PFUNC_CXX_CATCH_AND_RETHROW() 00403 } 00404 00416 template <typename TaskManager> 00417 static inline void spawn (TaskManager& tmanager, 00418 typename TaskManager::task& task, 00419 const typename TaskManager::attribute& attr, 00420 group& grp, 00421 typename TaskManager::functor& func) { 00422 PFUNC_START_TRY_BLOCK() 00423 tmanager.spawn_task (task, attr, grp, func); 00424 PFUNC_END_TRY_BLOCK() 00425 PFUNC_CXX_CATCH_AND_RETHROW() 00426 } 00427 00437 template <typename TaskManager> 00438 static inline void spawn (TaskManager& tmanager, 00439 typename TaskManager::task& task, 00440 typename TaskManager::functor& func) { 00441 PFUNC_START_TRY_BLOCK() 00442 tmanager.spawn_task (task, func); 00443 PFUNC_END_TRY_BLOCK() 00444 PFUNC_CXX_CATCH_AND_RETHROW() 00445 } 00446 00457 template <typename TaskManager> 00458 static inline void spawn (TaskManager& tmanager, 00459 typename TaskManager::task& task, 00460 const typename TaskManager::attribute& attr, 00461 typename TaskManager::functor& func) { 00462 PFUNC_START_TRY_BLOCK() 00463 tmanager.spawn_task (task, attr, func); 00464 PFUNC_END_TRY_BLOCK() 00465 PFUNC_CXX_CATCH_AND_RETHROW() 00466 } 00467 00468 /* 00469 * Set the maximum number of attempts before yielding for the specified 00470 * task manager. 00471 * 00472 * \param [out] tmanager The task manager in question. 00473 * \param [out] attempts Contains the value of max attempts. 00474 */ 00475 template <typename TaskManager> 00476 static inline void taskmgr_max_attempts_set (TaskManager& tmanager, 00477 const unsigned int& attempts) { 00478 PFUNC_START_TRY_BLOCK() 00479 tmanager.set_max_attempts (attempts); 00480 PFUNC_END_TRY_BLOCK() 00481 PFUNC_CXX_CATCH_AND_RETHROW() 00482 } 00483 00484 /* 00485 * Get the maximum number of attempts before yielding for the specified 00486 * task manager. 00487 * 00488 * \param [out] tmanager The task manager in question. 00489 * \param [out] attempts Contains the value of max attempts. 00490 */ 00491 template <typename TaskManager> 00492 static inline void taskmgr_max_attempts_get (TaskManager& tmanager, 00493 unsigned int& attempts) { 00494 PFUNC_START_TRY_BLOCK() 00495 attempts = tmanager.get_max_attempts (); 00496 PFUNC_END_TRY_BLOCK() 00497 PFUNC_CXX_CATCH_AND_RETHROW() 00498 } 00499 00500 /* 00501 * @param[in] taskmgr The task manager. 00502 * @param[out] num_queues The number of task queues in the global task 00503 * manager. 00504 */ 00505 template <typename TaskMgr> 00506 static inline void get_num_queues (const TaskMgr& tmanager, 00507 unsigned int& num_queues) { 00508 PFUNC_START_TRY_BLOCK() 00509 num_queues = tmanager.get_num_queues (); 00510 PFUNC_END_TRY_BLOCK() 00511 PFUNC_CXX_CATCH_AND_RETHROW() 00512 } 00513 00514 /* 00515 * @param[in] taskmgr The task manager. 00516 * @param[out] num_threads The total number of threads in the global task 00517 * manager. 00518 */ 00519 template <typename TaskMgr> 00520 static inline void get_num_threads (const TaskMgr& tmanager, 00521 unsigned int& num_threads) { 00522 PFUNC_START_TRY_BLOCK() 00523 num_threads = tmanager.get_num_threads (); 00524 PFUNC_END_TRY_BLOCK() 00525 PFUNC_CXX_CATCH_AND_RETHROW() 00526 } 00527 00528 /************************************************************************** 00529 * Here are the global versions of the functions that use task manager 00530 * All these are under the 'global' namespace to avoid confusion. 00531 *************************************************************************/ 00532 namespace global { 00533 00535 detail::taskmgr_virtual_base* global_tmanager = NULL; 00536 00552 template <typename TaskManager> 00553 void init (TaskManager& tmanager) { 00554 global_tmanager = &tmanager; 00555 } 00556 00561 void clear () { 00562 global_tmanager = NULL; 00563 } 00564 00568 static inline unsigned int thread_id () { 00569 unsigned int id; 00570 00571 PFUNC_START_TRY_BLOCK() 00572 id = pfunc::thread_id (*global_tmanager); 00573 PFUNC_END_TRY_BLOCK() 00574 PFUNC_CXX_CATCH_AND_RETHROW() 00575 00576 return id; 00577 } 00578 00582 static inline void group_rank (unsigned int& rank) { 00583 PFUNC_START_TRY_BLOCK() 00584 return pfunc::group_rank (*global_tmanager, rank); 00585 PFUNC_END_TRY_BLOCK() 00586 PFUNC_CXX_CATCH_AND_RETHROW() 00587 } 00588 00592 static inline void group_size (unsigned int& size) { 00593 PFUNC_START_TRY_BLOCK() 00594 return pfunc::group_size (*global_tmanager, size); 00595 PFUNC_END_TRY_BLOCK() 00596 PFUNC_CXX_CATCH_AND_RETHROW() 00597 } 00598 00602 template <typename TaskType> 00603 static inline void wait (TaskType& task) { 00604 PFUNC_START_TRY_BLOCK() 00605 return pfunc::wait (*global_tmanager, task); 00606 PFUNC_END_TRY_BLOCK() 00607 PFUNC_CXX_CATCH_AND_RETHROW() 00608 } 00609 00619 template <typename ForwardIterator> 00620 static inline void wait_any (ForwardIterator first, 00621 ForwardIterator last, 00622 int* completion_arr) { 00623 PFUNC_START_TRY_BLOCK() 00624 return pfunc::wait_any (*global_tmanager, first, last, completion_arr); 00625 PFUNC_END_TRY_BLOCK() 00626 PFUNC_CXX_CATCH_AND_RETHROW() 00627 } 00628 00635 template <typename ForwardIterator> 00636 static inline void wait_all (ForwardIterator first, 00637 ForwardIterator last) { 00638 PFUNC_START_TRY_BLOCK() 00639 return pfunc::wait_all (*global_tmanager, first, last); 00640 PFUNC_END_TRY_BLOCK() 00641 PFUNC_CXX_CATCH_AND_RETHROW() 00642 } 00643 00650 template <typename TaskType> 00651 static inline bool test (TaskType& task) { 00652 bool ret_val; 00653 00654 PFUNC_START_TRY_BLOCK() 00655 ret_val = pfunc::test (*global_tmanager, task); 00656 PFUNC_END_TRY_BLOCK() 00657 PFUNC_CXX_CATCH_AND_RETHROW() 00658 00659 return ret_val; 00660 } 00661 00669 template <typename ForwardIterator> 00670 static inline bool test_all (ForwardIterator first, 00671 ForwardIterator last, 00672 int* completion_arr) { 00673 bool ret_val; 00674 00675 PFUNC_START_TRY_BLOCK() 00676 ret_val = pfunc::test_all (*global_tmanager, first, last, completion_arr); 00677 PFUNC_END_TRY_BLOCK() 00678 PFUNC_CXX_CATCH_AND_RETHROW() 00679 00680 return ret_val; 00681 } 00682 00687 static inline void barrier () { 00688 PFUNC_START_TRY_BLOCK() 00689 return pfunc::barrier (*global_tmanager); 00690 PFUNC_END_TRY_BLOCK() 00691 PFUNC_CXX_CATCH_AND_RETHROW() 00692 } 00693 00702 template <typename Task, 00703 typename Functor> 00704 static inline void spawn (Task& task, Functor& func) { 00705 PFUNC_START_TRY_BLOCK() 00706 global_tmanager->spawn_task(reinterpret_cast<void*>(&task), 00707 reinterpret_cast<void*>(&func)); 00708 PFUNC_END_TRY_BLOCK() 00709 PFUNC_CXX_CATCH_AND_RETHROW() 00710 } 00711 00721 template <typename Task, 00722 typename Attribute, 00723 typename Functor> 00724 static inline void spawn (Task& task, 00725 const Attribute& attr, 00726 Functor& func) { 00727 PFUNC_START_TRY_BLOCK() 00728 global_tmanager->spawn_task(reinterpret_cast<void*>(&task), 00729 reinterpret_cast<void*>( 00730 &(const_cast<Attribute&>(attr))), 00731 reinterpret_cast<void*>(&func)); 00732 PFUNC_END_TRY_BLOCK() 00733 PFUNC_CXX_CATCH_AND_RETHROW() 00734 } 00735 00746 template <typename Task, 00747 typename Attribute, 00748 typename Functor> 00749 static inline void spawn (Task& task, 00750 const Attribute& attr, 00751 group& grp, 00752 Functor& func) { 00753 PFUNC_START_TRY_BLOCK() 00754 global_tmanager->spawn_task(reinterpret_cast<void*>(&task), 00755 reinterpret_cast<void*>( 00756 &(const_cast<Attribute&>(attr))), 00757 reinterpret_cast<void*>(&grp), 00758 reinterpret_cast<void*>(&func)); 00759 PFUNC_END_TRY_BLOCK() 00760 PFUNC_CXX_CATCH_AND_RETHROW() 00761 } 00762 00763 /* 00764 * Get the maximum number of attempts before yielding for teh global runtime 00765 * 00766 * \param [out] attempts Contains the value of max attempts. 00767 */ 00768 static inline void taskmgr_max_attempts_set (const unsigned int& attempts) { 00769 PFUNC_START_TRY_BLOCK() 00770 global_tmanager->set_max_attempts (attempts); 00771 PFUNC_END_TRY_BLOCK() 00772 PFUNC_CXX_CATCH_AND_RETHROW() 00773 } 00774 00775 /* 00776 * Get the maximum number of attempts before yielding for teh global runtime 00777 * 00778 * \param [out] attempts Contains the value of max attempts. 00779 */ 00780 static inline void taskmgr_max_attempts_get (unsigned int& attempts) { 00781 PFUNC_START_TRY_BLOCK() 00782 attempts = global_tmanager->get_max_attempts (); 00783 PFUNC_END_TRY_BLOCK() 00784 PFUNC_CXX_CATCH_AND_RETHROW() 00785 } 00786 00787 /* 00788 * @param[out] num_queues The number of task queues in the global task 00789 * manager. 00790 */ 00791 static inline void get_num_queues (unsigned int& num_queues) { 00792 PFUNC_START_TRY_BLOCK() 00793 num_queues = global_tmanager->get_num_queues (); 00794 PFUNC_END_TRY_BLOCK() 00795 PFUNC_CXX_CATCH_AND_RETHROW() 00796 } 00797 00798 /* 00799 * @param[out] num_threads The total number of threads in the global task 00800 * manager. 00801 */ 00802 static inline void get_num_threads (unsigned int& num_threads) { 00803 PFUNC_START_TRY_BLOCK() 00804 num_threads = global_tmanager->get_num_threads (); 00805 PFUNC_END_TRY_BLOCK() 00806 PFUNC_CXX_CATCH_AND_RETHROW() 00807 } 00808 } // namespace global 00809 } // namespace pfunc 00810 #endif // PFUNC_HPP