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