Adding support for causal message logging.
[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
354         CK_REDUCTION_CLIENT_DECL
355
356         void pup(PUP::er &p);
357 };
358 PUPmarshall(CProxy_ArrayBase)
359
360 class CProxyElement_ArrayBase:public CProxy_ArrayBase {
361 private:
362         CkArrayIndex _idx;//<- our element's array index
363 public:
364         CProxyElement_ArrayBase() { }
365         CProxyElement_ArrayBase(const CkArrayID &aid,
366                 const CkArrayIndex &idx,CK_DELCTOR_PARAM)
367                 :CProxy_ArrayBase(aid,CK_DELCTOR_ARGS), _idx(idx) { }
368         CProxyElement_ArrayBase(const CkArrayID &aid, const CkArrayIndex &idx)
369                 :CProxy_ArrayBase(aid), _idx(idx) { }
370         CProxyElement_ArrayBase(const ArrayElement *e);
371
372         void ckInsert(CkArrayMessage *m,int ctor,int onPe);
373         void ckSend(CkArrayMessage *m, int ep, int opts = 0) const;
374 //      static void ckSendWrapper(void *me, void *m, int ep, int opts = 0);
375       static void ckSendWrapper(CkArrayID _aid, CkArrayIndex _idx, void *m, int ep, int opts);
376         void *ckSendSync(CkArrayMessage *m, int ep) const;
377         const CkArrayIndex &ckGetIndex() const {return _idx;}
378
379         ArrayElement *ckLocal(void) const;
380         void pup(PUP::er &p);
381 };
382 PUPmarshall(CProxyElement_ArrayBase)
383
384 class CProxySection_ArrayBase:public CProxy_ArrayBase {
385 private:
386         int _nsid;
387         CkSectionID *_sid;
388 public:
389         CProxySection_ArrayBase(): _nsid(0), _sid(NULL) {}
390         CProxySection_ArrayBase(const CkArrayID &aid,
391                 const CkArrayIndex *elems, const int nElems)
392                 :CProxy_ArrayBase(aid), _nsid(1) { _sid = new CkSectionID(aid, elems, nElems); }
393         CProxySection_ArrayBase(const CkArrayID &aid,
394                 const CkArrayIndex *elems, const int nElems, CK_DELCTOR_PARAM)
395                 :CProxy_ArrayBase(aid,CK_DELCTOR_ARGS), _nsid(1) { _sid = new CkSectionID(aid, elems, nElems); }
396         CProxySection_ArrayBase(const CkSectionID &sid)
397                 :CProxy_ArrayBase(sid._cookie.get_aid()), _nsid(1) { _sid = new CkSectionID(sid); }
398         CProxySection_ArrayBase(const CkSectionID &sid, CK_DELCTOR_PARAM)
399                 :CProxy_ArrayBase(sid._cookie.get_aid(), CK_DELCTOR_ARGS), _nsid(1) { _sid = new CkSectionID(sid); }
400         CProxySection_ArrayBase(const CProxySection_ArrayBase &cs)
401                 :CProxy_ArrayBase(cs.ckGetArrayID()), _nsid(cs._nsid) {
402       if (_nsid == 1) _sid = new CkSectionID(cs.ckGetArrayID(), cs.ckGetArrayElements(), cs.ckGetNumElements());
403       else if (_nsid > 1) {
404         _sid = new CkSectionID[_nsid];
405         for (int i=0; i<_nsid; ++i) _sid[i] = cs._sid[i];
406       } else _sid = NULL;
407     }
408         CProxySection_ArrayBase(const CProxySection_ArrayBase &cs, CK_DELCTOR_PARAM)
409                 :CProxy_ArrayBase(cs.ckGetArrayID(),CK_DELCTOR_ARGS), _nsid(cs._nsid) {
410       if (_nsid == 1) _sid = new CkSectionID(cs.ckGetArrayID(), cs.ckGetArrayElements(), cs.ckGetNumElements());
411       else if (_nsid > 1) {
412         _sid = new CkSectionID[_nsid];
413         for (int i=0; i<_nsid; ++i) _sid[i] = cs._sid[i];
414       } else _sid = NULL;
415     }
416     CProxySection_ArrayBase(const int n, const CkArrayID *aid, CkArrayIndex const * const *elems, const int *nElems)
417         :CProxy_ArrayBase(aid[0]), _nsid(n) {
418       if (_nsid == 1) _sid = new CkSectionID(aid[0], elems[0], nElems[0]);
419       else if (_nsid > 1) {
420       _sid = new CkSectionID[n];
421       for (int i=0; i<n; ++i) _sid[i] = CkSectionID(aid[i], elems[i], nElems[i]);
422       } else _sid = NULL;
423     }
424     CProxySection_ArrayBase(const int n, const CkArrayID *aid, CkArrayIndex const * const *elems, const int *nElems,CK_DELCTOR_PARAM)
425         :CProxy_ArrayBase(aid[0],CK_DELCTOR_ARGS), _nsid(n) {
426       if (_nsid == 1) _sid = new CkSectionID(aid[0], elems[0], nElems[0]);
427       else if (_nsid > 1) {
428       _sid = new CkSectionID[n];
429       for (int i=0; i<n; ++i) _sid[i] = CkSectionID(aid[i], elems[i], nElems[i]);
430       } else _sid = NULL;
431     }
432
433     ~CProxySection_ArrayBase() {
434       if (_nsid == 1) delete _sid;
435       else if (_nsid > 1) delete[] _sid;
436     }
437
438     CProxySection_ArrayBase &operator=(const CProxySection_ArrayBase &cs) {
439       CProxy_ArrayBase::operator=(cs);
440       _nsid = cs._nsid;
441       if (_nsid == 1) _sid = new CkSectionID(*cs._sid);
442       else if (_nsid > 1) {
443         _sid = new CkSectionID[_nsid];
444         for (int i=0; i<_nsid; ++i) _sid[i] = cs._sid[i];
445       } else _sid = NULL;
446       return *this;
447     }
448     
449         void ckSectionDelegate(CkDelegateMgr *d) 
450                 { ckDelegate(d); d->initDelegateMgr(this); }
451 //      void ckInsert(CkArrayMessage *m,int ctor,int onPe);
452         void ckSend(CkArrayMessage *m, int ep, int opts = 0) ;
453
454 //      ArrayElement *ckLocal(void) const;
455     inline int ckGetNumSubSections() const { return _nsid; }
456         inline CkSectionInfo &ckGetSectionInfo() {return _sid->_cookie;}
457         inline CkSectionID *ckGetSectionIDs() {return _sid;}
458         inline CkSectionID &ckGetSectionID() {return _sid[0];}
459         inline CkSectionID &ckGetSectionID(int i) {return _sid[i];}
460         inline CkArrayID ckGetArrayIDn(int i) const {return _sid[i]._cookie.get_aid();}
461     inline CkArrayIndex *ckGetArrayElements() const {return _sid[0]._elems;}
462     inline CkArrayIndex *ckGetArrayElements(int i) const {return _sid[i]._elems;}
463     inline int ckGetNumElements() const { return _sid[0]._nElems; }
464         inline int ckGetNumElements(int i) const { return _sid[i]._nElems; }
465         void pup(PUP::er &p);
466 };
467 PUPmarshall(CProxySection_ArrayBase)
468
469 //Simple C-like API:
470 void CkSendMsgArray(int entryIndex, void *msg, CkArrayID aID, const CkArrayIndex &idx, int opts=0);
471 void CkSendMsgArrayInline(int entryIndex, void *msg, CkArrayID aID, const CkArrayIndex &idx, int opts=0);
472 void CkBroadcastMsgArray(int entryIndex, void *msg, CkArrayID aID, int opts=0);
473 void CkBroadcastMsgSection(int entryIndex, void *msg, CkSectionID sID, int opts=    0);
474 /************************ Array Element *********************/
475 /**
476  *An array element is a chare that lives inside the array.
477  *Unlike regular chares, array elements can migrate from one
478  *Pe to another.  Each element has a unique index.
479  */
480
481 class ArrayElement : public CkMigratable
482 {
483   friend class CkArray;
484   friend class CkArrayListener;
485   int numInitialElements; // Number of elements created by ckNew(numElements)
486   void initBasics(void);
487 #ifdef _PIPELINED_ALLREDUCE_
488 AllreduceMgr * allredMgr; // for allreduce
489 #endif
490 public:
491   ArrayElement(void);
492   ArrayElement(CkMigrateMessage *m);
493   virtual ~ArrayElement();
494
495 /// Pack/unpack routine (called before and after migration)
496   virtual void pup(PUP::er &p);
497
498 //Overridden functions:
499   /// Called by the system just before and after migration to another processor:
500   virtual void ckAboutToMigrate(void);
501   virtual void ckJustMigrated(void);
502   
503   virtual void ckJustRestored(void);
504   
505   virtual void ckDestroy(void);
506   virtual char *ckDebugChareName(void);
507   virtual int ckDebugChareID(char*, int);
508
509   /// Synonym for ckMigrate
510   inline void migrateMe(int toPe) {ckMigrate(toPe);}
511
512 #ifdef _PIPELINED_ALLREDUCE_
513         void contribute2(CkArrayIndex myIndex, int dataSize,const void *data,CkReduction::reducerType type,
514                            const CkCallback &cb,CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1);
515         void contribute2(int dataSize,const void *data,CkReduction::reducerType type, 
516                                         CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1); 
517         void contribute2(int dataSize,const void *data,CkReduction::reducerType type, 
518                                         const CkCallback &cb,CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1); 
519         void contribute2(CkReductionMsg *msg); 
520         void contribute2(const CkCallback &cb,CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1);
521         void contribute2(CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1);
522 #else
523   CK_REDUCTION_CONTRIBUTE_METHODS_DECL
524 #endif
525         // for _PIPELINED_ALLREDUCE_, assembler entry method
526         inline void defrag(CkReductionMsg* msg);
527   inline const CkArrayID &ckGetArrayID(void) const {return thisArrayID;}
528
529   inline int ckGetArraySize(void) const { return numInitialElements; }
530 protected:
531   CkArray *thisArray;//My source array
532   CkArrayID thisArrayID;//My source array's ID
533
534   //More verbose form of abort
535   virtual void CkAbort(const char *str) const;
536
537 private:
538 //Array implementation methods:
539 #ifndef CK_ARRAYLISTENER_MAXLEN
540 # define CK_ARRAYLISTENER_MAXLEN 3
541 #endif
542   int listenerData[CK_ARRAYLISTENER_MAXLEN];
543
544 #if CMK_MEM_CHECKPOINT
545 friend class CkMemCheckPT;
546 protected:
547   int budPEs[2];
548 private:
549   void init_checkpt();
550 #endif
551 public:
552         void inmem_checkpoint(CkArrayCheckPTReqMessage *m);
553         void recvBroadcast(CkMessage *);
554
555 #if CMK_GRID_QUEUE_AVAILABLE
556 public:
557   int grid_queue_interval;
558   int grid_queue_threshold;
559   int msg_count;
560   int msg_count_grid;
561   int border_flag;
562 #endif
563 };
564 inline int *CkArrayListener::ckGetData(ArrayElement *el) const
565   {return &el->listenerData[dataOffset];}
566
567 /**An ArrayElementT is a utility class where you are
568  * constrained to a "thisIndex" of some fixed-sized type T.
569  */
570 template <class T>
571 class ArrayElementT : public ArrayElement
572 {
573 public:
574   ArrayElementT(void): thisIndex(*(const T *)thisIndexMax.data()) {
575 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))     
576         mlogData->objID.data.array.idx=thisIndexMax;
577 #endif
578 }
579 #ifdef _PIPELINED_ALLREDUCE_
580         void contribute(int dataSize,const void *data,CkReduction::reducerType type,
581                                                 CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1)
582         {
583                 contribute2( dataSize,data, type, userFlag);
584
585         }
586         void contribute(int dataSize,const void *data,CkReduction::reducerType type,
587                                                 const CkCallback &cb,CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1)
588         {
589                 contribute2((CkArrayIndex)(thisIndex) ,dataSize, data, type,   cb, userFlag);
590         }
591         void contribute(CkReductionMsg *msg) 
592         {
593                 contribute2(msg);
594         }
595         void contribute(const CkCallback &cb,CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1)
596         {
597                 contribute2(cb ,userFlag);
598         }
599         void contribute(CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1)
600         {
601                 contribute2(userFlag);
602         }
603 #endif
604   ArrayElementT(CkMigrateMessage *msg)
605         :ArrayElement(msg),
606         thisIndex(*(const T *)thisIndexMax.data()) {}
607
608   const T thisIndex;/// Object array index
609 };
610
611 typedef ArrayElementT<CkIndex1D> ArrayElement1D;
612 typedef ArrayElementT<CkIndex2D> ArrayElement2D;
613 typedef ArrayElementT<CkIndex3D> ArrayElement3D;
614 typedef ArrayElementT<CkIndex4D> ArrayElement4D;
615 typedef ArrayElementT<CkIndex5D> ArrayElement5D;
616 typedef ArrayElementT<CkIndex6D> ArrayElement6D;
617 typedef ArrayElementT<CkIndexMax> ArrayElementMax;
618
619 /*@}*/
620
621
622 /*********************** Array Manager BOC *******************/
623 /**
624 \addtogroup CkArrayImpl
625 */
626 /*@{*/
627
628 #include "CkArray.decl.h"
629 #include "CkArrayReductionMgr.decl.h"
630
631 class CkArrayBroadcaster;
632 class CkArrayReducer;
633
634 void _ckArrayInit(void);
635
636 //#include "ComlibArrayListener.h"  FILE DELETED!
637
638 class CkArray : public CkReductionMgr, public CkArrMgr {
639   friend class ArrayElement;
640   friend class CProxy_ArrayBase;
641   friend class CProxyElement_ArrayBase;
642
643   CkMagicNumber<ArrayElement> magic; //To detect heap corruption
644   CkLocMgr *locMgr;
645   CkGroupID locMgrID;
646   CProxy_CkArray thisProxy;
647   typedef CkMigratableListT<ArrayElement> ArrayElementList;
648   ArrayElementList *elements;
649 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
650     int *children;
651     int numChildren;
652 #endif
653 private:
654   bool stableLocations;
655
656 public:
657 //Array Creation:
658   CkArray(CkArrayOptions &c,CkMarshalledMessage &initMsg,CkNodeGroupID nodereductionProxy);
659   CkArray(CkMigrateMessage *m);
660   CkGroupID &getGroupID(void) {return thisgroup;}
661
662 //Access & information routines
663   inline CkLocMgr *getLocMgr(void) {return locMgr;}
664   inline const CkArrayIndex &getNumInitial(void) const {return numInitial;}
665   inline int homePe(const CkArrayIndex &idx) const {return locMgr->homePe(idx);}
666   inline int procNum(const CkArrayIndex &idx) const {return locMgr->procNum(idx);}
667
668   /// Return the last known processor for this array index.
669   /// Valid for any possible array index.
670   inline int lastKnown(const CkArrayIndex &idx) const
671           {return locMgr->lastKnown(idx);}
672   /// Deliver message to this element (directly if local)
673   /// doFree if is local
674   inline int deliver(CkMessage *m,CkDeliver_t type,int opts=0)
675           {return locMgr->deliver(m,type,opts);}
676   /// Fetch a local element via its index (return NULL if not local)
677   inline ArrayElement *lookup(const CkArrayIndex &index)
678           {return (ArrayElement *)locMgr->lookup(index,thisgroup);}
679
680 //Creation:
681   /// Create-after-migrate:
682   virtual CkMigratable *allocateMigrated(int elChareType,const CkArrayIndex &idx,
683                         CkElementCreation_t type);
684
685   /// Prepare creation message:
686   void prepareCtorMsg(CkMessage *m,int &onPe,const CkArrayIndex &idx);
687
688   /// Create initial array elements:
689   virtual void insertInitial(const CkArrayIndex &idx,void *ctorMsg,int local=1);
690   virtual void doneInserting(void);
691   void remoteDoneInserting(void);
692
693   /// Create manually:
694   virtual CmiBool insertElement(CkMessage *);
695
696 /// Demand-creation:
697   CmiBool demandCreateElement(const CkArrayIndex &idx,
698         int onPe,int ctor,CkDeliver_t type);
699
700 /// Broadcast communication:
701   void sendBroadcast(CkMessage *msg);
702   void recvBroadcast(CkMessage *msg);
703   void sendExpeditedBroadcast(CkMessage *msg);
704   void recvExpeditedBroadcast(CkMessage *msg) { recvBroadcast(msg); }
705   void recvBroadcastViaTree(CkMessage *msg);
706
707   void pup(PUP::er &p);
708   void ckJustMigrated(void){ doneInserting(); }
709
710   // COMLIB HACK
711   // Ok, this has gone very far... getting rid of it!
712   //ComlibArrayListener * calistener;
713   //ComlibArrayListener * getComlibArrayListener() {return calistener;}
714
715   virtual CmiBool isArrMgr(void) {return CmiTrue;}
716
717 private:
718   CkArrayIndex numInitial;/// Number of initial array elements
719   CmiBool isInserting;/// Are we currently inserting elements?
720
721 /// Allocate space for a new array element
722   ArrayElement *allocate(int elChareType,const CkArrayIndex &idx,
723         CkMessage *msg,CmiBool fromMigration);
724
725 //Spring cleaning
726   void springCleaning(void);
727   static void staticSpringCleaning(void *forWhom,double curWallTime);
728
729 //ArrayListeners:
730 //Iterate over the CkArrayListeners in this vector, calling "inside" each time.
731 #define CK_ARRAYLISTENER_LOOP(listVec,inside) \
732   do { \
733         int lIdx,lMax=listVec.size();\
734         for (lIdx=0;lIdx<lMax;lIdx++) { \
735                 CkArrayListener *l=listVec[lIdx];\
736                 inside;\
737         }\
738   } while(0)
739
740   CkPupAblePtrVec<CkArrayListener> listeners;
741   int listenerDataOffset;
742  public:
743   void addListener(CkArrayListener *l) {
744     l->ckRegister(this,listenerDataOffset);
745     listenerDataOffset+=l->ckGetLen();
746     listeners.push_back(l);
747     if (listenerDataOffset>CK_ARRAYLISTENER_MAXLEN)
748       CkAbort("Too much array listener data!\n"
749               "You'll have to either use fewer array listeners, or increase the compile-time\n"
750               "constant CK_ARRAYLISTENER_MAXLEN!\n");
751   }
752  private:
753
754   CkArrayReducer *reducer; //Read-only copy of default reducer
755   CkArrayBroadcaster *broadcaster; //Read-only copy of default broadcaster
756 public:
757   void flushStates() { CkReductionMgr::flushStates(0); CK_ARRAYLISTENER_LOOP(listeners, l->flushState()); }
758 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
759         // the mlogft only support 1D arrays, then returning the number of elements in the first dimension
760         virtual int numberReductionMessages(){CkAssert(CkMyPe() == 0);return numInitial.data()[0];}
761         void broadcastHomeElements(void *data,CkLocRec *rec,CkArrayIndex *index);
762         static void staticBroadcastHomeElements(CkArray *arr,void *data,CkLocRec *rec,CkArrayIndex *index);
763 #endif
764
765 };
766
767
768
769 /*@}*/
770
771 #endif