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