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