d430e0eebee97c87d24d0bc8e8baa9036832c7d8
[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 bool _isAnytimeMigration;
43
44 /** This flag is true when users are sure there is at least one charm array element
45  *  per processor. In such case, when doing reduction on the array, the children
46  *  don't need to be notified that reduction starts
47  */
48 extern bool _isNotifyChildInRed;
49
50 /**
51 \addtogroup CkArray
52 \brief Migratable Chare Arrays: user-visible classes.
53
54 All these classes are defined in ckarray.C.
55 */
56 /*@{*/
57
58 typedef int CkIndex1D;
59 typedef struct {int x,y;} CkIndex2D;
60 inline void operator|(PUP::er &p,CkIndex2D &i) {p(i.x); p(i.y);}
61 typedef struct {int x,y,z;} CkIndex3D;
62 inline void operator|(PUP::er &p,CkIndex3D &i) {p(i.x); p(i.y); p(i.z);}
63 typedef struct {short int w,x,y,z;} CkIndex4D;
64 inline void operator|(PUP::er &p,CkIndex4D &i) {p(i.w); p(i.x); p(i.y); p(i.z);}
65 typedef struct {short int v,w,x,y,z;} CkIndex5D;
66 inline void operator|(PUP::er &p,CkIndex5D &i) {p(i.v); p(i.w); p(i.x); p(i.y); p(i.z);}
67 typedef struct {short int x1,y1,z1,x2,y2,z2;} CkIndex6D;
68 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);}
69 typedef struct {int data[CK_ARRAYINDEX_MAXLEN];} CkIndexMax;
70 inline void operator|(PUP::er &p,CkIndexMax &i) {
71   for (int j=0;j<CK_ARRAYINDEX_MAXLEN;j++) {
72     p|i.data[j];
73   }
74 }
75
76 /// Simple ArrayIndex classes: the key is just integer indices.
77 class CkArrayIndex1D : public CkArrayIndex {
78 public:
79         CkArrayIndex1D() {}
80         // CkIndex1D is an int, so that conversion is automatic
81         CkArrayIndex1D(int i0) { init(1, 1, i0); }
82 };
83 class CkArrayIndex2D : public CkArrayIndex {
84 public:
85         CkArrayIndex2D() {}
86         CkArrayIndex2D(int i0,int i1) { init(2, 2, i0, i1); }
87         CkArrayIndex2D(CkIndex2D idx) { init(2, 2, idx.x, idx.y); }
88 };
89 class CkArrayIndex3D : public CkArrayIndex {
90 public:
91         CkArrayIndex3D() {}
92         CkArrayIndex3D(int i0,int i1,int i2) { init(3, 3, i0, i1, i2); }
93         CkArrayIndex3D(CkIndex3D idx) { init(3, 3, idx.x, idx.y, idx.z); }
94 };
95 class CkArrayIndex4D : public CkArrayIndex {
96 public:
97         CkArrayIndex4D(){}
98         CkArrayIndex4D(short int i0,short int i1,short int i2,short int i3) { init(2, 4, i0, i1, i2, i3); }
99         CkArrayIndex4D(CkIndex4D idx) { init(2, 4, idx.w, idx.x, idx.y, idx.z); }
100 };
101 class CkArrayIndex5D : public CkArrayIndex {
102 public:
103         CkArrayIndex5D() {}
104         CkArrayIndex5D(short int i0,short int i1,short int i2,short int i3,short int i4) { init(3, 5, i0, i1, i2, i3, i4); }
105         CkArrayIndex5D(CkIndex5D idx) { init(3, 5, idx.v, idx.w, idx.x, idx.y, idx.z); }
106 };
107 class CkArrayIndex6D : public CkArrayIndex {
108 public:
109         CkArrayIndex6D(){}
110         CkArrayIndex6D(short int i0,short int i1,short int i2,short int i3,short int i4,short int i5) { init(3, 6, i0, i1, i2, i3, i4, i5); }
111         CkArrayIndex6D(CkIndex6D idx) { init(3, 6, idx.x1, idx.y1, idx.z1, idx.x2, idx.y2, idx.z2); }
112 };
113
114 /** A slightly more complex array index: the key is an object
115  *  whose size is fixed at compile time.
116  */
117 template <class object> //Key object
118 class CkArrayIndexT : public CkArrayIndex {
119 public:
120         object obj;
121         CkArrayIndexT(const object &srcObj) {obj=srcObj;
122                 nInts=sizeof(obj)/sizeof(int);
123                 dimension=0; }
124 };
125
126 /********************* CkArrayListener ****************/
127 ///An arrayListener is an object that gets informed whenever
128 /// an array element is created, migrated, or destroyed.
129 ///This abstract superclass just ignores everything sent to it.
130 class ArrayElement;
131 class CkArrayListener : public PUP::able {
132   int nInts; //Number of ints of data to store per element
133   int dataOffset; //Int offset of our data within the element
134  public:
135   CkArrayListener(int nInts_);
136   CkArrayListener(CkMigrateMessage *m);
137   virtual void pup(PUP::er &p);
138   PUPable_abstract(CkArrayListener)
139
140   ///Register this array type.  Our data is stored in the element at dataOffset
141   virtual void ckRegister(CkArray *arrMgr,int dataOffset_);
142
143   ///Return the number of ints of data to store per element
144   inline int ckGetLen(void) const {return nInts;}
145   ///Return the offset of our data into the element
146   inline int ckGetOffset(void) const {return dataOffset;}
147   ///Return our data associated with this array element
148   inline int *ckGetData(ArrayElement *el) const;
149
150   ///Elements may be being created
151   virtual void ckBeginInserting(void) {}
152   ///No more elements will be created (for now)
153   virtual void ckEndInserting(void) {}
154
155 //The stamp/creating/created/died sequence happens, in order, exactly
156 // once per array element.  Migrations don't show up here.
157   ///Element creation message is about to be sent
158   virtual void ckElementStamp(int *eltInfo) {}
159   ///Element is about to be created on this processor
160   virtual void ckElementCreating(ArrayElement *elt) {}
161   ///Element was just created on this processor
162   /// Return false if the element migrated away or deleted itself.
163   virtual CmiBool ckElementCreated(ArrayElement *elt)
164     { return CmiTrue; }
165
166   ///Element is about to be destroyed
167   virtual void ckElementDied(ArrayElement *elt) {}
168
169 //The leaving/arriving seqeunce happens once per migration.
170   ///Element is about to leave this processor (so about to call pup)
171   virtual void ckElementLeaving(ArrayElement *elt) {}
172
173   ///Element just arrived on this processor (so just called pup)
174   /// Return false if the element migrated away or deleted itself.
175   virtual CmiBool ckElementArriving(ArrayElement *elt)
176     { return CmiTrue; }
177
178   /// used by checkpointing to reset the states
179   virtual void flushState()  {}
180 };
181
182 /*@}*/
183
184 //This simple arrayListener just prints each event to stdout:
185 class CkVerboseListener : public CkArrayListener {
186  public:
187   CkVerboseListener(void);
188   CkVerboseListener(CkMigrateMessage *m):CkArrayListener(m) {}
189   PUPable_decl(CkVerboseListener);
190
191   virtual void ckRegister(CkArray *arrMgr,int dataOffset_);
192   virtual void ckBeginInserting(void);
193   virtual void ckEndInserting(void);
194
195   virtual void ckElementStamp(int *eltInfo);
196   virtual void ckElementCreating(ArrayElement *elt);
197   virtual CmiBool ckElementCreated(ArrayElement *elt);
198   virtual void ckElementDied(ArrayElement *elt);
199
200   virtual void ckElementLeaving(ArrayElement *elt);
201   virtual CmiBool ckElementArriving(ArrayElement *elt);
202 };
203
204 /**
205 \addtogroup CkArray
206 */
207 /*@{*/
208 /*********************** CkArrayOptions *******************************/
209 /// Arguments for array creation:
210 class CkArrayOptions {
211         friend class CkArray;
212
213         CkArrayIndex numInitial;///< Number of elements to create
214         CkGroupID map;///< Array location map object
215         CkGroupID locMgr;///< Location manager to bind to
216         CkPupAblePtrVec<CkArrayListener> arrayListeners; //CkArrayListeners for this array
217         CkCallback reductionClient; // Default target of reductions
218         bool anytimeMigration; // Elements are allowed to move freely
219         bool disableNotifyChildInRed; //Child elements are not notified when reduction starts
220         bool staticInsertion; // Elements are only inserted at construction
221
222         /// Set various safe defaults for all the constructors
223         void init();
224
225  public:
226  //Used by external world:
227         CkArrayOptions(void); ///< Default: empty array
228         CkArrayOptions(int ni1_); ///< With initial elements 1D
229         CkArrayOptions(int ni1_, int ni2_); ///< With initial elements 2D 
230         CkArrayOptions(int ni1_, int ni2_, int ni3); ///< With initial elements 3D
231         //CkArrayOptions(short ni1_, short ni2_, short ni3, short ni4_); ///< With initial elements 4D
232         //CkArrayOptions(short ni1_, short ni2_, short ni3, short ni4_, short ni5_); ///< With initial elements 5D
233         //CkArrayOptions(short ni1_, short ni2_, short ni3, short ni4_, short ni5_, short ni6_); ///< With initial elements 6D
234
235         /**
236          * These functions return "this" so you can string them together, e.g.:
237          *   foo(CkArrayOptions().setMap(mid).bindTo(aid));
238          */
239
240         /// Create this many initial elements 1D
241         CkArrayOptions &setNumInitial(int ni)
242                 {numInitial=CkArrayIndex1D(ni); return *this;}
243         /// Create this many initial elements 2D
244         CkArrayOptions &setNumInitial(int ni1, int ni2)
245                 {numInitial=CkArrayIndex2D(ni1, ni2); return *this;}
246         /// Create this many initial elements 3D
247         CkArrayOptions &setNumInitial(int ni1, int ni2, int ni3)
248                 {numInitial=CkArrayIndex3D(ni1 ,ni2, ni3); return *this;}
249         /*
250         /// Create this many initial elements 4D
251         CkArrayOptions &setNumInitial(short ni1, short ni2, short ni3, short ni4)
252                 {numInitial=CkArrayIndex4D(ni1, ni2, ni3, ni4); return *this;}
253         /// Create this many initial elements 5D
254         CkArrayOptions &setNumInitial(short ni1, short ni2, short ni3, short ni4, short ni5)
255                 {numInitial=CkArrayIndex5D(ni1, ni2, ni3, ni4, ni5); return *this;}
256         /// Create this many initial elements 6D
257         CkArrayOptions &setNumInitial(short ni1, short ni2, short ni3, short ni4, short ni5, short ni6)
258                 {numInitial=CkArrayIndex6D(ni1, ni2, ni3, ni4, ni5, ni6); return *this;}
259         */
260
261         /// Use this location map
262         CkArrayOptions &setMap(const CkGroupID &m)
263                 {map=m; return *this;}
264
265         /// Bind our elements to this array
266         CkArrayOptions &bindTo(const CkArrayID &b);
267
268         /// Use this location manager
269         CkArrayOptions &setLocationManager(const CkGroupID &l)
270                 {locMgr=l; return *this;}
271
272         /// Add an array listener component to this array (keeps the new'd listener)
273         CkArrayOptions &addListener(CkArrayListener *listener);
274
275         CkArrayOptions &setAnytimeMigration(bool b) { anytimeMigration = b; return *this; }
276         CkArrayOptions &setStaticInsertion(bool b);
277         CkArrayOptions &setReductionClient(CkCallback cb)
278         { reductionClient = cb; return *this; }
279
280   //Used by the array manager:
281         const CkArrayIndex &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 #if CMK_ERROR_CHECKING
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 #if CMK_ERROR_CHECKING
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         unsigned int numLocalElements() const { return ckLocMgr()->numLocalElements(); }
340
341         void doneInserting(void);
342
343         CK_REDUCTION_CLIENT_DECL
344
345         void pup(PUP::er &p);
346 };
347 PUPmarshall(CProxy_ArrayBase)
348
349 class CProxyElement_ArrayBase:public CProxy_ArrayBase {
350 private:
351         CkArrayIndex _idx;//<- our element's array index
352 public:
353         CProxyElement_ArrayBase() { }
354         CProxyElement_ArrayBase(const CkArrayID &aid,
355                 const CkArrayIndex &idx,CK_DELCTOR_PARAM)
356                 :CProxy_ArrayBase(aid,CK_DELCTOR_ARGS), _idx(idx) { }
357         CProxyElement_ArrayBase(const CkArrayID &aid, const CkArrayIndex &idx)
358                 :CProxy_ArrayBase(aid), _idx(idx) { }
359         CProxyElement_ArrayBase(const ArrayElement *e);
360
361         void ckInsert(CkArrayMessage *m,int ctor,int onPe);
362         void ckSend(CkArrayMessage *m, int ep, int opts = 0) const;
363 //      static void ckSendWrapper(void *me, void *m, int ep, int opts = 0);
364       static void ckSendWrapper(CkArrayID _aid, CkArrayIndex _idx, void *m, int ep, int opts);
365         void *ckSendSync(CkArrayMessage *m, int ep) const;
366         const CkArrayIndex &ckGetIndex() const {return _idx;}
367
368         ArrayElement *ckLocal(void) const;
369         void pup(PUP::er &p);
370 };
371 PUPmarshall(CProxyElement_ArrayBase)
372
373 class CProxySection_ArrayBase:public CProxy_ArrayBase {
374 private:
375         int _nsid;
376         CkSectionID *_sid;
377 public:
378         CProxySection_ArrayBase(): _nsid(0), _sid(NULL) {}
379         CProxySection_ArrayBase(const CkArrayID &aid,
380                 const CkArrayIndex *elems, const int nElems)
381                 :CProxy_ArrayBase(aid), _nsid(1) { _sid = new CkSectionID(aid, elems, nElems); }
382         CProxySection_ArrayBase(const CkArrayID &aid,
383                 const CkArrayIndex *elems, const int nElems, CK_DELCTOR_PARAM)
384                 :CProxy_ArrayBase(aid,CK_DELCTOR_ARGS), _nsid(1) { _sid = new CkSectionID(aid, elems, nElems); }
385         CProxySection_ArrayBase(const CkSectionID &sid)
386                 :CProxy_ArrayBase(sid._cookie.aid), _nsid(1) { _sid = new CkSectionID(sid); }
387         CProxySection_ArrayBase(const CkSectionID &sid, CK_DELCTOR_PARAM)
388                 :CProxy_ArrayBase(sid._cookie.aid, CK_DELCTOR_ARGS), _nsid(1) { _sid = new CkSectionID(sid); }
389         CProxySection_ArrayBase(const CProxySection_ArrayBase &cs)
390                 :CProxy_ArrayBase(cs.ckGetArrayID()), _nsid(cs._nsid) {
391       if (_nsid == 1) _sid = new CkSectionID(cs.ckGetArrayID(), cs.ckGetArrayElements(), cs.ckGetNumElements());
392       else if (_nsid > 1) {
393         _sid = new CkSectionID[_nsid];
394         for (int i=0; i<_nsid; ++i) _sid[i] = cs._sid[i];
395       } else _sid = NULL;
396     }
397         CProxySection_ArrayBase(const CProxySection_ArrayBase &cs, CK_DELCTOR_PARAM)
398                 :CProxy_ArrayBase(cs.ckGetArrayID(),CK_DELCTOR_ARGS), _nsid(cs._nsid) {
399       if (_nsid == 1) _sid = new CkSectionID(cs.ckGetArrayID(), cs.ckGetArrayElements(), cs.ckGetNumElements());
400       else if (_nsid > 1) {
401         _sid = new CkSectionID[_nsid];
402         for (int i=0; i<_nsid; ++i) _sid[i] = cs._sid[i];
403       } else _sid = NULL;
404     }
405     CProxySection_ArrayBase(const int n, const CkArrayID *aid, CkArrayIndex const * const *elems, const int *nElems)
406         :CProxy_ArrayBase(aid[0]), _nsid(n) {
407       if (_nsid == 1) _sid = new CkSectionID(aid[0], elems[0], nElems[0]);
408       else if (_nsid > 1) {
409       _sid = new CkSectionID[n];
410       for (int i=0; i<n; ++i) _sid[i] = CkSectionID(aid[i], elems[i], nElems[i]);
411       } else _sid = NULL;
412     }
413     CProxySection_ArrayBase(const int n, const CkArrayID *aid, CkArrayIndex const * const *elems, const int *nElems,CK_DELCTOR_PARAM)
414         :CProxy_ArrayBase(aid[0],CK_DELCTOR_ARGS), _nsid(n) {
415       if (_nsid == 1) _sid = new CkSectionID(aid[0], elems[0], nElems[0]);
416       else if (_nsid > 1) {
417       _sid = new CkSectionID[n];
418       for (int i=0; i<n; ++i) _sid[i] = CkSectionID(aid[i], elems[i], nElems[i]);
419       } else _sid = NULL;
420     }
421
422     ~CProxySection_ArrayBase() {
423       if (_nsid == 1) delete _sid;
424       else if (_nsid > 1) delete[] _sid;
425     }
426
427     CProxySection_ArrayBase &operator=(const CProxySection_ArrayBase &cs) {
428       CProxy_ArrayBase::operator=(cs);
429       _nsid = cs._nsid;
430       if (_nsid == 1) _sid = new CkSectionID(*cs._sid);
431       else if (_nsid > 1) {
432         _sid = new CkSectionID[_nsid];
433         for (int i=0; i<_nsid; ++i) _sid[i] = cs._sid[i];
434       } else _sid = NULL;
435       return *this;
436     }
437     
438         void ckSectionDelegate(CkDelegateMgr *d) 
439                 { ckDelegate(d); d->initDelegateMgr(this); }
440 //      void ckInsert(CkArrayMessage *m,int ctor,int onPe);
441         void ckSend(CkArrayMessage *m, int ep, int opts = 0) ;
442
443 //      ArrayElement *ckLocal(void) const;
444     inline int ckGetNumSubSections() const { return _nsid; }
445         inline CkSectionInfo &ckGetSectionInfo() {return _sid->_cookie;}
446         inline CkSectionID *ckGetSectionIDs() {return _sid;}
447         inline CkSectionID &ckGetSectionID() {return _sid[0];}
448         inline CkSectionID &ckGetSectionID(int i) {return _sid[i];}
449         inline CkArrayID ckGetArrayIDn(int i) const {return _sid[i]._cookie.aid;}
450     inline CkArrayIndex *ckGetArrayElements() const {return _sid[0]._elems;}
451     inline CkArrayIndex *ckGetArrayElements(int i) const {return _sid[i]._elems;}
452     inline int ckGetNumElements() const { return _sid[0]._nElems; }
453         inline int ckGetNumElements(int i) const { return _sid[i]._nElems; }
454         void pup(PUP::er &p);
455 };
456 PUPmarshall(CProxySection_ArrayBase)
457
458 //Simple C-like API:
459 void CkSendMsgArray(int entryIndex, void *msg, CkArrayID aID, const CkArrayIndex &idx, int opts=0);
460 void CkSendMsgArrayInline(int entryIndex, void *msg, CkArrayID aID, const CkArrayIndex &idx, int opts=0);
461 void CkBroadcastMsgArray(int entryIndex, void *msg, CkArrayID aID, int opts=0);
462
463 /************************ Array Element *********************/
464 /**
465  *An array element is a chare that lives inside the array.
466  *Unlike regular chares, array elements can migrate from one
467  *Pe to another.  Each element has a unique index.
468  */
469
470 class ArrayElement : public CkMigratable
471 {
472   friend class CkArray;
473   friend class CkArrayListener;
474   int numInitialElements; // Number of elements created by ckNew(numElements)
475   void initBasics(void);
476 public:
477   ArrayElement(void);
478   ArrayElement(CkMigrateMessage *m);
479   virtual ~ArrayElement();
480
481 /// Pack/unpack routine (called before and after migration)
482   virtual void pup(PUP::er &p);
483
484 //Overridden functions:
485   /// Called by the system just before and after migration to another processor:
486   virtual void ckAboutToMigrate(void);
487   virtual void ckJustMigrated(void);
488   
489   virtual void ckJustRestored(void);
490   
491   virtual void ckDestroy(void);
492   virtual char *ckDebugChareName(void);
493   virtual int ckDebugChareID(char*, int);
494
495   /// Synonym for ckMigrate
496   inline void migrateMe(int toPe) {ckMigrate(toPe);}
497
498   CK_REDUCTION_CONTRIBUTE_METHODS_DECL
499
500   inline const CkArrayID &ckGetArrayID(void) const {return thisArrayID;}
501
502   inline int ckGetArraySize(void) const { return numInitialElements; }
503 protected:
504   CkArray *thisArray;//My source array
505   CkArrayID thisArrayID;//My source array's ID
506
507   //More verbose form of abort
508   virtual void CkAbort(const char *str) const;
509
510 private:
511 //Array implementation methods:
512 #ifndef CK_ARRAYLISTENER_MAXLEN
513 # define CK_ARRAYLISTENER_MAXLEN 3
514 #endif
515   int listenerData[CK_ARRAYLISTENER_MAXLEN];
516
517 #if CMK_MEM_CHECKPOINT
518 friend class CkMemCheckPT;
519 protected:
520   int budPEs[2];
521 private:
522   void init_checkpt();
523 #endif
524 public:
525         void inmem_checkpoint(CkArrayCheckPTReqMessage *m);
526         void recvBroadcast(CkMessage *);
527
528 #if CMK_GRID_QUEUE_AVAILABLE
529 public:
530   int grid_queue_interval;
531   int grid_queue_threshold;
532   int msg_count;
533   int msg_count_grid;
534   int border_flag;
535 #endif
536 };
537 inline int *CkArrayListener::ckGetData(ArrayElement *el) const
538   {return &el->listenerData[dataOffset];}
539
540 /**An ArrayElementT is a utility class where you are
541  * constrained to a "thisIndex" of some fixed-sized type T.
542  */
543 template <class T>
544 class ArrayElementT : public ArrayElement
545 {
546 public:
547   ArrayElementT(void): thisIndex(*(const T *)thisIndexMax.data()) {
548 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))     
549         mlogData->objID.data.array.idx=thisIndexMax;
550 #endif
551 }
552   ArrayElementT(CkMigrateMessage *msg)
553         :ArrayElement(msg),
554         thisIndex(*(const T *)thisIndexMax.data()) {}
555
556   const T thisIndex;/// Object array index
557 };
558
559 typedef ArrayElementT<CkIndex1D> ArrayElement1D;
560 typedef ArrayElementT<CkIndex2D> ArrayElement2D;
561 typedef ArrayElementT<CkIndex3D> ArrayElement3D;
562 typedef ArrayElementT<CkIndex4D> ArrayElement4D;
563 typedef ArrayElementT<CkIndex5D> ArrayElement5D;
564 typedef ArrayElementT<CkIndex6D> ArrayElement6D;
565 typedef ArrayElementT<CkIndexMax> ArrayElementMax;
566
567 /*@}*/
568
569
570 /*********************** Array Manager BOC *******************/
571 /**
572 \addtogroup CkArrayImpl
573 */
574 /*@{*/
575
576 #include "CkArray.decl.h"
577 #include "CkArrayReductionMgr.decl.h"
578
579 class CkArrayBroadcaster;
580 class CkArrayReducer;
581
582 void _ckArrayInit(void);
583
584 //#include "ComlibArrayListener.h"  FILE DELETED!
585
586 class CkArray : public CkReductionMgr, public CkArrMgr {
587   friend class ArrayElement;
588   friend class CProxy_ArrayBase;
589   friend class CProxyElement_ArrayBase;
590
591   CkMagicNumber<ArrayElement> magic; //To detect heap corruption
592   CkLocMgr *locMgr;
593   CkGroupID locMgrID;
594   CProxy_CkArray thisProxy;
595   typedef CkMigratableListT<ArrayElement> ArrayElementList;
596   ArrayElementList *elements;
597   bool stableLocations;
598
599 public:
600 //Array Creation:
601   CkArray(CkArrayOptions &c,CkMarshalledMessage &initMsg,CkNodeGroupID nodereductionProxy);
602   CkArray(CkMigrateMessage *m);
603   CkGroupID &getGroupID(void) {return thisgroup;}
604
605 //Access & information routines
606   inline CkLocMgr *getLocMgr(void) {return locMgr;}
607   inline const CkArrayIndex &getNumInitial(void) const {return numInitial;}
608   inline int homePe(const CkArrayIndex &idx) const {return locMgr->homePe(idx);}
609   inline int procNum(const CkArrayIndex &idx) const {return locMgr->procNum(idx);}
610
611   /// Return the last known processor for this array index.
612   /// Valid for any possible array index.
613   inline int lastKnown(const CkArrayIndex &idx) const
614           {return locMgr->lastKnown(idx);}
615   /// Deliver message to this element (directly if local)
616   /// doFree if is local
617   inline int deliver(CkMessage *m,CkDeliver_t type,int opts=0)
618           {return locMgr->deliver(m,type,opts);}
619   /// Fetch a local element via its index (return NULL if not local)
620   inline ArrayElement *lookup(const CkArrayIndex &index)
621           {return (ArrayElement *)locMgr->lookup(index,thisgroup);}
622
623 //Creation:
624   /// Create-after-migrate:
625   virtual CkMigratable *allocateMigrated(int elChareType,const CkArrayIndex &idx,
626                         CkElementCreation_t type);
627
628   /// Prepare creation message:
629   void prepareCtorMsg(CkMessage *m,int &onPe,const CkArrayIndex &idx);
630
631   /// Create initial array elements:
632   virtual void insertInitial(const CkArrayIndex &idx,void *ctorMsg,int local=1);
633   virtual void doneInserting(void);
634   void remoteDoneInserting(void);
635
636   /// Create manually:
637   virtual CmiBool insertElement(CkMessage *);
638
639 /// Demand-creation:
640   CmiBool demandCreateElement(const CkArrayIndex &idx,
641         int onPe,int ctor,CkDeliver_t type);
642
643 /// Broadcast communication:
644   void sendBroadcast(CkMessage *msg);
645   void recvBroadcast(CkMessage *msg);
646   void sendExpeditedBroadcast(CkMessage *msg);
647   void recvExpeditedBroadcast(CkMessage *msg) { recvBroadcast(msg); }
648
649   void pup(PUP::er &p);
650   void ckJustMigrated(void){ doneInserting(); }
651
652   // COMLIB HACK
653   // Ok, this has gone very far... getting rid of it!
654   //ComlibArrayListener * calistener;
655   //ComlibArrayListener * getComlibArrayListener() {return calistener;}
656
657   virtual CmiBool isArrMgr(void) {return CmiTrue;}
658
659 private:
660   CkArrayIndex numInitial;/// Number of initial array elements
661   CmiBool isInserting;/// Are we currently inserting elements?
662
663 /// Allocate space for a new array element
664   ArrayElement *allocate(int elChareType,const CkArrayIndex &idx,
665         CkMessage *msg,CmiBool fromMigration);
666
667 //Spring cleaning
668   void springCleaning(void);
669   static void staticSpringCleaning(void *forWhom,double curWallTime);
670
671 //ArrayListeners:
672 //Iterate over the CkArrayListeners in this vector, calling "inside" each time.
673 #define CK_ARRAYLISTENER_LOOP(listVec,inside) \
674   do { \
675         int lIdx,lMax=listVec.size();\
676         for (lIdx=0;lIdx<lMax;lIdx++) { \
677                 CkArrayListener *l=listVec[lIdx];\
678                 inside;\
679         }\
680   } while(0)
681
682   CkPupAblePtrVec<CkArrayListener> listeners;
683   int listenerDataOffset;
684  public:
685   void addListener(CkArrayListener *l) {
686     l->ckRegister(this,listenerDataOffset);
687     listenerDataOffset+=l->ckGetLen();
688     listeners.push_back(l);
689     if (listenerDataOffset>CK_ARRAYLISTENER_MAXLEN)
690       CkAbort("Too much array listener data!\n"
691               "You'll have to either use fewer array listeners, or increase the compile-time\n"
692               "constant CK_ARRAYLISTENER_MAXLEN!\n");
693   }
694  private:
695
696   CkArrayReducer *reducer; //Read-only copy of default reducer
697   CkArrayBroadcaster *broadcaster; //Read-only copy of default broadcaster
698 public:
699   void flushStates() { CkReductionMgr::flushStates(); CK_ARRAYLISTENER_LOOP(listeners, l->flushState()); }
700 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
701         // the mlogft only support 1D arrays, then returning the number of elements in the first dimension
702         virtual int numberReductionMessages(){CkAssert(CkMyPe() == 0);return numInitial.data()[0];}
703         void broadcastHomeElements(void *data,CkLocRec *rec,CkArrayIndex *index);
704         static void staticBroadcastHomeElements(CkArray *arr,void *data,CkLocRec *rec,CkArrayIndex *index);
705 #endif
706
707 };
708
709
710
711 /*@}*/
712
713 #endif