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