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