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