fixed CProxySection_ArrayBase default constructor which may resulted in random _nsid...
[charm.git] / src / ck-core / ckarray.h
1 /* Generalized Chare Arrays
2
3 These classes implement Chare Arrays.
4 These are dynamic (i.e. allowing insertion
5 and deletion) collections of ordinary Chares
6 indexed by arbitrary runs of bytes.
7
8 The general structure is:
9
10 CkArray is the "array manager" Group, or BOC--
11 it creates, keeps track of, and cares for all the
12 array elements on this PE (i.e.. "local" elements).
13 It does so using a hashtable of CkArrayRec objects--
14 there's an entry for each local, home-here, and recently
15 communicated remote array elements.
16
17 CkArrayElement is the type of the array
18 elements (a subclass of Chare).
19
20 CkArrayIndex is an arbitrary run of bytes,
21 used to index into the CkArray hashtable.
22
23 Converted from 1-D arrays 2/27/2000 by
24 Orion Sky Lawlor, olawlor@acm.org
25 */
26 #ifndef __CKARRAY_H
27 #define __CKARRAY_H
28
29 #include "cklocation.h"
30 #include "ckmemcheckpoint.h" // for CkArrayCheckPTReqMessage
31
32 /***********************************************************
33         Utility defines, includes, etc.
34 */
35 extern void _registerCkArray(void);
36 CpvExtern (int ,serializer);
37
38
39 /** This flag is true when in the system there is anytime migration, false when
40  *  the user code guarantees that no migration happens except during load balancing
41  *  (in which case it can only happen between AtSync and ResumeFromSync). */
42 extern CmiBool isAnytimeMigration;
43
44 /**
45 \addtogroup CkArray
46 \brief Migratable Chare Arrays: user-visible classes.
47
48 All these classes are defined in ckarray.C.
49 */
50 /*@{*/
51
52 /// Simple ArrayIndex classes: the key is just integer indices.
53 class CkArrayIndex1D : public CkArrayIndex {
54 public: int index;
55         CkArrayIndex1D() { nInts=1; dimension=1; }
56         CkArrayIndex1D(int i0) {
57                 index=i0;nInts=1;dimension=1;
58         }
59         CkArrayIndex1D &operator=(const CkArrayIndex1D &that)  {
60                 CmiAssert(that.nInts == 1);
61                 CmiAssert(that.dimension == 1);
62                 nInts = that.nInts;
63                 dimension = that.dimension;
64                 index = that.index;
65                 return *this;
66         }
67 };
68 class CkArrayIndex2D : public CkArrayIndex {
69 public: int index[2];
70         CkArrayIndex2D() { nInts=2; dimension=2; }
71         CkArrayIndex2D(int i0,int i1) {
72                 index[0]=i0;index[1]=i1;nInts=2;dimension=2;
73         }
74         CkArrayIndex2D &operator=(const CkArrayIndex2D &that)  {
75                 CmiAssert(that.nInts == 2);
76                 CmiAssert(that.dimension == 2);
77                 nInts = that.nInts;
78                 dimension = that.dimension;
79                 memcpy(index, that.index, sizeof(int)*2);
80                 return *this;
81         }
82 };
83 class CkArrayIndex3D : public CkArrayIndex {
84 public: int index[3];
85         CkArrayIndex3D() { nInts=3; dimension=3; }
86         CkArrayIndex3D(int i0,int i1,int i2) {
87                 index[0]=i0;index[1]=i1;index[2]=i2;nInts=3;dimension=3;
88         }
89         CkArrayIndex3D &operator=(const CkArrayIndex3D &that)  {
90                 CmiAssert(that.nInts == 3);
91                 CmiAssert(that.dimension == 3);
92                 nInts = that.nInts;
93                 dimension = that.dimension;
94                 memcpy(index, that.index, sizeof(int)*3);
95                 return *this;
96         }
97 };
98 class CkArrayIndex4D : public CkArrayIndex {
99 public: short int index[4];
100         CkArrayIndex4D(){ nInts=2; dimension=4; }
101         CkArrayIndex4D(short int i0,short int i1,short int i2,short int i3) {
102                 index[0]=i0;index[1]=i1;index[2]=i2;index[3]=i3;nInts=2;dimension=4;
103         }
104         CkArrayIndex4D &operator=(const CkArrayIndex4D &that)  {
105                 CmiAssert(that.nInts == 2);
106                 CmiAssert(that.dimension == 4);
107                 nInts = that.nInts;
108                 dimension = that.dimension;
109                 memcpy(index, that.index, sizeof(short int)*4);
110                 return *this;
111         }
112 };
113 class CkArrayIndex5D : public CkArrayIndex {
114 public: short int index[5];
115         CkArrayIndex5D(){ nInts=3; dimension=5; }
116         CkArrayIndex5D(short int i0,short int i1,short int i2,short int i3,short int i4) {
117                 index[0]=i0;index[1]=i1;index[2]=i2;index[3]=i3;index[4]=i4;nInts=3;dimension=5;
118         }
119         CkArrayIndex5D &operator=(const CkArrayIndex5D &that)  {
120                 CmiAssert(that.nInts == 3);
121                 CmiAssert(that.dimension == 5);
122                 nInts = that.nInts;
123                 dimension = that.dimension;
124                 memcpy(index, that.index, sizeof(short int)*5);;
125                 return *this;
126         }
127 };
128 class CkArrayIndex6D : public CkArrayIndex {
129 public: short int index[6];
130         CkArrayIndex6D(){ nInts=3; dimension=6; }
131         CkArrayIndex6D(short int i0,short int i1,short int i2,short int i3,short int i4,short int i5) {
132                 index[0]=i0;index[1]=i1;index[2]=i2;index[3]=i3;index[4]=i4;index[5]=i5;nInts=3;dimension=6;
133         }
134         CkArrayIndex6D &operator=(const CkArrayIndex6D &that)  {
135                 CmiAssert(that.nInts == 3);
136                 CmiAssert(that.dimension == 6);
137                 nInts = that.nInts;
138                 dimension = that.dimension;
139                 memcpy(index, that.index, sizeof(short int)*6);;
140                 return *this;
141         }
142 };
143
144 /** A slightly more complex array index: the key is an object
145  *  whose size is fixed at compile time.
146  */
147 template <class object> //Key object
148 class CkArrayIndexT : public CkArrayIndex {
149 public:
150         object obj;
151         CkArrayIndexT(const object &srcObj) {obj=srcObj;
152                 nInts=sizeof(obj)/sizeof(int);
153                 dimension=0; }
154 };
155
156 /********************* CkArrayListener ****************/
157 ///An arrayListener is an object that gets informed whenever
158 /// an array element is created, migrated, or destroyed.
159 ///This abstract superclass just ignores everything sent to it.
160 class ArrayElement;
161 class CkArrayListener : public PUP::able {
162   int nInts; //Number of ints of data to store per element
163   int dataOffset; //Int offset of our data within the element
164  public:
165   CkArrayListener(int nInts_);
166   CkArrayListener(CkMigrateMessage *m);
167   virtual void pup(PUP::er &p);
168   PUPable_abstract(CkArrayListener)
169
170   ///Register this array type.  Our data is stored in the element at dataOffset
171   virtual void ckRegister(CkArray *arrMgr,int dataOffset_);
172
173   ///Return the number of ints of data to store per element
174   inline int ckGetLen(void) const {return nInts;}
175   ///Return the offset of our data into the element
176   inline int ckGetOffset(void) const {return dataOffset;}
177   ///Return our data associated with this array element
178   inline int *ckGetData(ArrayElement *el) const;
179
180   ///Elements may be being created
181   virtual void ckBeginInserting(void) {}
182   ///No more elements will be created (for now)
183   virtual void ckEndInserting(void) {}
184
185 //The stamp/creating/created/died sequence happens, in order, exactly
186 // once per array element.  Migrations don't show up here.
187   ///Element creation message is about to be sent
188   virtual void ckElementStamp(int *eltInfo) {}
189   ///Element is about to be created on this processor
190   virtual void ckElementCreating(ArrayElement *elt) {}
191   ///Element was just created on this processor
192   /// Return false if the element migrated away or deleted itself.
193   virtual CmiBool ckElementCreated(ArrayElement *elt)
194     { return CmiTrue; }
195
196   ///Element is about to be destroyed
197   virtual void ckElementDied(ArrayElement *elt) {}
198
199 //The leaving/arriving seqeunce happens once per migration.
200   ///Element is about to leave this processor (so about to call pup)
201   virtual void ckElementLeaving(ArrayElement *elt) {}
202
203   ///Element just arrived on this processor (so just called pup)
204   /// Return false if the element migrated away or deleted itself.
205   virtual CmiBool ckElementArriving(ArrayElement *elt)
206     { return CmiTrue; }
207
208   /// used by checkpointing to reset the states
209   virtual void flushState()  {}
210 };
211
212 /*@}*/
213
214 //This simple arrayListener just prints each event to stdout:
215 class CkVerboseListener : public CkArrayListener {
216  public:
217   CkVerboseListener(void);
218   CkVerboseListener(CkMigrateMessage *m):CkArrayListener(m) {}
219   PUPable_decl(CkVerboseListener);
220
221   virtual void ckRegister(CkArray *arrMgr,int dataOffset_);
222   virtual void ckBeginInserting(void);
223   virtual void ckEndInserting(void);
224
225   virtual void ckElementStamp(int *eltInfo);
226   virtual void ckElementCreating(ArrayElement *elt);
227   virtual CmiBool ckElementCreated(ArrayElement *elt);
228   virtual void ckElementDied(ArrayElement *elt);
229
230   virtual void ckElementLeaving(ArrayElement *elt);
231   virtual CmiBool ckElementArriving(ArrayElement *elt);
232 };
233
234 /**
235 \addtogroup CkArray
236 */
237 /*@{*/
238 /*********************** CkArrayOptions *******************************/
239 /// Arguments for array creation:
240 class CkArrayOptions {
241         CkArrayIndexMax numInitial;///< Number of elements to create
242         CkGroupID map;///< Array location map object
243         CkGroupID locMgr;///< Location manager to bind to
244         CkPupAblePtrVec<CkArrayListener> arrayListeners; //CkArrayListeners for this array
245  public:
246  //Used by external world:
247         CkArrayOptions(void); ///< Default: empty array
248         CkArrayOptions(int ni1_); ///< With initial elements 1D
249         CkArrayOptions(int ni1_, int ni2_); ///< With initial elements 2D 
250         CkArrayOptions(int ni1_, int ni2_, int ni3); ///< With initial elements 3D
251         //CkArrayOptions(short ni1_, short ni2_, short ni3, short ni4_); ///< With initial elements 4D
252         //CkArrayOptions(short ni1_, short ni2_, short ni3, short ni4_, short ni5_); ///< With initial elements 5D
253         //CkArrayOptions(short ni1_, short ni2_, short ni3, short ni4_, short ni5_, short ni6_); ///< With initial elements 6D
254
255         /**
256          * These functions return "this" so you can string them together, e.g.:
257          *   foo(CkArrayOptions().setMap(mid).bindTo(aid));
258          */
259
260         /// Create this many initial elements 1D
261         CkArrayOptions &setNumInitial(int ni)
262                 {numInitial=CkArrayIndex1D(ni); return *this;}
263         /// Create this many initial elements 2D
264         CkArrayOptions &setNumInitial(int ni1, int ni2)
265                 {numInitial=CkArrayIndex2D(ni1, ni2); return *this;}
266         /// Create this many initial elements 3D
267         CkArrayOptions &setNumInitial(int ni1, int ni2, int ni3)
268                 {numInitial=CkArrayIndex3D(ni1 ,ni2, ni3); return *this;}
269         /*
270         /// Create this many initial elements 4D
271         CkArrayOptions &setNumInitial(short ni1, short ni2, short ni3, short ni4)
272                 {numInitial=CkArrayIndex4D(ni1, ni2, ni3, ni4); return *this;}
273         /// Create this many initial elements 5D
274         CkArrayOptions &setNumInitial(short ni1, short ni2, short ni3, short ni4, short ni5)
275                 {numInitial=CkArrayIndex5D(ni1, ni2, ni3, ni4, ni5); return *this;}
276         /// Create this many initial elements 6D
277         CkArrayOptions &setNumInitial(short ni1, short ni2, short ni3, short ni4, short ni5, short ni6)
278                 {numInitial=CkArrayIndex6D(ni1, ni2, ni3, ni4, ni5, ni6); return *this;}
279         */
280
281         /// Use this location map
282         CkArrayOptions &setMap(const CkGroupID &m)
283                 {map=m; return *this;}
284
285         /// Bind our elements to this array
286         CkArrayOptions &bindTo(const CkArrayID &b);
287
288         /// Use this location manager
289         CkArrayOptions &setLocationManager(const CkGroupID &l)
290                 {locMgr=l; return *this;}
291
292         /// Add an array listener component to this array (keeps the new'd listener)
293         CkArrayOptions &addListener(CkArrayListener *listener);
294
295   //Used by the array manager:
296         const CkArrayIndexMax &getNumInitial(void) const {return numInitial;}
297         const CkGroupID &getMap(void) const {return map;}
298         const CkGroupID &getLocationManager(void) const {return locMgr;}
299         int getListeners(void) const {return arrayListeners.size();}
300         CkArrayListener *getListener(int listenerNum) {
301                 CkArrayListener *ret=arrayListeners[listenerNum];
302                 arrayListeners[listenerNum]=NULL; //Don't throw away this listener
303                 return ret;
304         }
305
306         void pup(PUP::er &p);
307 };
308 PUPmarshall(CkArrayOptions);
309
310
311 /*********************** Proxy Support ************************/
312 //Needed by CBase_ArrayElement
313 class ArrayBase { /*empty*/ };
314 /*forward*/ class ArrayElement;
315
316 /**
317  * This class is a wrapper around a CkArrayIndex and ArrayID,
318  *  used by array element proxies.  This makes the translator's
319  *  job simpler, and the translated code smaller.
320  */
321 class CProxy_ArrayBase :public CProxy {
322 private:
323         CkArrayID _aid;
324 public:
325         CProxy_ArrayBase() {
326 #ifndef CMK_OPTIMIZE
327                 _aid.setZero();
328 #endif
329         }
330         CProxy_ArrayBase(const CkArrayID &aid,CK_DELCTOR_PARAM)
331                 :CProxy(CK_DELCTOR_ARGS), _aid(aid) { }
332         CProxy_ArrayBase(const ArrayElement *e);
333
334 #ifndef CMK_OPTIMIZE
335         inline void ckCheck(void) const{  //Make sure this proxy has a value
336           if (_aid.isZero())
337                 CkAbort("Error! This array proxy has not been initialized!");
338         }
339 #else
340         inline void ckCheck(void) const {}
341 #endif
342
343         static CkArrayID ckCreateEmptyArray(void);
344         static CkArrayID ckCreateArray(CkArrayMessage *m,int ctor,const CkArrayOptions &opts);
345
346         void ckInsertIdx(CkArrayMessage *m,int ctor,int onPe,const CkArrayIndex &idx);
347         void ckBroadcast(CkArrayMessage *m, int ep, int opts=0) const;
348         CkArrayID ckGetArrayID(void) const { return _aid; }
349         CkArray *ckLocalBranch(void) const { return _aid.ckLocalBranch(); }
350         CkLocMgr *ckLocMgr(void) const;
351         inline operator CkArrayID () const {return ckGetArrayID();}
352         unsigned int numLocalElements() const { return ckLocMgr()->numLocalElements(); }
353
354         void doneInserting(void);
355
356         CK_REDUCTION_CLIENT_DECL
357
358         void pup(PUP::er &p);
359 };
360 PUPmarshall(CProxy_ArrayBase);
361 #define CK_DISAMBIG_ARRAY(super) \
362         CK_DISAMBIG_CPROXY(super) \
363         inline void ckCheck(void) const {super::ckCheck();} \
364         inline operator CkArrayID () const {return ckGetArrayID();}\
365         inline static CkArrayID ckCreateEmptyArray(void)\
366           { return super::ckCreateEmptyArray(); }\
367         inline static CkArrayID ckCreateArray(CkArrayMessage *m,int ctor,const CkArrayOptions &opts)\
368           { return super::ckCreateArray(m,ctor,opts); }\
369         inline void ckInsertIdx(CkArrayMessage *m,int ctor,int onPe,const CkArrayIndex &idx) \
370           { super::ckInsertIdx(m,ctor,onPe,idx); }\
371         inline void ckBroadcast(CkArrayMessage *m, int ep, int opts=0) const \
372           { super::ckBroadcast(m,ep,opts); } \
373         inline CkArrayID ckGetArrayID(void) const \
374           { return super::ckGetArrayID();} \
375         inline CkArray *ckLocalBranch(void) const \
376           { return super::ckLocalBranch(); } \
377         inline CkLocMgr *ckLocMgr(void) const \
378           { return super::ckLocMgr(); } \
379         inline void doneInserting(void) { super::doneInserting(); }\
380         CK_REDUCTION_CLIENT_DISAMBIG(super) \
381
382
383 class CProxyElement_ArrayBase:public CProxy_ArrayBase {
384 private:
385         CkArrayIndexMax _idx;//<- our element's array index
386 public:
387         CProxyElement_ArrayBase() { }
388         CProxyElement_ArrayBase(const CkArrayID &aid,
389                 const CkArrayIndex &idx,CK_DELCTOR_PARAM)
390                 :CProxy_ArrayBase(aid,CK_DELCTOR_ARGS), _idx(idx) { }
391         CProxyElement_ArrayBase(const ArrayElement *e);
392
393         void ckInsert(CkArrayMessage *m,int ctor,int onPe);
394         void ckSend(CkArrayMessage *m, int ep, int opts = 0) const;
395 //      static void ckSendWrapper(void *me, void *m, int ep, int opts = 0);
396       static void ckSendWrapper(CkArrayID _aid, CkArrayIndexMax _idx, void *m, int ep, int opts);
397         void *ckSendSync(CkArrayMessage *m, int ep) const;
398         const CkArrayIndex &ckGetIndex() const {return _idx;}
399
400         ArrayElement *ckLocal(void) const;
401         void pup(PUP::er &p);
402 };
403 PUPmarshall(CProxyElement_ArrayBase);
404 #define CK_DISAMBIG_ARRAY_ELEMENT(super) \
405         CK_DISAMBIG_ARRAY(super) \
406         inline void ckInsert(CkArrayMessage *m,int ctor,int onPe) \
407           { super::ckInsert(m,ctor,onPe); }\
408         inline void ckSend(CkArrayMessage *m, int ep, int opts = 0) const \
409           { super::ckSend(m,ep,opts); }\
410         inline void *ckSendSync(CkArrayMessage *m, int ep) const \
411           { return super::ckSendSync(m,ep); }\
412         inline const CkArrayIndex &ckGetIndex() const \
413           { return super::ckGetIndex(); }\
414
415
416 class CProxySection_ArrayBase:public CProxy_ArrayBase {
417 private:
418         int _nsid;
419         CkSectionID *_sid;
420 public:
421         CProxySection_ArrayBase(): _nsid(0), _sid(NULL) {}
422         CProxySection_ArrayBase(const CkArrayID &aid,
423                 const CkArrayIndexMax *elems, const int nElems, CK_DELCTOR_PARAM)
424                 :CProxy_ArrayBase(aid,CK_DELCTOR_ARGS), _nsid(1) { _sid = new CkSectionID(aid, elems, nElems); }
425         CProxySection_ArrayBase(const CkSectionID &sid, CK_DELCTOR_PARAM)
426                 :CProxy_ArrayBase(sid._cookie.aid, CK_DELCTOR_ARGS), _nsid(1) { _sid = new CkSectionID(sid); }
427     CProxySection_ArrayBase(const CProxySection_ArrayBase &cs, CK_DELCTOR_PARAM)
428                 :CProxy_ArrayBase(cs.ckGetArrayID(),CK_DELCTOR_ARGS), _nsid(cs._nsid) {
429       if (_nsid == 1) _sid = new CkSectionID(cs.ckGetArrayID(), cs.ckGetArrayElements(), cs.ckGetNumElements());
430       else if (_nsid > 1) {
431         _sid = new CkSectionID[_nsid];
432         for (int i=0; i<_nsid; ++i) _sid[i] = cs._sid[i];
433       } else _sid = NULL;
434     }
435     CProxySection_ArrayBase(const int n, const CkArrayID *aid, const CkArrayIndexMax **elems, const int *nElems,CK_DELCTOR_PARAM)
436         :CProxy_ArrayBase(aid[0],CK_DELCTOR_ARGS), _nsid(n) {
437       _sid = new CkSectionID[n];
438       for (int i=0; i<n; ++i) _sid[i] = CkSectionID(aid[i], elems[i], nElems[i]);
439     }
440
441     ~CProxySection_ArrayBase() {
442       if (_nsid == 1) delete _sid;
443       else if (_nsid > 1) delete[] _sid;
444     }
445
446     CProxySection_ArrayBase &operator=(const CProxySection_ArrayBase &cs) {
447       CProxy_ArrayBase::operator=(cs);
448       _nsid = cs._nsid;
449       if (_nsid == 1) _sid = new CkSectionID(*cs._sid);
450       else if (_nsid > 1) {
451         _sid = new CkSectionID[_nsid];
452         for (int i=0; i<_nsid; ++i) _sid[i] = cs._sid[i];
453       } else _sid = NULL;
454       return *this;
455     }
456     
457         void ckSectionDelegate(CkDelegateMgr *d) 
458                 { ckDelegate(d); d->initDelegateMgr(this); }
459 //      void ckInsert(CkArrayMessage *m,int ctor,int onPe);
460         void ckSend(CkArrayMessage *m, int ep, int opts = 0) ;
461
462 //      ArrayElement *ckLocal(void) const;
463         inline CkSectionInfo &ckGetSectionInfo() {return _sid->_cookie;}
464         inline CkSectionID *ckGetSectionID() {return _sid;}
465         inline CkArrayID ckGetArrayIDn(int i) const {return _sid[i]._cookie.aid;}
466     inline CkArrayIndexMax *ckGetArrayElements() const {return _sid[0]._elems;}
467     inline CkArrayIndexMax *ckGetArrayElements(int i) const {return _sid[i]._elems;}
468     inline int ckGetNumElements() const { return _sid[0]._nElems; }
469         inline int ckGetNumElements(int i) const { return _sid[i]._nElems; }
470         void pup(PUP::er &p);
471 };
472 PUPmarshall(CProxySection_ArrayBase);
473 #define CK_DISAMBIG_ARRAY_SECTION(super) \
474         CK_DISAMBIG_ARRAY(super) \
475         inline void ckSend(CkArrayMessage *m, int ep, int opts = 0) \
476           { super::ckSend(m,ep,opts); } \
477         inline CkSectionInfo &ckGetSectionInfo() \
478           { return super::ckGetSectionInfo(); } \
479         inline CkSectionID *ckGetSectionID() \
480           { return super::ckGetSectionID(); } \
481         inline CkArrayID ckGetArrayIDn(int i) const \
482       { return super::ckGetArrayIDn(i); }  \
483         inline CkArrayIndexMax *ckGetArrayElements() const \
484           { return super::ckGetArrayElements(); } \
485         inline CkArrayIndexMax *ckGetArrayElements(int i) const \
486       { return super::ckGetArrayElements(i); } \
487         inline int ckGetNumElements() const \
488           { return super::ckGetNumElements(); }  \
489         inline int ckGetNumElements(int i) const \
490       { return super::ckGetNumElements(i); }  \
491
492 //Simple C-like API:
493 void CkSendMsgArray(int entryIndex, void *msg, CkArrayID aID, const CkArrayIndex &idx, int opts=0);
494 void CkSendMsgArrayInline(int entryIndex, void *msg, CkArrayID aID, const CkArrayIndex &idx, int opts=0);
495 void CkBroadcastMsgArray(int entryIndex, void *msg, CkArrayID aID, int opts=0);
496
497 /************************ Array Element *********************/
498 /**
499  *An array element is a chare that lives inside the array.
500  *Unlike regular chares, array elements can migrate from one
501  *Pe to another.  Each element has a unique index.
502  */
503
504 class ArrayElement : public CkMigratable
505 {
506   friend class CkArray;
507   friend class CkArrayListener;
508   void initBasics(void);
509 public:
510   ArrayElement(void);
511   ArrayElement(CkMigrateMessage *m);
512   virtual ~ArrayElement();
513
514   int numElements; /// Initial number of array elements (DEPRICATED)
515   // On the previous line, someone wrote "deprecated", but nevertheless it is still
516   // used on TempoArray (tempo.C), ampi.C, irecv (receiver.h), as well as many tests and examples!
517
518 /// Pack/unpack routine (called before and after migration)
519   virtual void pup(PUP::er &p);
520
521 //Overridden functions:
522   /// Called by the system just before and after migration to another processor:
523   virtual void ckAboutToMigrate(void);
524   virtual void ckJustMigrated(void);
525   
526   virtual void ckJustRestored(void);
527   
528   virtual void ckDestroy(void);
529   virtual char *ckDebugChareName(void);
530   virtual int ckDebugChareID(char*, int);
531
532   /// Synonym for ckMigrate
533   inline void migrateMe(int toPe) {ckMigrate(toPe);}
534
535   CK_REDUCTION_CONTRIBUTE_METHODS_DECL
536
537   const CkArrayID &ckGetArrayID(void) const {return thisArrayID;}
538
539 protected:
540   CkArray *thisArray;//My source array
541   CkArrayID thisArrayID;//My source array's ID
542
543   //More verbose form of abort
544   virtual void CkAbort(const char *str) const;
545
546 private:
547 //Array implementation methods:
548 #ifndef CK_ARRAYLISTENER_MAXLEN
549 # define CK_ARRAYLISTENER_MAXLEN 3
550 #endif
551   int listenerData[CK_ARRAYLISTENER_MAXLEN];
552
553 #if CMK_MEM_CHECKPOINT
554 friend class CkMemCheckPT;
555 protected:
556   int budPEs[2];
557 private:
558   void init_checkpt();
559 #endif
560 public:
561         void inmem_checkpoint(CkArrayCheckPTReqMessage *m);
562         void recvBroadcast(CkMessage *);
563
564 #if CMK_GRID_QUEUE_AVAILABLE
565 public:
566   int grid_queue_interval;
567   int grid_queue_threshold;
568   int msg_count;
569   int msg_count_grid;
570   int border_flag;
571 #endif
572 };
573 inline int *CkArrayListener::ckGetData(ArrayElement *el) const
574   {return &el->listenerData[dataOffset];}
575
576 /**An ArrayElementT is a utility class where you are
577  * constrained to a "thisIndex" of some fixed-sized type T.
578  */
579 template <class T>
580 class ArrayElementT : public ArrayElement
581 {
582 public:
583   ArrayElementT(void): thisIndex(*(const T *)thisIndexMax.data()) {
584 #ifdef _FAULT_MLOG_     
585         mlogData->objID.data.array.idx.asMax()=thisIndexMax;
586 #endif
587 }
588   ArrayElementT(CkMigrateMessage *msg)
589         :ArrayElement(msg),
590         thisIndex(*(const T *)thisIndexMax.data()) {}
591
592   const T thisIndex;/// Object array index
593 };
594
595 typedef int CkIndex1D;
596 typedef struct {int x,y;} CkIndex2D;
597 inline void operator|(PUP::er &p,CkIndex2D &i) {p(i.x); p(i.y);}
598 typedef struct {int x,y,z;} CkIndex3D;
599 inline void operator|(PUP::er &p,CkIndex3D &i) {p(i.x); p(i.y); p(i.z);}
600 typedef struct {short int w,x,y,z;} CkIndex4D;
601 inline void operator|(PUP::er &p,CkIndex4D &i) {p(i.w); p(i.x); p(i.y); p(i.z);}
602 typedef struct {short int v,w,x,y,z;} CkIndex5D;
603 inline void operator|(PUP::er &p,CkIndex5D &i) {p(i.v); p(i.w); p(i.x); p(i.y); p(i.z);}
604 typedef struct {short int x1,y1,z1,x2,y2,z2;} CkIndex6D;
605 inline void operator|(PUP::er &p,CkIndex6D &i) {p(i.x1); p(i.y1); p(i.z1); p(i.x2); p(i.y2); p(i.z2);}
606 typedef struct {int data[CK_ARRAYINDEX_MAXLEN];} CkIndexMax;
607 inline void operator|(PUP::er &p,CkIndexMax &i) {
608   for (int j=0;j<CK_ARRAYINDEX_MAXLEN;j++) {
609     p|i.data[j];
610   }
611 }
612
613 typedef ArrayElementT<CkIndex1D> ArrayElement1D;
614 typedef ArrayElementT<CkIndex2D> ArrayElement2D;
615 typedef ArrayElementT<CkIndex3D> ArrayElement3D;
616 typedef ArrayElementT<CkIndex4D> ArrayElement4D;
617 typedef ArrayElementT<CkIndex5D> ArrayElement5D;
618 typedef ArrayElementT<CkIndex6D> ArrayElement6D;
619 typedef ArrayElementT<CkIndexMax> ArrayElementMax;
620 /*@}*/
621
622
623 /*********************** Array Manager BOC *******************/
624 /**
625 \addtogroup CkArrayImpl
626 */
627 /*@{*/
628
629 #include "CkArray.decl.h"
630 #include "CkArrayReductionMgr.decl.h"
631
632 ///This arrayListener is in charge of delivering broadcasts to the array.
633 class CkArrayBroadcaster : public CkArrayListener {
634   inline int &getData(ArrayElement *el) {return *ckGetData(el);}
635 public:
636   CkArrayBroadcaster(void);
637   CkArrayBroadcaster(CkMigrateMessage *m);
638   virtual void pup(PUP::er &p);
639   virtual ~CkArrayBroadcaster();
640   PUPable_decl(CkArrayBroadcaster);
641
642   virtual void ckElementStamp(int *eltInfo) {*eltInfo=bcastNo;}
643
644   ///Element was just created on this processor
645   /// Return false if the element migrated away or deleted itself.
646   virtual CmiBool ckElementCreated(ArrayElement *elt)
647     { return bringUpToDate(elt); }
648
649   ///Element just arrived on this processor (so just called pup)
650   /// Return false if the element migrated away or deleted itself.
651   virtual CmiBool ckElementArriving(ArrayElement *elt)
652     { return bringUpToDate(elt); }
653
654   void incoming(CkArrayMessage *msg);
655
656   CmiBool deliver(CkArrayMessage *bcast,ArrayElement *el);
657
658   void springCleaning(void);
659
660   void flushState();
661 private:
662   int bcastNo;//Number of broadcasts received (also serial number)
663   int oldBcastNo;//Above value last spring cleaning
664   //This queue stores old broadcasts (in case a migrant arrives
665   // and needs to be brought up to date)
666   CkQ<CkArrayMessage *> oldBcasts;
667
668   CmiBool bringUpToDate(ArrayElement *el);
669 };
670
671 ///This arrayListener is in charge of performing reductions on the array.
672 class CkArrayReducer : public CkArrayListener {
673   CkGroupID mgrID;
674   CkReductionMgr *mgr;
675   typedef  contributorInfo *I;
676   inline contributorInfo *getData(ArrayElement *el)
677     {return (I)ckGetData(el);}
678 public:
679   /// Attach this array to this CkReductionMgr
680   CkArrayReducer(CkGroupID mgrID_);
681   CkArrayReducer(CkMigrateMessage *m);
682   virtual void pup(PUP::er &p);
683   virtual ~CkArrayReducer();
684   PUPable_decl(CkArrayReducer);
685
686   void ckBeginInserting(void) {mgr->creatingContributors();}
687   void ckEndInserting(void) {mgr->doneCreatingContributors();}
688
689   void ckElementStamp(int *eltInfo) {mgr->contributorStamped((I)eltInfo);}
690
691   void ckElementCreating(ArrayElement *elt)
692     {mgr->contributorCreated(getData(elt));}
693   void ckElementDied(ArrayElement *elt)
694     {mgr->contributorDied(getData(elt));}
695
696   void ckElementLeaving(ArrayElement *elt)
697     {mgr->contributorLeaving(getData(elt));}
698   CmiBool ckElementArriving(ArrayElement *elt)
699     {mgr->contributorArriving(getData(elt)); return CmiTrue; }
700 };
701
702 void _ckArrayInit(void);
703
704 //#include "ComlibArrayListener.h"  FILE DELETED!
705
706 class CkArray : public CkReductionMgr, public CkArrMgr {
707   friend class ArrayElement;
708   friend class CProxy_ArrayBase;
709   friend class CProxyElement_ArrayBase;
710
711   CkMagicNumber<ArrayElement> magic; //To detect heap corruption
712   CkLocMgr *locMgr;
713   CkGroupID locMgrID;
714   CProxy_CkArray thisProxy;
715   typedef CkMigratableListT<ArrayElement> ArrayElementList;
716   ArrayElementList *elements;
717
718 public:
719 //Array Creation:
720   CkArray(CkArrayOptions &c,CkMarshalledMessage &initMsg,CkNodeGroupID nodereductionProxy);
721   CkArray(CkMigrateMessage *m);
722   CkGroupID &getGroupID(void) {return thisgroup;}
723
724 //Access & information routines
725   inline CkLocMgr *getLocMgr(void) {return locMgr;}
726   inline const CkArrayIndexMax &getNumInitial(void) const {return numInitial;}
727   inline int homePe(const CkArrayIndex &idx) const {return locMgr->homePe(idx);}
728   inline int procNum(const CkArrayIndex &idx) const {return locMgr->procNum(idx);}
729
730   /// Return the last known processor for this array index.
731   /// Valid for any possible array index.
732   inline int lastKnown(const CkArrayIndex &idx) const
733           {return locMgr->lastKnown(idx);}
734   /// Deliver message to this element (directly if local)
735   /// doFree if is local
736   inline int deliver(CkMessage *m,CkDeliver_t type,int opts=0)
737           {return locMgr->deliver(m,type,opts);}
738   /// Fetch a local element via its index (return NULL if not local)
739   inline ArrayElement *lookup(const CkArrayIndex &index)
740           {return (ArrayElement *)locMgr->lookup(index,thisgroup);}
741
742 //Creation:
743   /// Create-after-migrate:
744   virtual CkMigratable *allocateMigrated(int elChareType,const CkArrayIndex &idx,
745                         CkElementCreation_t type);
746
747   /// Prepare creation message:
748   void prepareCtorMsg(CkMessage *m,int &onPe,const CkArrayIndex &idx);
749
750   /// Create initial array elements:
751   virtual void insertInitial(const CkArrayIndex &idx,void *ctorMsg,int local=1);
752   virtual void doneInserting(void);
753   void remoteDoneInserting(void);
754
755   /// Create manually:
756   virtual CmiBool insertElement(CkMessage *);
757
758 /// Demand-creation:
759   CmiBool demandCreateElement(const CkArrayIndex &idx,
760         int onPe,int ctor,CkDeliver_t type);
761
762 /// Broadcast communication:
763   void sendBroadcast(CkMessage *msg);
764   void recvBroadcast(CkMessage *msg);
765   void sendExpeditedBroadcast(CkMessage *msg);
766   void recvExpeditedBroadcast(CkMessage *msg) { recvBroadcast(msg); }
767
768   void pup(PUP::er &p);
769   void ckJustMigrated(void){ doneInserting(); }
770
771   // COMLIB HACK
772   // Ok, this has gone very far... getting rid of it!
773   //ComlibArrayListener * calistener;
774   //ComlibArrayListener * getComlibArrayListener() {return calistener;}
775
776   virtual CmiBool isArrMgr(void) {return CmiTrue;}
777
778 private:
779   CkArrayIndexMax numInitial;/// Number of initial array elements
780   CmiBool isInserting;/// Are we currently inserting elements?
781
782 /// Allocate space for a new array element
783   ArrayElement *allocate(int elChareType,const CkArrayIndex &idx,
784         CkMessage *msg,CmiBool fromMigration);
785
786 //Spring cleaning
787   void springCleaning(void);
788   static void staticSpringCleaning(void *forWhom,double curWallTime);
789
790 //ArrayListeners:
791 //Iterate over the CkArrayListeners in this vector, calling "inside" each time.
792 #define CK_ARRAYLISTENER_LOOP(listVec,inside) \
793   do { \
794         int lIdx,lMax=listVec.size();\
795         for (lIdx=0;lIdx<lMax;lIdx++) { \
796                 CkArrayListener *l=listVec[lIdx];\
797                 inside;\
798         }\
799   } while(0)
800
801   CkPupAblePtrVec<CkArrayListener> listeners;
802   int listenerDataOffset;
803  public:
804   void addListener(CkArrayListener *l) {
805     l->ckRegister(this,listenerDataOffset);
806     listenerDataOffset+=l->ckGetLen();
807     listeners.push_back(l);
808     if (listenerDataOffset>CK_ARRAYLISTENER_MAXLEN)
809       CkAbort("Too much array listener data!\n"
810               "You'll have to either use fewer array listeners, or increase the compile-time\n"
811               "constant CK_ARRAYLISTENER_MAXLEN!\n");
812   }
813  private:
814
815   CkArrayReducer *reducer; //Read-only copy of default reducer
816   CkArrayBroadcaster *broadcaster; //Read-only copy of default broadcaster
817 public:
818   void flushStates() { CkReductionMgr::flushStates(); CK_ARRAYLISTENER_LOOP(listeners, l->flushState()); }
819 #ifdef _FAULT_MLOG_
820         // the mlogft only support 1D arrays, then returning the number of elements in the first dimension
821         virtual int numberReductionMessages(){CkAssert(CkMyPe() == 0);return numInitial.data()[0];}
822         void broadcastHomeElements(void *data,CkLocRec *rec,CkArrayIndex *index);
823         static void staticBroadcastHomeElements(CkArray *arr,void *data,CkLocRec *rec,CkArrayIndex *index);
824 #endif
825
826 };
827
828
829
830 /*@}*/
831
832 #endif