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