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