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