3153e4b92944ede3ddaf4461b1b860f277451355
[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 #ifdef _PIPELINED_ALLREDUCE_
477 AllreduceMgr * allredMgr; // for allreduce
478 #endif
479 public:
480   ArrayElement(void);
481   ArrayElement(CkMigrateMessage *m);
482   virtual ~ArrayElement();
483
484 /// Pack/unpack routine (called before and after migration)
485   virtual void pup(PUP::er &p);
486
487 //Overridden functions:
488   /// Called by the system just before and after migration to another processor:
489   virtual void ckAboutToMigrate(void);
490   virtual void ckJustMigrated(void);
491   
492   virtual void ckJustRestored(void);
493   
494   virtual void ckDestroy(void);
495   virtual char *ckDebugChareName(void);
496   virtual int ckDebugChareID(char*, int);
497
498   /// Synonym for ckMigrate
499   inline void migrateMe(int toPe) {ckMigrate(toPe);}
500
501 #ifdef _PIPELINED_ALLREDUCE_
502         void contribute2(CkArrayIndex myIndex, int dataSize,const void *data,CkReduction::reducerType type,
503                            const CkCallback &cb,CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1);
504         void contribute2(int dataSize,const void *data,CkReduction::reducerType type, 
505                                         CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1); 
506         void contribute2(int dataSize,const void *data,CkReduction::reducerType type, 
507                                         const CkCallback &cb,CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1); 
508         void contribute2(CkReductionMsg *msg); 
509         void contribute2(const CkCallback &cb,CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1);
510         void contribute2(CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1);
511 #else
512   CK_REDUCTION_CONTRIBUTE_METHODS_DECL
513 #endif
514         // for _PIPELINED_ALLREDUCE_, assembler entry method
515         inline void defrag(CkReductionMsg* msg);
516   inline const CkArrayID &ckGetArrayID(void) const {return thisArrayID;}
517
518   inline int ckGetArraySize(void) const { return numInitialElements; }
519 protected:
520   CkArray *thisArray;//My source array
521   CkArrayID thisArrayID;//My source array's ID
522
523   //More verbose form of abort
524   virtual void CkAbort(const char *str) const;
525
526 private:
527 //Array implementation methods:
528 #ifndef CK_ARRAYLISTENER_MAXLEN
529 # define CK_ARRAYLISTENER_MAXLEN 3
530 #endif
531   int listenerData[CK_ARRAYLISTENER_MAXLEN];
532
533 #if CMK_MEM_CHECKPOINT
534 friend class CkMemCheckPT;
535 protected:
536   int budPEs[2];
537 private:
538   void init_checkpt();
539 #endif
540 public:
541         void inmem_checkpoint(CkArrayCheckPTReqMessage *m);
542         void recvBroadcast(CkMessage *);
543
544 #if CMK_GRID_QUEUE_AVAILABLE
545 public:
546   int grid_queue_interval;
547   int grid_queue_threshold;
548   int msg_count;
549   int msg_count_grid;
550   int border_flag;
551 #endif
552 };
553 inline int *CkArrayListener::ckGetData(ArrayElement *el) const
554   {return &el->listenerData[dataOffset];}
555
556 /**An ArrayElementT is a utility class where you are
557  * constrained to a "thisIndex" of some fixed-sized type T.
558  */
559 template <class T>
560 class ArrayElementT : public ArrayElement
561 {
562 public:
563   ArrayElementT(void): thisIndex(*(const T *)thisIndexMax.data()) {
564 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))     
565         mlogData->objID.data.array.idx=thisIndexMax;
566 #endif
567 }
568 #ifdef _PIPELINED_ALLREDUCE_
569         void contribute(int dataSize,const void *data,CkReduction::reducerType type,
570                                                 CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1)
571         {
572                 contribute2( dataSize,data, type, userFlag);
573
574         }
575         void contribute(int dataSize,const void *data,CkReduction::reducerType type,
576                                                 const CkCallback &cb,CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1)
577         {
578                 contribute2((CkArrayIndex)(thisIndex) ,dataSize, data, type,   cb, userFlag);
579         }
580         void contribute(CkReductionMsg *msg) 
581         {
582                 contribute2(msg);
583         }
584         void contribute(const CkCallback &cb,CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1)
585         {
586                 contribute2(cb ,userFlag);
587         }
588         void contribute(CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1)
589         {
590                 contribute2(userFlag);
591         }
592 #endif
593   ArrayElementT(CkMigrateMessage *msg)
594         :ArrayElement(msg),
595         thisIndex(*(const T *)thisIndexMax.data()) {}
596
597   const T thisIndex;/// Object array index
598 };
599
600 typedef ArrayElementT<CkIndex1D> ArrayElement1D;
601 typedef ArrayElementT<CkIndex2D> ArrayElement2D;
602 typedef ArrayElementT<CkIndex3D> ArrayElement3D;
603 typedef ArrayElementT<CkIndex4D> ArrayElement4D;
604 typedef ArrayElementT<CkIndex5D> ArrayElement5D;
605 typedef ArrayElementT<CkIndex6D> ArrayElement6D;
606 typedef ArrayElementT<CkIndexMax> ArrayElementMax;
607
608 /*@}*/
609
610
611 /*********************** Array Manager BOC *******************/
612 /**
613 \addtogroup CkArrayImpl
614 */
615 /*@{*/
616
617 #include "CkArray.decl.h"
618 #include "CkArrayReductionMgr.decl.h"
619
620 class CkArrayBroadcaster;
621 class CkArrayReducer;
622
623 void _ckArrayInit(void);
624
625 //#include "ComlibArrayListener.h"  FILE DELETED!
626
627 class CkArray : public CkReductionMgr, public CkArrMgr {
628   friend class ArrayElement;
629   friend class CProxy_ArrayBase;
630   friend class CProxyElement_ArrayBase;
631
632   CkMagicNumber<ArrayElement> magic; //To detect heap corruption
633   CkLocMgr *locMgr;
634   CkGroupID locMgrID;
635   CProxy_CkArray thisProxy;
636   typedef CkMigratableListT<ArrayElement> ArrayElementList;
637   ArrayElementList *elements;
638   bool stableLocations;
639
640 public:
641 //Array Creation:
642   CkArray(CkArrayOptions &c,CkMarshalledMessage &initMsg,CkNodeGroupID nodereductionProxy);
643   CkArray(CkMigrateMessage *m);
644   CkGroupID &getGroupID(void) {return thisgroup;}
645
646 //Access & information routines
647   inline CkLocMgr *getLocMgr(void) {return locMgr;}
648   inline const CkArrayIndex &getNumInitial(void) const {return numInitial;}
649   inline int homePe(const CkArrayIndex &idx) const {return locMgr->homePe(idx);}
650   inline int procNum(const CkArrayIndex &idx) const {return locMgr->procNum(idx);}
651
652   /// Return the last known processor for this array index.
653   /// Valid for any possible array index.
654   inline int lastKnown(const CkArrayIndex &idx) const
655           {return locMgr->lastKnown(idx);}
656   /// Deliver message to this element (directly if local)
657   /// doFree if is local
658   inline int deliver(CkMessage *m,CkDeliver_t type,int opts=0)
659           {return locMgr->deliver(m,type,opts);}
660   /// Fetch a local element via its index (return NULL if not local)
661   inline ArrayElement *lookup(const CkArrayIndex &index)
662           {return (ArrayElement *)locMgr->lookup(index,thisgroup);}
663
664 //Creation:
665   /// Create-after-migrate:
666   virtual CkMigratable *allocateMigrated(int elChareType,const CkArrayIndex &idx,
667                         CkElementCreation_t type);
668
669   /// Prepare creation message:
670   void prepareCtorMsg(CkMessage *m,int &onPe,const CkArrayIndex &idx);
671
672   /// Create initial array elements:
673   virtual void insertInitial(const CkArrayIndex &idx,void *ctorMsg,int local=1);
674   virtual void doneInserting(void);
675   void remoteDoneInserting(void);
676
677   /// Create manually:
678   virtual CmiBool insertElement(CkMessage *);
679
680 /// Demand-creation:
681   CmiBool demandCreateElement(const CkArrayIndex &idx,
682         int onPe,int ctor,CkDeliver_t type);
683
684 /// Broadcast communication:
685   void sendBroadcast(CkMessage *msg);
686   void recvBroadcast(CkMessage *msg);
687   void sendExpeditedBroadcast(CkMessage *msg);
688   void recvExpeditedBroadcast(CkMessage *msg) { recvBroadcast(msg); }
689
690   void pup(PUP::er &p);
691   void ckJustMigrated(void){ doneInserting(); }
692
693   // COMLIB HACK
694   // Ok, this has gone very far... getting rid of it!
695   //ComlibArrayListener * calistener;
696   //ComlibArrayListener * getComlibArrayListener() {return calistener;}
697
698   virtual CmiBool isArrMgr(void) {return CmiTrue;}
699
700 private:
701   CkArrayIndex numInitial;/// Number of initial array elements
702   CmiBool isInserting;/// Are we currently inserting elements?
703
704 /// Allocate space for a new array element
705   ArrayElement *allocate(int elChareType,const CkArrayIndex &idx,
706         CkMessage *msg,CmiBool fromMigration);
707
708 //Spring cleaning
709   void springCleaning(void);
710   static void staticSpringCleaning(void *forWhom,double curWallTime);
711
712 //ArrayListeners:
713 //Iterate over the CkArrayListeners in this vector, calling "inside" each time.
714 #define CK_ARRAYLISTENER_LOOP(listVec,inside) \
715   do { \
716         int lIdx,lMax=listVec.size();\
717         for (lIdx=0;lIdx<lMax;lIdx++) { \
718                 CkArrayListener *l=listVec[lIdx];\
719                 inside;\
720         }\
721   } while(0)
722
723   CkPupAblePtrVec<CkArrayListener> listeners;
724   int listenerDataOffset;
725  public:
726   void addListener(CkArrayListener *l) {
727     l->ckRegister(this,listenerDataOffset);
728     listenerDataOffset+=l->ckGetLen();
729     listeners.push_back(l);
730     if (listenerDataOffset>CK_ARRAYLISTENER_MAXLEN)
731       CkAbort("Too much array listener data!\n"
732               "You'll have to either use fewer array listeners, or increase the compile-time\n"
733               "constant CK_ARRAYLISTENER_MAXLEN!\n");
734   }
735  private:
736
737   CkArrayReducer *reducer; //Read-only copy of default reducer
738   CkArrayBroadcaster *broadcaster; //Read-only copy of default broadcaster
739 public:
740   void flushStates() { CkReductionMgr::flushStates(); CK_ARRAYLISTENER_LOOP(listeners, l->flushState()); }
741 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
742         // the mlogft only support 1D arrays, then returning the number of elements in the first dimension
743         virtual int numberReductionMessages(){CkAssert(CkMyPe() == 0);return numInitial.data()[0];}
744         void broadcastHomeElements(void *data,CkLocRec *rec,CkArrayIndex *index);
745         static void staticBroadcastHomeElements(CkArray *arr,void *data,CkLocRec *rec,CkArrayIndex *index);
746 #endif
747
748 };
749
750
751
752 /*@}*/
753
754 #endif