Merged arrays into Charj mainline.
[charm.git] / src / ck-core / charm++.h
1 /*****************************************************************************
2  * $Source$
3  * $Author$
4  * $Date$
5  * $Revision$
6  *****************************************************************************/
7
8 #ifndef _CHARMPP_H_
9 #define _CHARMPP_H_
10
11 #include <stdlib.h>
12 #include <memory.h>
13
14 #include "charm.h"
15 #include "middle.h"
16
17 #if CMK_HAS_STRINGS_H
18   #include <strings.h>            /* defines bzero */
19 #else
20   #define bzero(s,n)   memset(s,0,n)
21 #endif
22
23 class CMessage_CkArgMsg {
24 public: static int __idx;
25 };
26 #define CK_ALIGN(val,to) (((val)+(to)-1)&~((to)-1))
27
28 #include "pup.h"
29 #include "cklists.h"
30 #include "ckbitvector.h"
31 #include "init.h"
32 #include "debug-charm.h"
33 #include "simd.h"
34
35 PUPbytes(CkChareID)
36 PUPbytes(CkGroupID)
37 PUPbytes(CmiGroup)
38   
39 /**
40  * CkMessage is the superclass of all Charm++ messages.
41  * Typically, a message foo inherits from CMessage_foo, which
42  * inherits from CkMessage.  In the internals of Charm++,
43  * messages are often represented by bare "void *"s, which is 
44  * silly and dangerous.
45  */
46 class CkMessage { 
47         //Don't use these: use CkCopyMsg
48         CkMessage(const CkMessage &);
49         void operator=(const CkMessage &);
50 public:
51         CkMessage() {}
52         void operator delete(void *ptr) { CkFreeMsg(ptr); }
53         
54         /* This pup routine only packs the message itself, *not* the
55         message header.  Use CkPupMessage instead of calling this directly. */
56         void pup(PUP::er &p);
57         
58         /// This is used to display message contents in the debugger.
59         static void ckDebugPup(PUP::er &p,void *msg);
60 };
61 class CMessage_CkMessage {
62 public:
63         static int __idx;
64 };
65
66 /// CkArgMsg is passed to the mainchare's constructor.
67 class CkArgMsg : public CkMessage {
68 public:
69   int argc;
70   char **argv;
71 };
72
73 class CkArray;
74
75 void CkPupMessage(PUP::er &p,void **atMsg,int pack_detail=1);
76
77 //This is for passing a single Charm++ message via parameter marshalling
78 class CkMarshalledMessage {
79         void *msg;
80         //Don't use these: only pass by reference
81         void operator=(const CkMarshalledMessage &);
82  public:
83         CkMarshalledMessage(void): msg(NULL) {}
84         CkMarshalledMessage(CkMessage *m): msg(m) {} //Takes ownership of message
85         CkMarshalledMessage(const CkMarshalledMessage &);
86         ~CkMarshalledMessage() {if (msg) CkFreeMsg(msg);}
87         CkMessage *getMessage(void) {void *ret=msg; msg=NULL; return (CkMessage *)ret;}
88         void pup(PUP::er &p) {CkPupMessage(p,&msg,1);}
89 };
90 PUPmarshall(CkMarshalledMessage)
91
92 /**
93  * CkEntryOptions describes the options associated
94  * with an entry method invocation, which include
95  * the message priority and queuing strategy.
96  * It is only used with parameter marshalling.
97  */
98 class CkEntryOptions : public CkNoncopyable {
99         int queueingtype; //CK_QUEUEING type
100         int prioBits; //Number of bits of priority to use
101         typedef unsigned int prio_t; //Datatype used to represent priorities
102         prio_t *prioPtr; //Points to message priority values
103         prio_t prioStore; //For short priorities, stores the priority value
104         CkGroupID  depGroupID;  // group dependence
105 public:
106         CkEntryOptions(void): queueingtype(CK_QUEUEING_FIFO), prioBits(0), 
107                               prioPtr(NULL), prioStore(0) { depGroupID.setZero(); }
108
109         ~CkEntryOptions() {
110                 if ( prioPtr != NULL && queueingtype != CK_QUEUEING_IFIFO ) {
111                         delete [] prioPtr;
112                         prioBits = 0;
113                 }
114         }
115         
116         inline void setPriority(prio_t integerPrio) {
117                 queueingtype=CK_QUEUEING_IFIFO;
118                 prioBits=8*sizeof(integerPrio);
119                 prioPtr=&prioStore;
120                 prioStore=integerPrio;
121         }
122         inline void setPriority(int prioBits_,const prio_t *prioPtr_) {
123                 if ( prioPtr != NULL && queueingtype != CK_QUEUEING_IFIFO ) {
124                         delete [] prioPtr;
125                         prioBits = 0;
126                 }
127                 queueingtype=CK_QUEUEING_BFIFO;
128                 prioBits=prioBits_;
129                 int dataLength = (prioBits + (sizeof(prio_t)*8 - 1)) /
130                                  (sizeof(prio_t)*8);
131                 prioPtr = new prio_t[dataLength];
132                 memcpy((void *)prioPtr, prioPtr_, dataLength*sizeof(unsigned int));
133         }
134         inline void setPriority(const CkBitVector &cbv) {
135                 if ( cbv.data != NULL ) {
136                         if ( prioPtr != NULL && queueingtype != CK_QUEUEING_IFIFO ) {
137                                 delete [] prioPtr;
138                                 prioBits = 0;
139                         }
140                         queueingtype=CK_QUEUEING_BFIFO;
141                         prioBits=cbv.usedBits;
142                         int dataLength = (prioBits + (sizeof(prio_t)*8 - 1)) /
143                                         (sizeof(prio_t)*8);
144                         prioPtr = new prio_t[dataLength];
145                         memcpy((void *)prioPtr, cbv.data, dataLength*sizeof(prio_t));
146                 } else {
147                         queueingtype=CK_QUEUEING_BFIFO;
148                         prioBits=0;
149                         int dataLength = 1;
150                         prioPtr = new prio_t[dataLength];
151                         prioPtr[0] = 0;
152                 }
153         }
154         
155         inline void setQueueing(int queueingtype_) {queueingtype=queueingtype_;}
156         inline void setGroupDepID(CkGroupID &gid) { depGroupID = gid; }
157
158         ///These are used by CkAllocateMarshallMsg, below:
159         inline int getQueueing(void) const {return queueingtype;}
160         inline int getPriorityBits(void) const {return prioBits;}
161         inline const prio_t *getPriorityPtr(void) const {return prioPtr;}
162         inline const CkGroupID getGroupDepID() const { return depGroupID; }
163 };
164
165 #include "CkMarshall.decl.h"
166 //This is the message type marshalled parameters get packed into:
167 class CkMarshallMsg : public CMessage_CkMarshallMsg {
168 public: 
169         char *msgBuf;
170 };
171
172
173
174 //A queue-of-messages, like CkMsgQ<CkReductionMsg>
175 template <class MSG>
176 class CkMsgQ : public CkQ<MSG *> {
177 public:
178         ~CkMsgQ() { //Delete the messages in the queue:
179                 MSG *m;
180                 while (NULL!=(m=this->deq())) delete m;
181         }
182         void pup(PUP::er &p) {
183                 int l=this->length();
184                 p(l);
185                 for (int i=0;i<l;i++) {
186                         MSG *m=NULL;
187                         if (!p.isUnpacking()) m=this->deq();
188                         CkPupMessage(p,(void **)&m);
189                         this->enq(m);
190                 }
191         }
192         friend void operator|(PUP::er &p,CkMsgQ<MSG> &v) {v.pup(p);}
193 };
194
195 /*******************************************************
196 Array Index class.  An array index is just a hash key-- 
197 a run of integers used to look up an object in a hash table.
198 */
199
200 #include "ckhashtable.h"
201
202 #ifndef CK_ARRAYINDEX_MAXLEN 
203 #define CK_ARRAYINDEX_MAXLEN 3 /*Max. # of integers in an array index*/
204 #endif
205
206
207 class CkArrayIndex
208 {
209 public:
210         ///Length of index in *integers*
211         short int nInts;
212         ///Number of dimensions in this index, not valid for user-defined indices
213         short int dimension; 
214         /// The actual index data
215         union {
216             int index[CK_ARRAYINDEX_MAXLEN];
217             short int indexShorts[2 * CK_ARRAYINDEX_MAXLEN];
218         };
219
220         /// Zero out the index bits upon construction
221         CkArrayIndex(): nInts(0), dimension(0) { bzero(index,CK_ARRAYINDEX_MAXLEN*sizeof(int)); }
222
223         int *data(void)             {return index; }
224         const int *data(void) const {return index; }
225
226         int getCombinedCount(void) const {
227           if (nInts == 1) return data()[0];
228           else if (nInts == 2) return data()[0] * data()[1];
229           else if (nInts == 3) return data()[0] * data()[1] * data()[2];
230           else return 0;
231         }
232
233         void pup(PUP::er &p);
234
235     //These routines allow CkArrayIndex to be used in
236     //  a CkHashtableT
237         CkHashCode hash(void) const;
238         static CkHashCode staticHash(const void *a,size_t);
239         int compare(const CkArrayIndex &ind) const;
240         static int staticCompare(const void *a,const void *b,size_t);
241 };
242
243 inline CkHashCode CkArrayIndex::hash(void) const
244 {
245         register int i;
246         register const int *d=data();
247         register CkHashCode ret=d[0];
248         for (i=1;i<nInts;i++)
249                 ret +=circleShift(d[i],10+11*i)+circleShift(d[i],9+7*i);
250         return ret;
251 }
252 inline int CkArrayIndex::compare(const CkArrayIndex &i2) const
253 {
254         const CkArrayIndex &i1=*this;
255 #if CMK_1D_ONLY
256         return i1.data()[0]==i2.data()[0];
257 #else
258         const int *d1=i1.data();
259         const int *d2=i2.data();
260         int l=i1.nInts;
261         if (l!=i2.nInts) return 0;
262         for (int i=0;i<l;i++)
263                 if (d1[i]!=d2[i])
264                         return 0;
265         //If we got here, the two keys must have exactly the same data
266         return 1;
267 #endif
268 }
269
270
271 //This class is as large as any CkArrayIndex
272 class CkArrayIndexMax : public CkArrayIndex {
273         void copyFrom(const CkArrayIndex &that)
274         {
275                 nInts=that.nInts;
276                 dimension=that.dimension;
277                 for (int i=0;i<nInts;i++) index[i]=that.data()[i];
278         }
279 public:
280         CkArrayIndexMax(void) { nInts=0; dimension=0; }
281         CkArrayIndexMax(int i) { nInts=0; dimension=0; }   // used for CkVec
282         CkArrayIndexMax(const CkArrayIndex &that) 
283                 {copyFrom(that);}
284         CkArrayIndexMax &operator=(const CkArrayIndex &that) 
285                 {copyFrom(that); return *this;}
286         void print() { CmiPrintf("%d: %d %d %d\n", nInts,index[0], index[1], index[2]); }
287         void sprint(char *str) { sprintf(str, "%d: %d %d %d", nInts,index[0], index[1], index[2]); }
288         void pup(PUP::er &p) {
289                 p|nInts;
290                 p|dimension;
291                 for (int i=0;i<nInts;i++) p|index[i];
292         }
293         /*
294          * Code for the previous attempt to introduce CkArrayID into CmiObjId
295          * 
296          * Turns out this:
297          * i) does not appear to work right.
298          * ii) does not result in the same ID as the ones used by the Load
299          *     Balancer.
300          *
301          * FIXME **CWL** - temporary solution:
302          * i) ignore the arrayID passed into the method.
303          * ii) use exactly the same code as the 
304          *     idx2LDObjid(const CkArrayIndex &idx) found in cklocation.C
305          *     The only problem is that the code only exists when the
306          *     CMK_LBDB_ON is set, so we cannot reuse the code and
307          *     risk having to modify the code should idx2LDObjid be changed.
308          *
309         CmiObjId *getProjectionID(int arrayID) { 
310           CmiObjId *ret = new CmiObjId;
311           for (int i=0; i<CK_ARRAYINDEX_MAXLEN; i++) {
312             ret->id[i] = index.data[i];
313           }
314           ret->id[CK_ARRAYINDEX_MAXLEN] = arrayID;
315           return ret; 
316         }
317         */
318         CmiObjId *getProjectionID(int arrayID) {
319           CmiObjId *ret = new CmiObjId;
320             int i;
321             const int *data=this->data();
322             if (OBJ_ID_SZ>=this->nInts) {
323               for (i=0;i<this->nInts;i++)
324                 ret->id[i]=data[i];
325               for (i=this->nInts;i<OBJ_ID_SZ;i++)
326                 ret->id[i]=0;
327             } else {
328               //Must hash array index into LBObjid
329               int j;
330               for (j=0;j<OBJ_ID_SZ;j++)
331                 ret->id[j]=data[j];
332               for (i=0;i<this->nInts;i++)
333                 for (j=0;j<OBJ_ID_SZ;j++)
334                   ret->id[j]+=circleShift(data[i],22+11*i*(j+1))+
335                     circleShift(data[i],21-9*i*(j+1));
336             }
337             return ret;
338         }
339
340         CmiBool operator==(const CkArrayIndexMax& idx) const {
341           if (nInts != idx.nInts) return CmiFalse;
342           for (int i=0; i<nInts; i++)
343                 if (index[i] != idx.index[i]) return CmiFalse;
344           return CmiTrue;
345         }
346 };
347 PUPmarshall(CkArrayIndexMax)
348
349 //A layout-compatible version of a CkArrayIndexMax.
350 //  Needed, e.g., for use in unions where a constructor is forbidden.
351 class CkArrayIndexStruct {
352 public:
353         short int nInts;
354         short int dimension;
355         int index[CK_ARRAYINDEX_MAXLEN];
356         CkArrayIndexMax &asMax(void) 
357                 {return *(CkArrayIndexMax *)this;}
358         const CkArrayIndexMax &asMax(void) const
359                 {return *(const CkArrayIndexMax *)this;}
360         void pup(PUP::er &p) {
361                 p|nInts;
362                 p|dimension;
363                 for (int i=0;i<nInts;i++) p|index[i];
364         }
365 };
366 PUPmarshall(CkArrayIndexStruct)
367
368 class CkArrayID {
369         CkGroupID _gid;
370 public:
371         CkArrayID() : _gid() { }
372         CkArrayID(CkGroupID g) :_gid(g) {}
373         inline void setZero(void) {_gid.setZero();}
374         inline int isZero(void) const {return _gid.isZero();}
375         operator CkGroupID() const {return _gid;}
376         CkArray *ckLocalBranch(void) const
377                 { return (CkArray *)CkLocalBranch(_gid); }
378         static CkArray *CkLocalBranch(CkArrayID id) 
379                 { return (CkArray *)::CkLocalBranch(id); }
380         void pup(PUP::er &p) {p | _gid; }
381         int operator == (const CkArrayID& other) const {
382                 return (_gid == other._gid);
383         }
384 };
385 PUPmarshall(CkArrayID)
386
387 #include "cksection.h"
388
389 #include "ckcallback.h"
390
391 /********************* Superclass of all Chares ******************/
392 #if CMK_MULTIPLE_DELETE
393 #define CHARM_INPLACE_NEW \
394     void *operator new(size_t, void *ptr) { return ptr; }; \
395     void operator delete(void*, void*) {}; \
396     void *operator new(size_t s) { return malloc(s); } \
397     void operator delete(void *ptr) { free(ptr); }
398 #else
399 #define CHARM_INPLACE_NEW \
400     void *operator new(size_t, void *ptr) { return ptr; }; \
401     void *operator new(size_t s) { return malloc(s); } \
402     void operator delete(void *ptr) { free(ptr); }
403 #endif
404
405 // for object message queue
406 #include "ckobjQ.h"
407
408
409 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
410 class ChareMlogData;
411 #endif
412
413
414 /**
415   The base class of all parallel objects in Charm++,
416   including Array Elements, Groups, and NodeGroups.
417 */
418 class Chare {
419   protected:
420     CkChareID thishandle;
421 #if CMK_OBJECT_QUEUE_AVAILABLE
422     CkObjectMsgQ objQ;                // object message queue
423 #endif
424   public:
425 #ifndef CMK_CHARE_USE_PTR
426     int chareIdx;                  // index in the chare obj table (chare_objs)
427 #endif
428 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
429     ChareMlogData *mlogData;
430 #endif
431     Chare(CkMigrateMessage *m);
432     Chare();
433     virtual ~Chare(); //<- needed for *any* child to have a virtual destructor
434     virtual void pup(PUP::er &p);//<- pack/unpack routine
435     inline const CkChareID &ckGetChareID(void) const {return thishandle;}
436     inline void CkGetChareID(CkChareID *dest) const {*dest=thishandle;}
437     // object message queue
438     void  CkEnableObjQ();
439 #if CMK_OBJECT_QUEUE_AVAILABLE
440     inline CkObjectMsgQ &CkGetObjQueue() { return objQ; }
441 #endif
442     CHARM_INPLACE_NEW
443     /// Return the type of this chare, as present in _chareTable
444     virtual int ckGetChareType() const;
445     /// Return a strdup'd array containing this object's string name.
446     virtual char *ckDebugChareName(void);
447     /// Place into str a copy of the id of this object up to limit bytes, return
448     /// the number of bytes used for the id
449     virtual int ckDebugChareID(char *str, int limit);
450     virtual void ckDebugPup(PUP::er &p);
451     /// Called when a [threaded] charm entry method is created:
452     virtual void CkAddThreadListeners(CthThread tid, void *msg);
453 };
454
455 //Superclass of all Groups that cannot participate in reductions.
456 //  Undocumented: should only be used inside Charm++.
457 /*forward*/ class Group;
458 class IrrGroup : public Chare {
459   protected:
460     CkGroupID thisgroup;
461   public:
462     IrrGroup(CkMigrateMessage *m): Chare(m) { }
463     IrrGroup();
464     virtual ~IrrGroup(); //<- needed for *any* child to have a virtual destructor
465
466     virtual void pup(PUP::er &p);//<- pack/unpack routine
467     virtual void ckJustMigrated(void);
468     inline const CkGroupID &ckGetGroupID(void) const {return thisgroup;}
469     inline CkGroupID CkGetGroupID(void) const {return thisgroup;}
470     virtual int ckGetChareType() const;
471     virtual char *ckDebugChareName();
472     virtual int ckDebugChareID(char *, int);
473
474     // Silly run-time type information
475     virtual int isNodeGroup() { return 0; };
476     virtual CmiBool isLocMgr(void){ return CmiFalse; }
477     virtual CmiBool isArrMgr(void){ return CmiFalse; }
478     virtual CmiBool isReductionMgr(void){ return CmiFalse; }
479     static int isIrreducible(){ return 1;}
480     virtual void flushStates() {}
481                 /*
482                         FAULT_EVAC
483                 */
484                 virtual void evacuate(){};
485                 virtual void doneEvacuate(){};
486     virtual void CkAddThreadListeners(CthThread tid, void *msg);
487 };
488
489 #define CBASE_PROXY_MEMBERS(CProxy_Derived) \
490         typedef typename CProxy_Derived::local_t local_t; \
491         typedef typename CProxy_Derived::index_t index_t; \
492         typedef typename CProxy_Derived::proxy_t proxy_t; \
493         typedef typename CProxy_Derived::element_t element_t; \
494         CProxy_Derived thisProxy; 
495
496
497 /*Templated implementation of CBase_* classes.*/
498 template <class Parent,class CProxy_Derived>
499 class CBaseT : public Parent {
500 public:
501         CBASE_PROXY_MEMBERS(CProxy_Derived)
502
503         CBaseT(void) :Parent()  { thisProxy=this; }
504         CBaseT(CkMigrateMessage *m) :Parent(m) { thisProxy=this; }
505         void pup(PUP::er &p) {
506                 Parent::pup(p);
507                 p|thisProxy;
508         }
509 };
510
511 /*Templated version of above for multiple (at least duplicate) inheritance:*/
512 template <class Parent1,class Parent2,class CProxy_Derived>
513 class CBaseT2 : public Parent1, public Parent2 {
514 public:
515         CBASE_PROXY_MEMBERS(CProxy_Derived)
516
517         CBaseT2(void) :Parent1(), Parent2()
518                 { thisProxy = (Parent1 *)this; }
519         CBaseT2(CkMigrateMessage *m) :Parent1(m), Parent2(m)
520                 { thisProxy = (Parent1 *)this; } 
521         void pup(PUP::er &p) {
522                 Parent1::pup(p);
523                 Parent2::pup(p);
524                 p|thisProxy;
525         }
526
527 //These overloads are needed to prevent ambiguity for multiple inheritance:
528         inline const CkChareID &ckGetChareID(void) const
529                 {return ((Parent1 *)this)->ckGetChareID();}
530         static int isIrreducible(){ return (Parent1::isIrreducible() && Parent2::isIrreducible());}
531         CHARM_INPLACE_NEW
532 };
533
534 /**************************** CkDelegateMgr **************************/
535
536 class CProxy;
537
538 /**
539  Per-proxy data storage for delegation.  A CkDelegateMgr
540  inherits from this class and adds his per-proxy data. 
541  This class is reference counted.
542 */
543 class CkDelegateData : public CkNoncopyable {
544         int refcount; // reference count
545 public:
546         CkDelegateData() :refcount(0) {}
547         virtual ~CkDelegateData();
548         
549         //Child class constructor may have to set this.
550         inline void reset() {
551             refcount = 0;
552         }
553         
554         /// Add a reference to this delegation data.  Just increments the refcount.
555         ///   Only CProxy should ever have to call this routine.
556         /// Actually now the delegate manager calls it.
557         inline void ref(void) {refcount++;}
558         
559         /// Remove our reference from this data.  If the refcount
560         ///  reaches 0, deletes the delegateData.
561         ///   Only CProxy should ever have to call this routine.
562         /// Actually now the delegate manager calls it.
563         inline void unref(void) {
564                 refcount--;
565                 if (refcount==0) delete this;
566         }
567 };
568
569 /**
570 Message delegation support, where you send a message via
571 a proxy normally, but the message ends up routed via this
572 special delegateMgr group.
573
574 An "interface" class-- all delegated messages are routed via 
575 this class.  The default action is to deliver the message directly.
576 */
577 class CkDelegateMgr : public IrrGroup {
578   public:
579     virtual ~CkDelegateMgr(); //<- so children can have virtual destructor
580     virtual void ChareSend(CkDelegateData *pd,int ep,void *m,const CkChareID *c,int onPE);
581
582     virtual void GroupSend(CkDelegateData *pd,int ep,void *m,int onPE,CkGroupID g);
583     virtual void GroupBroadcast(CkDelegateData *pd,int ep,void *m,CkGroupID g);
584     virtual void GroupSectionSend(CkDelegateData *pd,int ep,void *m,int nsid,CkSectionID *s);
585
586     virtual void NodeGroupSend(CkDelegateData *pd,int ep,void *m,int onNode,CkNodeGroupID g);
587     virtual void NodeGroupBroadcast(CkDelegateData *pd,int ep,void *m,CkNodeGroupID g);
588     virtual void NodeGroupSectionSend(CkDelegateData *pd,int ep,void *m,int nsid,CkSectionID *s);
589
590     virtual void ArrayCreate(CkDelegateData *pd,int ep,void *m,const CkArrayIndexMax &idx,int onPE,CkArrayID a);
591     virtual void ArraySend(CkDelegateData *pd,int ep,void *m,const CkArrayIndexMax &idx,CkArrayID a);
592     virtual void ArrayBroadcast(CkDelegateData *pd,int ep,void *m,CkArrayID a);
593     virtual void ArraySectionSend(CkDelegateData *pd,int ep,void *m,int nsid,CkSectionID *s,int opts);
594     virtual void initDelegateMgr(CProxy *proxy)  {}
595     virtual CkDelegateData* ckCopyDelegateData(CkDelegateData *data) {
596         data->ref();
597         return data;
598     } 
599     
600     /**
601      Management of per-proxy data: pup this delegate's data.
602      If p.isUnpacking, allocate and return a new set of delegate data.
603      Never delete (or unref) the data-- the proxy will do that itself
604         when it is required.
605      The default implementation just ignores this call.
606      
607      A typical implementation that uses CkDelegateData might look like this:
608      <code>
609        myData *d=(myData *)pd;
610        if (p.isUnpacking()) d=new myData();
611        p|d->myField1;
612        p|d->myField2;
613        return d;
614      </code>
615     */
616     virtual CkDelegateData *DelegatePointerPup(PUP::er &p,CkDelegateData *pd);
617 };
618
619
620 /**************************** Proxies **************************/
621
622 /*Message delegation support, where you send a message via
623 a proxy normally, but the message ends up routed via a 
624 special delegateMgr group.
625 */
626 class CkDelegateMgr;
627
628 /** 
629   A proxy is a local handle to a remote object.  This is the superclass
630   of all proxies: CProxy_Array, CProxy_Group, etc. inherit from this class.
631   
632   Real proxies for user classes are generated by the .ci file translator charmxi
633   and put in the generated .decl.h headers.
634 */
635 class CProxy {
636   private:
637     CkDelegateMgr *delegatedMgr; // can be either a group or a nodegroup
638     CkDelegateData *delegatedPtr; // private data for use by delegatedMgr.
639   protected: //Never allocate CProxy's-- only subclass them.
640     CProxy() :delegatedMgr(0), delegatedPtr(0) { }
641
642 #define CK_DELCTOR_PARAM CkDelegateMgr *dTo,CkDelegateData *dPtr
643 #define CK_DELCTOR_ARGS dTo,dPtr
644 #define CK_DELCTOR_CALL ckDelegatedTo(),ckDelegatedPtr()
645 /// Delegation constructor: used when building 
646 ///   an element proxy from a collective proxy, like in "aProxy[i]".
647     CProxy(CK_DELCTOR_PARAM)
648         :delegatedMgr(dTo)
649         {
650             delegatedPtr = NULL;
651             if(delegatedMgr != NULL && dPtr != NULL) 
652                 delegatedPtr = dTo->ckCopyDelegateData(dPtr);            
653         }
654   public:
655     /// Copy constructor.  Only needed for delegated proxies.
656     CProxy(const CProxy &src);
657     /// Assignment operator.  Only needed for delegated proxies.
658     CProxy& operator=(const CProxy &src);
659     /// Destructor.  Only needed for delegated proxies. 
660     ~CProxy() {
661         if (delegatedPtr) delegatedPtr->unref();
662     }
663     
664     /**
665       Delegation allows a class, called a CkDelegateMgr, to 
666       intercept calls made to this proxy for further processing.
667       
668       "ptr" is any delegator-specific data the CkDelegateMgr wants
669       to associate with this proxy: the pointer is owned by this 
670       proxy, but will be copied and pupped by calling delegator routines.
671       
672       This interface should only be used by library writers,
673       not ordinary user code.
674     */
675     void ckDelegate(CkDelegateMgr *to,CkDelegateData *pd=NULL);
676     
677     /// Remove delegation from this proxy.
678     void ckUndelegate(void);
679     
680     /// Return true if this proxy is delegated.
681     int ckIsDelegated(void) const { return(delegatedMgr!=NULL);}
682     
683     /// Return the delegator of this proxy, to which the proxies' messages
684     ///  are actually sent.
685     inline CkDelegateMgr *ckDelegatedTo(void) const { return delegatedMgr; }
686     
687     /// Return the delegator's local data associated with this proxy.
688     inline CkDelegateData *ckDelegatedPtr(void) const {return delegatedPtr;}
689     
690     /// Return the groupID of our delegator.
691     ///   Note that this can be a GroupID or a NodeGroupID, so be careful!
692     CkGroupID ckDelegatedIdx(void) const {
693         if (delegatedMgr) return delegatedMgr->CkGetGroupID();
694         else {
695           CkGroupID gid; gid.setZero();
696           return gid;
697         }
698     }
699     
700     /// Pup the data for this proxy.  Only needed for delegated proxies.
701     void pup(PUP::er &p);
702 };
703
704 PUPmarshall(CProxy)
705
706
707 /*The base classes of each proxy type
708 */
709 class CProxy_Chare : public CProxy {
710   private:
711     CkChareID _ck_cid;
712   public:
713     CProxy_Chare() {
714 #if CMK_ERROR_CHECKING
715         _ck_cid.onPE=0; _ck_cid.objPtr=0;
716 #endif
717     }
718 #if CMK_ERROR_CHECKING
719     inline void ckCheck(void) const  {   //Make sure this proxy has a value
720 #ifdef CMK_CHARE_USE_PTR
721         if (_ck_cid.objPtr==0)
722                 CkAbort("Error! This chare proxy has not been initialized!");
723 #endif
724     }
725 #else
726     inline void ckCheck() const {}
727 #endif
728     CProxy_Chare(const CkChareID &c) : _ck_cid(c) {}
729     CProxy_Chare(const Chare *c) : _ck_cid(c->ckGetChareID()) {}
730     const CkChareID &ckGetChareID(void) const {return _ck_cid;}
731     operator const CkChareID &(void) const {return ckGetChareID();}
732     void ckSetChareID(const CkChareID &c) {_ck_cid=c;}
733     void pup(PUP::er &p) {
734         CProxy::pup(p);
735         p(_ck_cid.onPE);
736         //Copy the pointer as straight bytes
737         p((char *)&_ck_cid.objPtr,sizeof(_ck_cid.objPtr));
738     }
739 };
740 PUPmarshall(CProxy_Chare)
741
742 /******************* Reduction Declarations ****************/
743 //Silly: need the type of a reduction client here so it can be used by proxies.
744 //A clientFn is called on PE 0 when all contributions
745 // have been received and reduced.
746 //  param can be ignored, or used to pass any client-specific data you $
747 //  dataSize gives the size (in bytes) of the data array
748 //  data gives the reduced contributions--
749 //       it will be disposed of after this procedure returns.
750 typedef void (*CkReductionClientFn)(void *param,int dataSize,void *data);
751
752 /// Tiny utility class used by CkReductionClientAdaptor--
753 /// lets us keep backward compatability with the old C-style interface.
754 class CkReductionClientBundle : public CkCallback {
755         CkReductionClientFn fn;
756         void *param;
757  public:
758         static void callbackCfn(void *thisPtr,void *reductionMsg);
759         CkReductionClientBundle(): fn(NULL), param(NULL) {}
760         CkReductionClientBundle(CkReductionClientFn fn_,void *param_);
761 };
762 PUPbytes(CkReductionClientBundle)
763
764 #define CK_REDUCTION_CLIENT_DECL \
765         void setReductionClient(CkReductionClientFn fn,void *param=NULL) const\
766                 { ckSetReductionClient(fn,param); } \
767         void ckSetReductionClient(CkReductionClientFn fn,void *param=NULL) const \
768                 { ckSetReductionClient(new CkReductionClientBundle(fn,param)); } \
769         void ckSetReductionClient(CkCallback *cb) const;\
770
771 #define CK_REDUCTION_CLIENT_DEF(className,mgr) \
772         void className::ckSetReductionClient(CkCallback *cb) const \
773                 { (mgr)->ckSetReductionClient(cb); }\
774
775
776 class CProxy_NodeGroup;
777 class CProxy_CkArrayReductionMgr;
778 class CProxy_Group : public CProxy {
779   private:
780     CkGroupID _ck_gid;
781
782   public:
783     CProxy_Group() {
784 #if CMK_ERROR_CHECKING
785         _ck_gid.setZero();
786 #endif
787         //CkPrintf(" In CProxy_Group Constructor\n");
788     }
789     CProxy_Group(CkGroupID g)
790        :CProxy(),_ck_gid(g) {
791        //CkPrintf(" In CProxy_Group Constructor\n");
792        }
793     CProxy_Group(CkGroupID g,CK_DELCTOR_PARAM)
794         :CProxy(CK_DELCTOR_ARGS),_ck_gid(g) {
795         //CkPrintf(" In CProxy_Group Constructor\n");
796         }
797     CProxy_Group(const IrrGroup *g)
798         :CProxy(), _ck_gid(g->ckGetGroupID()) {
799         //CkPrintf(" In CProxy_Group Constructor\n");
800         }
801 /*    CProxy_Group(const NodeGroup *g)  //<- for compatability with NodeGroups
802         :CProxy(), _ck_gid(g->ckGetGroupID()) {}*/
803
804 #if CMK_ERROR_CHECKING
805     inline void ckCheck(void) const {   //Make sure this proxy has a value
806         if (_ck_gid.isZero())
807                 CkAbort("Error! This group proxy has not been initialized!");
808     }
809 #else
810     inline void ckCheck() const {}
811 #endif
812
813     CkChareID ckGetChareID(void) const {
814         CkChareID ret;
815         ret.onPE=CkMyPe();
816         ret.objPtr=CkLocalBranch(_ck_gid);
817         return ret;
818     }
819     CkGroupID ckGetGroupID(void) const {return _ck_gid;}
820     operator CkGroupID () const {return ckGetGroupID();}
821     void ckSetGroupID(CkGroupID g) {_ck_gid=g;}
822     void pup(PUP::er &p) {
823         CProxy::pup(p);
824         p|_ck_gid;
825     }
826     CK_REDUCTION_CLIENT_DECL
827 };
828 PUPmarshall(CProxy_Group)
829
830 class CProxyElement_Group : public CProxy_Group {
831   private:
832     int _onPE;
833   public:
834     CProxyElement_Group() { }
835     CProxyElement_Group(CkGroupID g,int onPE)
836        : CProxy_Group(g),_onPE(onPE) {}
837     CProxyElement_Group(CkGroupID g,int onPE,CK_DELCTOR_PARAM)
838         : CProxy_Group(g,CK_DELCTOR_ARGS),_onPE(onPE) {}
839     CProxyElement_Group(const IrrGroup *g)
840         :CProxy_Group(g), _onPE(CkMyPe()) {}
841     /*CProxyElement_Group(const NodeGroup *g)  //<- for compatability with NodeGroups
842         :CProxy_Group(g), _onPE(CkMyPe()) {}*/
843
844     int ckGetGroupPe(void) const {return _onPE;}
845     void pup(PUP::er &p) {
846         CProxy_Group::pup(p);
847         p(_onPE);
848     }
849 };
850 PUPmarshall(CProxyElement_Group)
851
852 class CProxySection_Group : public CProxy_Group {
853 private:
854   int _nsid;
855   CkSectionID *_sid;
856 public:
857   CProxySection_Group() { }
858   CProxySection_Group(const CkGroupID &gid, const int *elems, const int nElems)
859       :CProxy_Group(gid), _nsid(1) { _sid = new CkSectionID(gid, elems, nElems); }
860   CProxySection_Group(const CkGroupID &gid, const int *elems, const int nElems,CK_DELCTOR_PARAM)
861       :CProxy_Group(gid,CK_DELCTOR_ARGS), _nsid(1) { _sid = new CkSectionID(gid, elems, nElems); }
862   CProxySection_Group(const CProxySection_Group &cs)
863       :CProxy_Group(cs.ckGetGroupID()), _nsid(cs._nsid) {
864     if (_nsid == 1) _sid = new CkSectionID(cs.ckGetGroupID(), cs.ckGetElements(), cs.ckGetNumElements());
865     else if (_nsid > 1) {
866       _sid = new CkSectionID[_nsid];
867       for (int i=0; i<_nsid; ++i) _sid[i] = cs._sid[i];
868     } else _sid = NULL;
869   }
870   CProxySection_Group(const CProxySection_Group &cs,CK_DELCTOR_PARAM)
871       :CProxy_Group(cs.ckGetGroupID(),CK_DELCTOR_ARGS), _nsid(cs._nsid) {
872     if (_nsid == 1) _sid = new CkSectionID(cs.ckGetGroupID(), cs.ckGetElements(), cs.ckGetNumElements());
873     else if (_nsid > 1) {
874       _sid = new CkSectionID[_nsid];
875       for (int i=0; i<_nsid; ++i) _sid[i] = cs._sid[i];
876     } else _sid = NULL;
877   }
878   CProxySection_Group(const IrrGroup *g)
879       :CProxy_Group(g), _nsid(0) {}
880   CProxySection_Group(const int n, const CkGroupID *gid,  int const * const *elems, const int *nElems)
881       :CProxy_Group(gid[0]), _nsid(n) {
882     _sid = new CkSectionID[n];
883     for (int i=0; i<n; ++i) _sid[i] = CkSectionID(gid[i], elems[i], nElems[i]);
884   }
885   CProxySection_Group(const int n, const CkGroupID *gid, int const * const *elems, const int *nElems,CK_DELCTOR_PARAM)
886       :CProxy_Group(gid[0],CK_DELCTOR_ARGS), _nsid(n) {
887     _sid = new CkSectionID[n];
888     for (int i=0; i<n; ++i) _sid[i] = CkSectionID(gid[i], elems[i], nElems[i]);
889   }
890   
891   ~CProxySection_Group() {
892     if (_nsid == 1) delete _sid;
893     else if (_nsid > 1) delete[] _sid;
894   }
895   
896   CProxySection_Group &operator=(const CProxySection_Group &cs) {
897     CProxy_Group::operator=(cs);
898     _nsid = cs._nsid;
899     if (_nsid == 1) _sid = new CkSectionID(*cs._sid);
900     else if (_nsid > 1) {
901       _sid = new CkSectionID[_nsid];
902       for (int i=0; i<_nsid; ++i) _sid[i] = cs._sid[i];
903     } else _sid = NULL;
904     return *this;
905   }
906   
907   //void ckSend(CkArrayMessage *m, int ep, int opts = 0) ;
908
909   inline int ckGetNumSections() const {return _nsid;}
910   inline CkSectionInfo &ckGetSectionInfo() {return _sid[0]._cookie;}
911   inline CkSectionID *ckGetSectionIDs() {return _sid; }
912   inline CkSectionID &ckGetSectionID() {return _sid[0]; }
913   inline CkSectionID &ckGetSectionID(int i) {return _sid[i]; }
914   inline CkGroupID ckGetGroupIDn(int i) const {return (CkGroupID)_sid[i]._cookie.aid;}
915   inline int *ckGetElements() const {return _sid[0].pelist;}
916   inline int *ckGetElements(int i) const {return _sid[i].pelist;}
917   inline int ckGetNumElements() const { return _sid[0].npes; }
918   inline int ckGetNumElements(int i) const { return _sid[i].npes; }
919   void pup(PUP::er &p) {
920     CProxy_Group::pup(p);
921     p | _nsid;
922     if (p.isUnpacking()) {
923       if (_nsid == 1) _sid = new CkSectionID;
924       else if (_nsid > 1) _sid = new CkSectionID[_nsid];
925       else _sid = NULL;
926     }
927     for (int i=0; i<_nsid; ++i) p | _sid[i];
928   }
929 };
930 PUPmarshall(CProxySection_Group)
931
932 /* These classes exist to provide chare indices for the basic
933  chare types.*/
934 class CkIndex_Chare { public:
935     static int __idx;//Fake chare index for registration
936 };
937 class CkIndex_ArrayBase { public:
938     static int __idx;//Fake chare index for registration
939 };
940 class CkIndex_Group { public:
941     static int __idx;//Fake chare index for registration
942 };
943
944 typedef CkIndex_Group CkIndex_NodeGroup;
945 typedef CkIndex_Group CkIndex_IrrGroup;
946
947
948 //typedef CProxy_Group CProxy_NodeGroup;
949 class CProxy_NodeGroup : public CProxy{
950
951   private:
952     CkGroupID _ck_gid;
953   public:
954     CProxy_NodeGroup() {
955 #if CMK_ERROR_CHECKING
956         _ck_gid.setZero();
957 #endif
958         //CkPrintf("In CProxy_NodeGroup0 Constructor %d\n",CkLocalNodeBranch(_ck_gid));
959     }
960     CProxy_NodeGroup(CkGroupID g)
961        :CProxy(),_ck_gid(g) {/*CkPrintf("In CProxy_NodeGroup1 Constructor %d\n",CkLocalNodeBranch(_ck_gid));*/}
962     CProxy_NodeGroup(CkGroupID g,CK_DELCTOR_PARAM)
963         :CProxy(CK_DELCTOR_ARGS),_ck_gid(g) {/*CkPrintf("In CProxy_NodeGroup2 Constructor %d\n",CkLocalNodeBranch(_ck_gid));*/}
964     CProxy_NodeGroup(const IrrGroup *g)
965         :CProxy(), _ck_gid(g->ckGetGroupID()) {/*CkPrintf("In CProxy_NodeGroup3 Constructor %d\n",CkLocalNodeBranch(_ck_gid));*/}
966 /*    CProxy_Group(const NodeGroup *g)  //<- for compatability with NodeGroups
967         :CProxy(), _ck_gid(g->ckGetGroupID()) {}*/
968
969 #if CMK_ERROR_CHECKING
970     inline void ckCheck(void) const {   //Make sure this proxy has a value
971         if (_ck_gid.isZero())
972                 CkAbort("Error! This group proxy has not been initialized!");
973     }
974 #else
975     inline void ckCheck() const {}
976 #endif
977
978     CkChareID ckGetChareID(void) const {
979         CkChareID ret;
980         ret.onPE=CkMyPe();
981         ret.objPtr=CkLocalBranch(_ck_gid);
982         return ret;
983     }
984     CkGroupID ckGetGroupID(void) const {return _ck_gid;}
985     operator CkGroupID () const {return ckGetGroupID();}
986     void ckSetGroupID(CkGroupID g) {_ck_gid=g;}
987     void pup(PUP::er &p) {
988         CProxy::pup(p);
989         p | _ck_gid;
990     }
991     CK_REDUCTION_CLIENT_DECL
992
993 };
994
995 typedef CProxy_Group CProxy_IrrGroup;
996 typedef CProxyElement_Group CProxyElement_NodeGroup;
997 typedef CProxyElement_Group CProxyElement_IrrGroup;
998 typedef CProxySection_Group CProxySection_NodeGroup;
999 typedef CProxySection_Group CProxySection_IrrGroup;
1000
1001
1002 //(CProxy_ArrayBase is defined in ckarray.h)
1003
1004 //Defines the actual "Group"
1005 #include "ckreduction.h"
1006
1007 class CkQdMsg {
1008   public:
1009     void *operator new(size_t s) { return CkAllocMsg(0,(int)s,0); }
1010     void operator delete(void* ptr) { CkFreeMsg(ptr); }
1011     static void *alloc(int, size_t s, int*, int) {
1012       return CkAllocMsg(0,(int)s,0);
1013     }
1014     static void *pack(CkQdMsg *m) { return (void*) m; }
1015     static CkQdMsg *unpack(void *buf) { return (CkQdMsg*) buf; }
1016 };
1017
1018 class CkThrCallArg {
1019   public:
1020     void *msg;
1021     void *obj;
1022     CkThrCallArg(void *m, void *o) : msg(m), obj(o) {}
1023 };
1024
1025 extern void CkStartQD(const CkCallback& cb);
1026 #define CkExitAfterQuiescence() CkStartQD(CkCallback(CkCallback::ckExit))
1027
1028
1029 #if !CMK_MACHINE_PROGRESS_DEFINED
1030 #define CkNetworkProgress() 
1031 #define CkNetworkProgressAfter(p) 
1032
1033 #else
1034 void CmiMachineProgressImpl();
1035
1036 #define CkNetworkProgress() {CpvAccess(networkProgressCount) ++; \
1037 if(CpvAccess(networkProgressCount) >=  networkProgressPeriod)  \
1038     if (LBDatabaseObj()->getLBDB()->StatsOn() == 0) { \
1039         CmiMachineProgressImpl(); \
1040         CpvAccess(networkProgressCount) = 0; \
1041     } \
1042 } \
1043
1044 #define CkNetworkProgressAfter(p) {CpvAccess(networkProgressCount) ++; \
1045 if(CpvAccess(networkProgressCount) >=  p)  \
1046     if (LBDatabaseObj()->getLBDB()->StatsOn() == 0) { \
1047         CmiMachineProgressImpl(); \
1048         CpvAccess(networkProgressCount) = 0; \
1049     } \
1050 } \
1051
1052 #endif
1053
1054
1055 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1056 #include "ckmessagelogging.h"
1057 #endif
1058 #include "ckmemcheckpoint.h"
1059 #include "readonly.h"
1060 #include "ckarray.h"
1061 #include "ckstream.h"
1062 #include "CkFutures.decl.h"
1063 #include "charisma.h"
1064 #include "tempo.h"
1065 #include "waitqd.h"
1066 #include "sdag.h"
1067 #include "ckcheckpoint.h"
1068 #include "ckevacuation.h"
1069 #include "ckarrayreductionmgr.h"
1070 #include "trace.h"
1071 #include "envelope.h"
1072
1073
1074
1075
1076
1077
1078 CkMarshallMsg *CkAllocateMarshallMsgNoninline(int size,const CkEntryOptions *opts);
1079 inline CkMarshallMsg *CkAllocateMarshallMsg(int size,const CkEntryOptions *opts=NULL)
1080 {
1081         if (opts==NULL) {
1082           CkMarshallMsg *newMemory = new (size,0)CkMarshallMsg;
1083           setMemoryTypeMessage(UsrToEnv(newMemory));
1084           return newMemory;
1085         }
1086         else return CkAllocateMarshallMsgNoninline(size,opts);
1087 }
1088
1089
1090
1091
1092
1093
1094
1095 template <typename T> 
1096 inline T *CkAllocateMarshallMsgT(int size,const CkEntryOptions *opts) 
1097
1098   int priobits = 0; 
1099   if (opts!=NULL) priobits = opts->getPriorityBits(); 
1100   //Allocate the message 
1101   T *m=new (size,priobits)T; 
1102   //Copy the user's priority data into the message 
1103   envelope *env=UsrToEnv(m); 
1104   setMemoryTypeMessage(env); 
1105   if (opts!=NULL) { 
1106     CmiMemcpy(env->getPrioPtr(),opts->getPriorityPtr(),env->getPrioBytes()); 
1107     //Set the message's queueing type 
1108     env->setQueueing((unsigned char)opts->getQueueing()); 
1109   } 
1110   return m; 
1111
1112
1113
1114
1115
1116
1117 /************************** Debugging Utilities **************/
1118
1119 CkpvExtern(DebugEntryTable, _debugEntryTable);
1120
1121 //For debugging: convert given index to a string (NOT threadsafe)
1122 static const char *idx2str(const CkArrayIndex &ind) {
1123   static char retBuf[80];
1124   retBuf[0]=0;
1125   if (ind.dimension <= 3) {
1126     for (int i=0;i<ind.nInts;i++) {
1127       if (i>0) strcat(retBuf,";");
1128       sprintf(&retBuf[strlen(retBuf)],"%d",ind.data()[i]);
1129     }
1130   } else {
1131     const short int *idx = (const short int*)ind.data();
1132     for (int i=0;i<ind.dimension;i++) {
1133       if (i>0) strcat(retBuf,";");
1134       sprintf(&retBuf[strlen(retBuf)],"%hd",idx[i]);
1135     }
1136   }
1137   return retBuf;
1138 }
1139
1140 static const char *idx2str(const ArrayElement *el) {
1141   return idx2str(el->thisIndexMax);
1142 }
1143
1144
1145
1146 class CkConditional {
1147   int refcount;
1148 public:
1149   CkConditional() : refcount(1) { }
1150   virtual ~CkConditional() { }
1151     /*
1152   void* operator new(size_t s) {
1153     return malloc(s);
1154   }
1155     */
1156   void deallocate() {
1157     //CkPrintf("CkConditional::delete %d\n",refcount);
1158     if (--refcount == 0) {
1159       //((CkConditional*)p)->~CkConditional();
1160       delete this;
1161     }
1162   }
1163   void copyreference(void) {
1164     ++refcount;
1165   }
1166 };
1167
1168
1169 #endif
1170
1171
1172