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