PFUNC  1.0
pfunc/pfunc.hpp
Go to the documentation of this file.
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