00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 #ifndef _CKCALLBACK_H_
00013 #define _CKCALLBACK_H_
00014 
00015 #include "cksection.h"
00016 #include "conv-ccs.h" 
00017 #include "charm.h"
00018 #include "ckarrayindex.h"
00019 #include "register.h"
00020 
00021 typedef void (*CkCallbackFn)(void *param,void *message);
00022 typedef void (*Ck1CallbackFn)(void *message);
00023 
00024 class CProxyElement_ArrayBase; 
00025 class CProxySection_ArrayBase;
00026 class CProxyElement_Group; 
00027 class CProxyElement_NodeGroup; 
00028 class CProxy_NodeGroup;
00029 class Chare;
00030 class Group;
00031 class NodeGroup;
00032 class ArrayElement;
00033 #define CkSelfCallback(ep)  CkCallback(this, ep)
00034 
00035 class CkCallback {
00036 public:
00037     enum callbackType : uint8_t {
00038     invalid=0, 
00039     ignore, 
00040     ckExit, 
00041     resumeThread, 
00042     callCFn, 
00043     call1Fn, 
00044     sendChare, 
00045     sendGroup, 
00046     sendNodeGroup, 
00047     sendArray, 
00048     isendChare, 
00049     isendGroup, 
00050     isendNodeGroup, 
00051     isendArray, 
00052     bcastGroup, 
00053     bcastNodeGroup, 
00054     bcastArray, 
00055     bcastSection,
00056     replyCCS 
00057     };
00058 #if CMK_ERROR_CHECKING
00059   static const char* typeName(callbackType type) {
00060     switch(type) {
00061       case invalid: return "CkCallback::invalid";
00062       case ignore: return "CkCallback::ignore";
00063       case ckExit: return "CkCallback::ckExit";
00064       case resumeThread: return "CkCallback::resumeThread";
00065       case callCFn: return "CkCallback::callCFn";
00066       case call1Fn: return "CkCallback::call1Fn";
00067       case sendChare: return "CkCallback::sendChare";
00068       case sendGroup: return "CkCallback::sendGroup";
00069       case sendNodeGroup: return "CkCallback::sendNodeGroup";
00070       case sendArray: return "CkCallback::sendArray";
00071       case isendChare: return "CkCallback::isendChare";
00072       case isendGroup: return "CkCallback::isendGroup";
00073       case isendNodeGroup: return "CkCallback::isendNodeGroup";
00074       case isendArray: return "CkCallback::isendArray";
00075       case bcastGroup: return "CkCallback::bcastGroup";
00076       case bcastNodeGroup: return "CkCallback::bcastNodeGroup";
00077       case bcastArray: return "CkCallback::bcastArray";
00078       case bcastSection: return "CkCallback::bcastSection";
00079       case replyCCS: return "CkCallback::replyCCS";
00080       default : return "unknown CkCallback type";
00081     }
00082   }
00083 #endif
00084 private:
00085     union callbackData {
00086     struct s_thread { 
00087         int onPE; 
00088         int cb; 
00089         CthThread th; 
00090         void *ret; 
00091     } thread;
00092     struct s_cfn { 
00093         int onPE; 
00094         CkCallbackFn fn; 
00095         void *param; 
00096     } cfn;
00097     struct s_c1fn { 
00098         Ck1CallbackFn fn; 
00099     } c1fn;
00100     struct s_chare { 
00101         int ep; 
00102         CkChareID id; 
00103         CMK_REFNUM_TYPE refnum; 
00104         bool hasRefnum;
00105     } chare;
00106     struct s_group { 
00107         int ep; 
00108         CkGroupID id; 
00109         int onPE; 
00110         CMK_REFNUM_TYPE refnum; 
00111         bool hasRefnum;
00112     } group;
00113     struct s_array { 
00114         int ep; 
00115         CkGroupID id; 
00116         CkArrayIndexBase idx; 
00117         CMK_REFNUM_TYPE refnum; 
00118         bool hasRefnum;
00119     } array;
00120     struct s_section {
00121                 CkArrayIndex *_elems;
00122                 int *pelist;
00123         CkSectionInfo::CkSectionInfoStruct sinfo;
00124                 int _nElems;
00125                 int npes;
00126         int ep;
00127         CMK_REFNUM_TYPE refnum; 
00128         bool hasRefnum;
00129     } section;
00130 
00131     struct s_ccsReply {
00132         CcsDelayedReply reply;
00133     } ccsReply;
00134     
00135     
00136     
00137     };
00138 
00139 public:
00140     callbackType type;
00141     callbackData d;
00142 #if CMK_CHARMPY
00143     
00144     
00145     
00146     bool isCkExtReductionCb = false;
00147 #endif
00148 
00149     bool operator==(CkCallback & other){
00150       if(type != other.type)
00151         return false;
00152       switch (type) {
00153         case resumeThread:
00154           return (d.thread.onPE == other.d.thread.onPE &&
00155           d.thread.cb == other.d.thread.cb);
00156         case isendChare:
00157         case sendChare:
00158           return (d.chare.ep == other.d.chare.ep &&
00159           d.chare.id.onPE == other.d.chare.id.onPE &&
00160           d.chare.hasRefnum == other.d.chare.hasRefnum &&
00161           d.chare.refnum == other.d.chare.refnum);
00162         case isendGroup:
00163         case sendGroup:
00164         case isendNodeGroup:
00165         case sendNodeGroup:
00166           return (d.group.ep == other.d.group.ep &&
00167           d.group.id == other.d.group.id &&
00168           d.group.onPE == other.d.group.onPE &&
00169           d.group.hasRefnum == other.d.group.hasRefnum &&
00170           d.group.refnum == other.d.group.refnum);
00171         case bcastNodeGroup:
00172         case bcastGroup:
00173           return (d.group.ep == other.d.group.ep &&
00174           d.group.id == other.d.group.id &&
00175           d.group.hasRefnum == other.d.group.hasRefnum &&
00176           d.group.refnum == other.d.group.refnum);
00177         case isendArray:
00178         case sendArray:
00179           return (d.array.ep == other.d.array.ep &&
00180           d.array.id == other.d.array.id &&
00181           d.array.idx == other.d.array.idx &&
00182           d.array.hasRefnum == other.d.array.hasRefnum &&
00183           d.array.refnum == other.d.array.refnum);
00184         case bcastArray:
00185           return (d.array.ep == other.d.array.ep &&
00186           d.array.id == other.d.array.id &&
00187           d.array.hasRefnum == other.d.array.hasRefnum &&
00188           d.array.refnum == other.d.array.refnum);
00189         case replyCCS:
00190           return true;
00191         case call1Fn:
00192           return (d.c1fn.fn == other.d.c1fn.fn);
00193         case callCFn:
00194           return (d.cfn.fn == other.d.cfn.fn &&
00195           d.cfn.onPE == other.d.cfn.onPE &&
00196           d.cfn.param == other.d.cfn.param);
00197         case bcastSection:
00198           return (d.section._elems == other.d.section._elems &&
00199         d.section.pelist && other.d.section.pelist &&
00200         d.section.sinfo == other.d.section.sinfo &&
00201         d.section._nElems == other.d.section._nElems &&
00202         d.section.npes == other.d.section.npes &&
00203         d.section.ep == other.d.section.ep &&
00204         ((d.section.hasRefnum && other.d.section.hasRefnum) &&
00205          (d.section.refnum == other.d.section.refnum)));
00206         case ignore:
00207         case ckExit:
00208         case invalid:
00209           return true;
00210         default:
00211           CkAbort("Inconsistent CkCallback type");
00212           return false;
00213       }
00214     }
00215 
00216 
00217     void impl_thread_init(void);
00218     void *impl_thread_delay(void) const;
00219 
00220     CkCallback(void) {
00221 #if CMK_REPLAYSYSTEM
00222       memset(this, 0, sizeof(CkCallback));
00223 #endif
00224       type=invalid;
00225     }
00226     
00227     CkCallback(callbackType t) {
00228 #if CMK_REPLAYSYSTEM
00229       memset(this, 0, sizeof(CkCallback));
00230 #endif
00231       if (t==resumeThread) impl_thread_init();
00232       type=t;
00233     }
00234 
00235     
00236     CkCallback(Ck1CallbackFn fn) {
00237 #if CMK_REPLAYSYSTEM
00238       memset(this, 0, sizeof(CkCallback));
00239 #endif
00240       type=call1Fn;
00241       d.c1fn.fn=fn;
00242     }
00243 
00244     
00245     CkCallback(CkCallbackFn fn,void *param) {
00246 #if CMK_REPLAYSYSTEM
00247       memset(this, 0, sizeof(CkCallback));
00248 #endif
00249       type=callCFn;
00250       d.cfn.onPE=CkMyPe(); d.cfn.fn=fn; d.cfn.param=param;
00251     }
00252 
00253     
00254     CkCallback(int ep,const CkChareID &id,bool forceInline=false) {
00255 #if CMK_REPLAYSYSTEM
00256       memset(this, 0, sizeof(CkCallback));
00257 #endif
00258       type = (forceInline || _entryTable[ep]->isInline) ? isendChare : sendChare;
00259       d.chare.ep=ep; d.chare.id=id;
00260           d.chare.hasRefnum = false;
00261           d.chare.refnum = 0;
00262     }
00263 
00264     
00265     CkCallback(int ep,const CProxy_NodeGroup &ngp);
00266 
00267     
00268     CkCallback(int ep,const CkGroupID &id, bool isNodeGroup=false) {
00269 #if CMK_REPLAYSYSTEM
00270       memset(this, 0, sizeof(CkCallback));
00271 #endif
00272       type=isNodeGroup?bcastNodeGroup:bcastGroup;
00273       d.group.ep=ep; d.group.id=id;
00274           d.group.hasRefnum = false;
00275           d.group.refnum = 0;
00276     }
00277 
00278     
00279     CkCallback(int ep,int onPE,const CProxy_NodeGroup &ngp,bool forceInline=false);
00280 
00281     
00282     CkCallback(int ep,int onPE,const CkGroupID &id,bool forceInline=false, bool isNodeGroup=false) {
00283 #if CMK_REPLAYSYSTEM
00284       memset(this, 0, sizeof(CkCallback));
00285 #endif
00286       type = (forceInline || _entryTable[ep]->isInline) ?  (isNodeGroup?isendNodeGroup:isendGroup) : (isNodeGroup?sendNodeGroup:sendGroup);
00287       d.group.ep=ep; d.group.id=id; d.group.onPE=onPE;
00288       d.group.hasRefnum = false;
00289           d.group.refnum = 0;
00290         }
00291 
00292     
00293     CkCallback(int ep,const CProxyElement_Group &grpElt,bool forceInline=false);
00294 
00295     
00296     CkCallback(int ep,const CProxyElement_NodeGroup &grpElt,bool forceInline=false);
00297 
00298     
00299     CkCallback(int ep,const CkArrayID &id) {
00300 #if CMK_REPLAYSYSTEM
00301       memset(this, 0, sizeof(CkCallback));
00302 #endif
00303       type=bcastArray;
00304       d.array.ep=ep; d.array.id=id;
00305       d.array.hasRefnum = false;
00306           d.array.refnum = 0;
00307         }
00308 
00309     
00310     CkCallback(int ep,const CkArrayIndex &idx,const CkArrayID &id,bool forceInline=false) {
00311 #if CMK_REPLAYSYSTEM
00312       memset(this, 0, sizeof(CkCallback));
00313 #endif
00314       type = (forceInline || _entryTable[ep]->isInline) ? isendArray : sendArray;
00315       d.array.ep=ep; d.array.id=id; d.array.idx = idx;
00316       d.array.hasRefnum = false;
00317           d.array.refnum = 0;
00318         }
00319 
00320     
00321     CkCallback(int ep,const CProxyElement_ArrayBase &arrElt,bool forceInline=false);
00322     
00323     
00324     CkCallback(int ep,CProxySection_ArrayBase §Elt,bool forceInline=false);
00325     CkCallback(int ep, CkSectionID &sid);
00326     
00327     
00328     CkCallback(Chare *p, int ep, bool forceInline=false);
00329 
00330     
00331     CkCallback(Group *p, int ep, bool forceInline=false);
00332 
00333     
00334     CkCallback(NodeGroup *p, int ep, bool forceInline=false);
00335 
00336     
00337     CkCallback(ArrayElement *p, int ep,bool forceInline=false);
00338 
00339     CkCallback(const CcsDelayedReply &reply) {
00340 #if CMK_REPLAYSYSTEM
00341       memset(this, 0, sizeof(CkCallback));
00342 #endif
00343       type=replyCCS;
00344       d.ccsReply.reply=reply;
00345     }
00346 
00347     ~CkCallback() {
00348       thread_destroy();
00349     }
00350     
00351     bool isInvalid(void) const {return type==invalid;}
00352 
00353     bool requiresMsgConstruction() const {
00354         return (type != ignore && type != ckExit && type != invalid);
00355     }
00356 
00359         bool containsPointer() const;
00360 
00368     void *thread_delay(void) const {
00369         if (type==resumeThread) return impl_thread_delay();
00370         return NULL;
00371     }
00372 
00373     void thread_destroy() const;
00374     
00382     void send(void *msg=NULL) const;
00383     
00387     void send(int length,const void *data) const;
00388     
00389     void pup(PUP::er &p);
00390 
00391         
00392         void setRefNum(CMK_REFNUM_TYPE refnum) { setRefnum(refnum); }
00393 
00394         void setRefnum(CMK_REFNUM_TYPE refnum) {
00395         switch(type) {
00396                 case sendChare:
00397                 case isendChare:
00398                   d.chare.hasRefnum = true;
00399                   d.chare.refnum = refnum;
00400                   break;
00401 
00402                 case sendGroup:
00403                 case sendNodeGroup:
00404                 case isendGroup:
00405                 case isendNodeGroup:
00406                 case bcastGroup:
00407                 case bcastNodeGroup:
00408                   d.group.hasRefnum = true;
00409                   d.group.refnum = refnum;
00410                   break;
00411 
00412                 case sendArray:
00413                 case isendArray:
00414                 case bcastArray:
00415                   d.array.hasRefnum = true;
00416                   d.array.refnum = refnum;
00417                   break;
00418 
00419                 case bcastSection:
00420                   d.section.hasRefnum = true;
00421                   d.section.refnum = refnum;
00422                   break;
00423 
00424                 default:
00425                   CkAbort("Tried to set a refnum on a callback not directed at an entry method");
00426                 }
00427         }
00428 };
00429 
00430 
00440 class CkCallbackResumeThread : public CkCallback {
00441  protected: void ** result;
00442  public:
00443     CkCallbackResumeThread(void)
00444         :CkCallback(resumeThread) { result = NULL; }
00445     CkCallbackResumeThread(void * &ptr)
00446         :CkCallback(resumeThread) { result = &ptr; }
00447         ~CkCallbackResumeThread(void);
00448 };
00449 
00450 void _registerCkCallback(void); 
00451 
00452 void CkCallbackInit();
00453 
00454 #endif
00455 
00456 
00457