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