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