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