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