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