PFUNC 1.0
pfunc/group.hpp
Go to the documentation of this file.
00001 #ifndef PFUNC_GROUP_HPP
00002 #define PFUNC_GROUP_HPP
00003 
00004   
00010 #include <pfunc/pfunc_common.h>
00011 #include <pfunc/exception.hpp>
00012 #include <pfunc/mutex.hpp>
00013 #include <pfunc/pfunc_atomics.h>
00014 
00015 namespace pfunc { namespace detail {
00016 
00020 struct group {
00021   private:
00022   ALIGN128 volatile bool barrier_phase; 
00023   ALIGN128 volatile unsigned int barrier_count; 
00024   volatile unsigned int rank_token; 
00025   unsigned int group_id; 
00026   unsigned int group_size; 
00027   mutex group_lock; 
00028   unsigned int type_of_barrier; 
00029   PFUNC_DEFINE_EXCEPT_PTR() 
00031   public:
00035   void barrier_spin ()  {
00036     PFUNC_START_TRY_BLOCK()
00037     while (!group_lock.trylock()); /* spin until lock acquire */
00038     volatile bool my_phase = barrier_phase;
00039     ++barrier_count;
00040     if (barrier_count == group_size) {
00041       barrier_count = 0;
00042       barrier_phase = !barrier_phase;
00043       group_lock.unlock();
00044     } else {
00045       group_lock.unlock();
00046       while (my_phase == barrier_phase); /* spin until  different phase */
00047     }
00048     PFUNC_END_TRY_BLOCK()
00049     PFUNC_CATCH_AND_RETHROW(group,barrier_spin)
00050   }
00051 
00052 
00058   template <typename TaskManager>
00059   void barrier_steal (TaskManager& taskmgr) {
00060     PFUNC_START_TRY_BLOCK()
00061     group_lock.lock();
00062     volatile bool my_phase = barrier_phase;
00063     ++barrier_count;
00064     if (barrier_count == group_size) {
00065       barrier_count = 0;
00066       barrier_phase = !barrier_phase;
00067       group_lock.unlock();
00068     } else {
00069       group_lock.unlock();
00070       while (my_phase == barrier_phase) taskmgr.progress_barrier ();
00071     }
00072     PFUNC_END_TRY_BLOCK()
00073     PFUNC_CATCH_AND_RETHROW(group,barrier_steal)
00074   }
00075 
00079   unsigned int join_group ()  {
00080     return pfunc_fetch_and_add_32 
00081               (reinterpret_cast<volatile int32_t*>(&rank_token), 1);
00082   }
00083 
00087   void leave_group (void)  {
00088     pfunc_fetch_and_add_32 
00089       (reinterpret_cast<volatile int32_t*>(&rank_token), -1);
00090   }
00091 
00095   unsigned int get_id () const  { return group_id; }
00096 
00101   unsigned int get_size ()  const  { return group_size; }
00102 
00106   unsigned int get_barrier() const  { return type_of_barrier; }
00107 
00111   void set_id (const unsigned int& gid)  { group_id = gid; }
00112 
00116   void set_size (const unsigned int& gsize)  { group_size = gsize; }
00117 
00121   void set_barrier (const unsigned int& barr) {type_of_barrier = barr;}
00122 
00126   template <typename TaskManager>
00127   void barrier (TaskManager& taskmgr)  {
00128     PFUNC_START_TRY_BLOCK()
00129     if (group_size > 1) {
00130       if (BARRIER_SPIN == type_of_barrier) return barrier_spin();
00131       else if (BARRIER_STEAL == type_of_barrier) return barrier_steal(taskmgr);
00132     } else {
00133       /* If the group count is 0 or 1, no use with the barrier */
00134     }
00135     PFUNC_END_TRY_BLOCK()
00136     PFUNC_CATCH_AND_RETHROW(group,barrier)
00137   }
00138 
00142   group ()  : barrier_phase (false),
00143               barrier_count (0),
00144               rank_token (0),
00145               group_id (0), 
00146               group_size (0), 
00147               type_of_barrier (BARRIER_SPIN)
00148               PFUNC_EXCEPT_PTR_INIT() {}
00149 
00156   group (const unsigned int& group_id,
00157          const unsigned int& group_size) : barrier_phase (false),
00158                                            barrier_count (0),
00159                                            rank_token (0),
00160                                            group_id (group_id), 
00161                                            group_size (group_size),
00162                                            type_of_barrier (BARRIER_SPIN)
00163                                            PFUNC_EXCEPT_PTR_INIT() {}
00164 
00172   group (const unsigned int& group_id,
00173          const unsigned int& group_size,
00174          const unsigned int& barrier) : barrier_phase (false),
00175                                         barrier_count (0),
00176                                         rank_token (0),
00177                                         group_id (group_id), 
00178                                         group_size (group_size),
00179                                         type_of_barrier (barrier)
00180                                         PFUNC_EXCEPT_PTR_INIT() {}
00181 
00185   ~group ()  { PFUNC_EXCEPT_PTR_CLEAR() }
00186 
00187 
00194   friend bool operator== (const group& one, const group& two)  {
00195     return (one.group_size == two.group_size && one.group_id == two.group_id);
00196   }
00197 };
00198 
00199 } /* namespace detail */ } /* namespace pfunc */
00200 #endif // PFUNC_GROUP_HPP