7ff7656d1fa7f667a2285ba9ee6061b75571cc6f
[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         bool broadcastViaScheduler;     // broadcast inline or through scheduler
222
223         /// Set various safe defaults for all the constructors
224         void init();
225
226  public:
227  //Used by external world:
228         CkArrayOptions(void); ///< Default: empty array
229         CkArrayOptions(int ni1_); ///< With initial elements 1D
230         CkArrayOptions(int ni1_, int ni2_); ///< With initial elements 2D 
231         CkArrayOptions(int ni1_, int ni2_, int ni3); ///< With initial elements 3D
232         //CkArrayOptions(short ni1_, short ni2_, short ni3, short ni4_); ///< With initial elements 4D
233         //CkArrayOptions(short ni1_, short ni2_, short ni3, short ni4_, short ni5_); ///< With initial elements 5D
234         //CkArrayOptions(short ni1_, short ni2_, short ni3, short ni4_, short ni5_, short ni6_); ///< With initial elements 6D
235
236         /**
237          * These functions return "this" so you can string them together, e.g.:
238          *   foo(CkArrayOptions().setMap(mid).bindTo(aid));
239          */
240
241         /// Create this many initial elements 1D
242         CkArrayOptions &setNumInitial(int ni)
243                 {numInitial=CkArrayIndex1D(ni); return *this;}
244         /// Create this many initial elements 2D
245         CkArrayOptions &setNumInitial(int ni1, int ni2)
246                 {numInitial=CkArrayIndex2D(ni1, ni2); return *this;}
247         /// Create this many initial elements 3D
248         CkArrayOptions &setNumInitial(int ni1, int ni2, int ni3)
249                 {numInitial=CkArrayIndex3D(ni1 ,ni2, ni3); return *this;}
250         /*
251         /// Create this many initial elements 4D
252         CkArrayOptions &setNumInitial(short ni1, short ni2, short ni3, short ni4)
253                 {numInitial=CkArrayIndex4D(ni1, ni2, ni3, ni4); return *this;}
254         /// Create this many initial elements 5D
255         CkArrayOptions &setNumInitial(short ni1, short ni2, short ni3, short ni4, short ni5)
256                 {numInitial=CkArrayIndex5D(ni1, ni2, ni3, ni4, ni5); return *this;}
257         /// Create this many initial elements 6D
258         CkArrayOptions &setNumInitial(short ni1, short ni2, short ni3, short ni4, short ni5, short ni6)
259                 {numInitial=CkArrayIndex6D(ni1, ni2, ni3, ni4, ni5, ni6); return *this;}
260         */
261
262         /// Use this location map
263         CkArrayOptions &setMap(const CkGroupID &m)
264                 {map=m; return *this;}
265
266         /// Bind our elements to this array
267         CkArrayOptions &bindTo(const CkArrayID &b);
268
269         /// Use this location manager
270         CkArrayOptions &setLocationManager(const CkGroupID &l)
271                 {locMgr=l; return *this;}
272
273         /// Add an array listener component to this array (keeps the new'd listener)
274         CkArrayOptions &addListener(CkArrayListener *listener);
275
276         CkArrayOptions &setAnytimeMigration(bool b) { anytimeMigration = b; return *this; }
277         CkArrayOptions &setStaticInsertion(bool b);
278         CkArrayOptions &setBroadcastViaScheduler(bool b) { broadcastViaScheduler = b; return *this; }
279         CkArrayOptions &setReductionClient(CkCallback cb)
280         { reductionClient = cb; return *this; }
281
282   //Used by the array manager:
283         const CkArrayIndex &getNumInitial(void) const {return numInitial;}
284         const CkGroupID &getMap(void) const {return map;}
285         const CkGroupID &getLocationManager(void) const {return locMgr;}
286         int getListeners(void) const {return arrayListeners.size();}
287         CkArrayListener *getListener(int listenerNum) {
288                 CkArrayListener *ret=arrayListeners[listenerNum];
289                 arrayListeners[listenerNum]=NULL; //Don't throw away this listener
290                 return ret;
291         }
292
293         void pup(PUP::er &p);
294 };
295 PUPmarshall(CkArrayOptions)
296
297
298 /*********************** Proxy Support ************************/
299 //Needed by CBase_ArrayElement
300 class ArrayBase { /*empty*/ };
301 /*forward*/ class ArrayElement;
302
303 /**
304  * This class is a wrapper around a CkArrayIndex and ArrayID,
305  *  used by array element proxies.  This makes the translator's
306  *  job simpler, and the translated code smaller.
307  */
308 class CProxy_ArrayBase :public CProxy {
309 private:
310         CkArrayID _aid;
311 public:
312         CProxy_ArrayBase() {
313 #if CMK_ERROR_CHECKING
314                 _aid.setZero();
315 #endif
316         }
317         CProxy_ArrayBase(const CkArrayID &aid,CK_DELCTOR_PARAM)
318                 :CProxy(CK_DELCTOR_ARGS), _aid(aid) { }
319         CProxy_ArrayBase(const CkArrayID &aid)
320                 :CProxy(), _aid(aid) { }
321         CProxy_ArrayBase(const ArrayElement *e);
322
323 #if CMK_ERROR_CHECKING
324         inline void ckCheck(void) const{  //Make sure this proxy has a value
325           if (_aid.isZero())
326                 CkAbort("Error! This array proxy has not been initialized!");
327         }
328 #else
329         inline void ckCheck(void) const {}
330 #endif
331
332         static CkArrayID ckCreateEmptyArray(void);
333         static CkArrayID ckCreateArray(CkArrayMessage *m,int ctor,const CkArrayOptions &opts);
334
335         void ckInsertIdx(CkArrayMessage *m,int ctor,int onPe,const CkArrayIndex &idx);
336         void ckBroadcast(CkArrayMessage *m, int ep, int opts=0) const;
337         CkArrayID ckGetArrayID(void) const { return _aid; }
338         CkArray *ckLocalBranch(void) const { return _aid.ckLocalBranch(); }
339         CkLocMgr *ckLocMgr(void) const;
340         inline operator CkArrayID () const {return ckGetArrayID();}
341         unsigned int numLocalElements() const { return ckLocMgr()->numLocalElements(); }
342
343         void doneInserting(void);
344
345         CK_REDUCTION_CLIENT_DECL
346
347         void pup(PUP::er &p);
348 };
349 PUPmarshall(CProxy_ArrayBase)
350
351 class CProxyElement_ArrayBase:public CProxy_ArrayBase {
352 private:
353         CkArrayIndex _idx;//<- our element's array index
354 public:
355         CProxyElement_ArrayBase() { }
356         CProxyElement_ArrayBase(const CkArrayID &aid,
357                 const CkArrayIndex &idx,CK_DELCTOR_PARAM)
358                 :CProxy_ArrayBase(aid,CK_DELCTOR_ARGS), _idx(idx) { }
359         CProxyElement_ArrayBase(const CkArrayID &aid, const CkArrayIndex &idx)
360                 :CProxy_ArrayBase(aid), _idx(idx) { }
361         CProxyElement_ArrayBase(const ArrayElement *e);
362
363         void ckInsert(CkArrayMessage *m,int ctor,int onPe);
364         void ckSend(CkArrayMessage *m, int ep, int opts = 0) const;
365 //      static void ckSendWrapper(void *me, void *m, int ep, int opts = 0);
366       static void ckSendWrapper(CkArrayID _aid, CkArrayIndex _idx, void *m, int ep, int opts);
367         void *ckSendSync(CkArrayMessage *m, int ep) const;
368         const CkArrayIndex &ckGetIndex() const {return _idx;}
369
370         ArrayElement *ckLocal(void) const;
371         void pup(PUP::er &p);
372 };
373 PUPmarshall(CProxyElement_ArrayBase)
374
375 class CProxySection_ArrayBase:public CProxy_ArrayBase {
376 private:
377         int _nsid;
378         CkSectionID *_sid;
379 public:
380         CProxySection_ArrayBase(): _nsid(0), _sid(NULL) {}
381         CProxySection_ArrayBase(const CkArrayID &aid,
382                 const CkArrayIndex *elems, const int nElems)
383                 :CProxy_ArrayBase(aid), _nsid(1) { _sid = new CkSectionID(aid, elems, nElems); }
384         CProxySection_ArrayBase(const CkArrayID &aid,
385                 const CkArrayIndex *elems, const int nElems, CK_DELCTOR_PARAM)
386                 :CProxy_ArrayBase(aid,CK_DELCTOR_ARGS), _nsid(1) { _sid = new CkSectionID(aid, elems, nElems); }
387         CProxySection_ArrayBase(const CkSectionID &sid)
388                 :CProxy_ArrayBase(sid._cookie.get_aid()), _nsid(1) { _sid = new CkSectionID(sid); }
389         CProxySection_ArrayBase(const CkSectionID &sid, CK_DELCTOR_PARAM)
390                 :CProxy_ArrayBase(sid._cookie.get_aid(), CK_DELCTOR_ARGS), _nsid(1) { _sid = new CkSectionID(sid); }
391         CProxySection_ArrayBase(const CProxySection_ArrayBase &cs)
392                 :CProxy_ArrayBase(cs.ckGetArrayID()), _nsid(cs._nsid) {
393       if (_nsid == 1) _sid = new CkSectionID(cs.ckGetArrayID(), cs.ckGetArrayElements(), cs.ckGetNumElements());
394       else if (_nsid > 1) {
395         _sid = new CkSectionID[_nsid];
396         for (int i=0; i<_nsid; ++i) _sid[i] = cs._sid[i];
397       } else _sid = NULL;
398     }
399         CProxySection_ArrayBase(const CProxySection_ArrayBase &cs, CK_DELCTOR_PARAM)
400                 :CProxy_ArrayBase(cs.ckGetArrayID(),CK_DELCTOR_ARGS), _nsid(cs._nsid) {
401       if (_nsid == 1) _sid = new CkSectionID(cs.ckGetArrayID(), cs.ckGetArrayElements(), cs.ckGetNumElements());
402       else if (_nsid > 1) {
403         _sid = new CkSectionID[_nsid];
404         for (int i=0; i<_nsid; ++i) _sid[i] = cs._sid[i];
405       } else _sid = NULL;
406     }
407     CProxySection_ArrayBase(const int n, const CkArrayID *aid, CkArrayIndex const * const *elems, const int *nElems)
408         :CProxy_ArrayBase(aid[0]), _nsid(n) {
409       if (_nsid == 1) _sid = new CkSectionID(aid[0], elems[0], nElems[0]);
410       else if (_nsid > 1) {
411       _sid = new CkSectionID[n];
412       for (int i=0; i<n; ++i) _sid[i] = CkSectionID(aid[i], elems[i], nElems[i]);
413       } else _sid = NULL;
414     }
415     CProxySection_ArrayBase(const int n, const CkArrayID *aid, CkArrayIndex const * const *elems, const int *nElems,CK_DELCTOR_PARAM)
416         :CProxy_ArrayBase(aid[0],CK_DELCTOR_ARGS), _nsid(n) {
417       if (_nsid == 1) _sid = new CkSectionID(aid[0], elems[0], nElems[0]);
418       else if (_nsid > 1) {
419       _sid = new CkSectionID[n];
420       for (int i=0; i<n; ++i) _sid[i] = CkSectionID(aid[i], elems[i], nElems[i]);
421       } else _sid = NULL;
422     }
423
424     ~CProxySection_ArrayBase() {
425       if (_nsid == 1) delete _sid;
426       else if (_nsid > 1) delete[] _sid;
427     }
428
429     CProxySection_ArrayBase &operator=(const CProxySection_ArrayBase &cs) {
430       CProxy_ArrayBase::operator=(cs);
431       _nsid = cs._nsid;
432       if (_nsid == 1) _sid = new CkSectionID(*cs._sid);
433       else if (_nsid > 1) {
434         _sid = new CkSectionID[_nsid];
435         for (int i=0; i<_nsid; ++i) _sid[i] = cs._sid[i];
436       } else _sid = NULL;
437       return *this;
438     }
439     
440         void ckSectionDelegate(CkDelegateMgr *d) 
441                 { ckDelegate(d); d->initDelegateMgr(this); }
442 //      void ckInsert(CkArrayMessage *m,int ctor,int onPe);
443         void ckSend(CkArrayMessage *m, int ep, int opts = 0) ;
444
445 //      ArrayElement *ckLocal(void) const;
446     inline int ckGetNumSubSections() const { return _nsid; }
447         inline CkSectionInfo &ckGetSectionInfo() {return _sid->_cookie;}
448         inline CkSectionID *ckGetSectionIDs() {return _sid;}
449         inline CkSectionID &ckGetSectionID() {return _sid[0];}
450         inline CkSectionID &ckGetSectionID(int i) {return _sid[i];}
451         inline CkArrayID ckGetArrayIDn(int i) const {return _sid[i]._cookie.get_aid();}
452     inline CkArrayIndex *ckGetArrayElements() const {return _sid[0]._elems;}
453     inline CkArrayIndex *ckGetArrayElements(int i) const {return _sid[i]._elems;}
454     inline int ckGetNumElements() const { return _sid[0]._nElems; }
455         inline int ckGetNumElements(int i) const { return _sid[i]._nElems; }
456         void pup(PUP::er &p);
457 };
458 PUPmarshall(CProxySection_ArrayBase)
459
460 //Simple C-like API:
461 void CkSendMsgArray(int entryIndex, void *msg, CkArrayID aID, const CkArrayIndex &idx, int opts=0);
462 void CkSendMsgArrayInline(int entryIndex, void *msg, CkArrayID aID, const CkArrayIndex &idx, int opts=0);
463 void CkBroadcastMsgArray(int entryIndex, void *msg, CkArrayID aID, int opts=0);
464 void CkBroadcastMsgSection(int entryIndex, void *msg, CkSectionID sID, int opts=    0);
465 /************************ Array Element *********************/
466 /**
467  *An array element is a chare that lives inside the array.
468  *Unlike regular chares, array elements can migrate from one
469  *Pe to another.  Each element has a unique index.
470  */
471
472 class ArrayElement : public CkMigratable
473 {
474   friend class CkArray;
475   friend class CkArrayListener;
476   int numInitialElements; // Number of elements created by ckNew(numElements)
477   void initBasics(void);
478 #ifdef _PIPELINED_ALLREDUCE_
479 AllreduceMgr * allredMgr; // for allreduce
480 #endif
481 public:
482   ArrayElement(void);
483   ArrayElement(CkMigrateMessage *m);
484   virtual ~ArrayElement();
485
486 /// Pack/unpack routine (called before and after migration)
487   virtual void pup(PUP::er &p);
488
489 //Overridden functions:
490   /// Called by the system just before and after migration to another processor:
491   virtual void ckAboutToMigrate(void);
492   virtual void ckJustMigrated(void);
493   
494   virtual void ckJustRestored(void);
495   
496   virtual void ckDestroy(void);
497   virtual char *ckDebugChareName(void);
498   virtual int ckDebugChareID(char*, int);
499
500   /// Synonym for ckMigrate
501   inline void migrateMe(int toPe) {ckMigrate(toPe);}
502
503 #ifdef _PIPELINED_ALLREDUCE_
504         void contribute2(CkArrayIndex myIndex, int dataSize,const void *data,CkReduction::reducerType type,
505                            const CkCallback &cb,CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1);
506         void contribute2(int dataSize,const void *data,CkReduction::reducerType type, 
507                                         CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1); 
508         void contribute2(int dataSize,const void *data,CkReduction::reducerType type, 
509                                         const CkCallback &cb,CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1); 
510         void contribute2(CkReductionMsg *msg); 
511         void contribute2(const CkCallback &cb,CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1);
512         void contribute2(CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1);
513 #else
514   CK_REDUCTION_CONTRIBUTE_METHODS_DECL
515 #endif
516         // for _PIPELINED_ALLREDUCE_, assembler entry method
517         inline void defrag(CkReductionMsg* msg);
518   inline const CkArrayID &ckGetArrayID(void) const {return thisArrayID;}
519
520   inline int ckGetArraySize(void) const { return numInitialElements; }
521 protected:
522   CkArray *thisArray;//My source array
523   CkArrayID thisArrayID;//My source array's ID
524
525   //More verbose form of abort
526   virtual void CkAbort(const char *str) const;
527
528 private:
529 //Array implementation methods:
530 #ifndef CK_ARRAYLISTENER_MAXLEN
531 # define CK_ARRAYLISTENER_MAXLEN 3
532 #endif
533   int listenerData[CK_ARRAYLISTENER_MAXLEN];
534
535 #if CMK_MEM_CHECKPOINT
536 friend class CkMemCheckPT;
537 protected:
538   int budPEs[2];
539 private:
540   void init_checkpt();
541 #endif
542 public:
543         void inmem_checkpoint(CkArrayCheckPTReqMessage *m);
544         void recvBroadcast(CkMessage *);
545
546 #if CMK_GRID_QUEUE_AVAILABLE
547 public:
548   int grid_queue_interval;
549   int grid_queue_threshold;
550   int msg_count;
551   int msg_count_grid;
552   int border_flag;
553 #endif
554 };
555 inline int *CkArrayListener::ckGetData(ArrayElement *el) const
556   {return &el->listenerData[dataOffset];}
557
558 /**An ArrayElementT is a utility class where you are
559  * constrained to a "thisIndex" of some fixed-sized type T.
560  */
561 template <class T>
562 class ArrayElementT : public ArrayElement
563 {
564 public:
565   ArrayElementT(void): thisIndex(*(const T *)thisIndexMax.data()) {
566 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))     
567         mlogData->objID.data.array.idx=thisIndexMax;
568 #endif
569 }
570 #ifdef _PIPELINED_ALLREDUCE_
571         void contribute(int dataSize,const void *data,CkReduction::reducerType type,
572                                                 CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1)
573         {
574                 contribute2( dataSize,data, type, userFlag);
575
576         }
577         void contribute(int dataSize,const void *data,CkReduction::reducerType type,
578                                                 const CkCallback &cb,CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1)
579         {
580                 contribute2((CkArrayIndex)(thisIndex) ,dataSize, data, type,   cb, userFlag);
581         }
582         void contribute(CkReductionMsg *msg) 
583         {
584                 contribute2(msg);
585         }
586         void contribute(const CkCallback &cb,CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1)
587         {
588                 contribute2(cb ,userFlag);
589         }
590         void contribute(CMK_REFNUM_TYPE userFlag=(CMK_REFNUM_TYPE)-1)
591         {
592                 contribute2(userFlag);
593         }
594 #endif
595   ArrayElementT(CkMigrateMessage *msg)
596         :ArrayElement(msg),
597         thisIndex(*(const T *)thisIndexMax.data()) {}
598
599   const T thisIndex;/// Object array index
600 };
601
602 typedef ArrayElementT<CkIndex1D> ArrayElement1D;
603 typedef ArrayElementT<CkIndex2D> ArrayElement2D;
604 typedef ArrayElementT<CkIndex3D> ArrayElement3D;
605 typedef ArrayElementT<CkIndex4D> ArrayElement4D;
606 typedef ArrayElementT<CkIndex5D> ArrayElement5D;
607 typedef ArrayElementT<CkIndex6D> ArrayElement6D;
608 typedef ArrayElementT<CkIndexMax> ArrayElementMax;
609
610 /*@}*/
611
612
613 /*********************** Array Manager BOC *******************/
614 /**
615 \addtogroup CkArrayImpl
616 */
617 /*@{*/
618
619 #include "CkArray.decl.h"
620 #include "CkArrayReductionMgr.decl.h"
621
622 class CkArrayBroadcaster;
623 class CkArrayReducer;
624
625 void _ckArrayInit(void);
626
627 //#include "ComlibArrayListener.h"  FILE DELETED!
628
629 class CkArray : public CkReductionMgr, public CkArrMgr {
630   friend class ArrayElement;
631   friend class CProxy_ArrayBase;
632   friend class CProxyElement_ArrayBase;
633
634   CkMagicNumber<ArrayElement> magic; //To detect heap corruption
635   CkLocMgr *locMgr;
636   CkGroupID locMgrID;
637   CProxy_CkArray thisProxy;
638   typedef CkMigratableListT<ArrayElement> ArrayElementList;
639   ArrayElementList *elements;
640 private:
641   bool stableLocations;
642
643 public:
644 //Array Creation:
645   CkArray(CkArrayOptions &c,CkMarshalledMessage &initMsg,CkNodeGroupID nodereductionProxy);
646   CkArray(CkMigrateMessage *m);
647   CkGroupID &getGroupID(void) {return thisgroup;}
648
649 //Access & information routines
650   inline CkLocMgr *getLocMgr(void) {return locMgr;}
651   inline const CkArrayIndex &getNumInitial(void) const {return numInitial;}
652   inline int homePe(const CkArrayIndex &idx) const {return locMgr->homePe(idx);}
653   inline int procNum(const CkArrayIndex &idx) const {return locMgr->procNum(idx);}
654
655   /// Return the last known processor for this array index.
656   /// Valid for any possible array index.
657   inline int lastKnown(const CkArrayIndex &idx) const
658           {return locMgr->lastKnown(idx);}
659   /// Deliver message to this element (directly if local)
660   /// doFree if is local
661   inline int deliver(CkMessage *m,CkDeliver_t type,int opts=0)
662           {return locMgr->deliver(m,type,opts);}
663   /// Fetch a local element via its index (return NULL if not local)
664   inline ArrayElement *lookup(const CkArrayIndex &index)
665           {return (ArrayElement *)locMgr->lookup(index,thisgroup);}
666
667 //Creation:
668   /// Create-after-migrate:
669   virtual CkMigratable *allocateMigrated(int elChareType,const CkArrayIndex &idx,
670                         CkElementCreation_t type);
671
672   /// Prepare creation message:
673   void prepareCtorMsg(CkMessage *m,int &onPe,const CkArrayIndex &idx);
674
675   /// Create initial array elements:
676   virtual void insertInitial(const CkArrayIndex &idx,void *ctorMsg,int local=1);
677   virtual void doneInserting(void);
678   void remoteDoneInserting(void);
679
680   /// Create manually:
681   virtual CmiBool insertElement(CkMessage *);
682
683 /// Demand-creation:
684   CmiBool demandCreateElement(const CkArrayIndex &idx,
685         int onPe,int ctor,CkDeliver_t type);
686
687 /// Broadcast communication:
688   void sendBroadcast(CkMessage *msg);
689   void recvBroadcast(CkMessage *msg);
690   void sendExpeditedBroadcast(CkMessage *msg);
691   void recvExpeditedBroadcast(CkMessage *msg) { recvBroadcast(msg); }
692
693   void pup(PUP::er &p);
694   void ckJustMigrated(void){ doneInserting(); }
695
696   // COMLIB HACK
697   // Ok, this has gone very far... getting rid of it!
698   //ComlibArrayListener * calistener;
699   //ComlibArrayListener * getComlibArrayListener() {return calistener;}
700
701   virtual CmiBool isArrMgr(void) {return CmiTrue;}
702
703 private:
704   CkArrayIndex numInitial;/// Number of initial array elements
705   CmiBool isInserting;/// Are we currently inserting elements?
706
707 /// Allocate space for a new array element
708   ArrayElement *allocate(int elChareType,const CkArrayIndex &idx,
709         CkMessage *msg,CmiBool fromMigration);
710
711 //Spring cleaning
712   void springCleaning(void);
713   static void staticSpringCleaning(void *forWhom,double curWallTime);
714
715 //ArrayListeners:
716 //Iterate over the CkArrayListeners in this vector, calling "inside" each time.
717 #define CK_ARRAYLISTENER_LOOP(listVec,inside) \
718   do { \
719         int lIdx,lMax=listVec.size();\
720         for (lIdx=0;lIdx<lMax;lIdx++) { \
721                 CkArrayListener *l=listVec[lIdx];\
722                 inside;\
723         }\
724   } while(0)
725
726   CkPupAblePtrVec<CkArrayListener> listeners;
727   int listenerDataOffset;
728  public:
729   void addListener(CkArrayListener *l) {
730     l->ckRegister(this,listenerDataOffset);
731     listenerDataOffset+=l->ckGetLen();
732     listeners.push_back(l);
733     if (listenerDataOffset>CK_ARRAYLISTENER_MAXLEN)
734       CkAbort("Too much array listener data!\n"
735               "You'll have to either use fewer array listeners, or increase the compile-time\n"
736               "constant CK_ARRAYLISTENER_MAXLEN!\n");
737   }
738  private:
739
740   CkArrayReducer *reducer; //Read-only copy of default reducer
741   CkArrayBroadcaster *broadcaster; //Read-only copy of default broadcaster
742 public:
743   void flushStates() { CkReductionMgr::flushStates(0); CK_ARRAYLISTENER_LOOP(listeners, l->flushState()); }
744 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
745         // the mlogft only support 1D arrays, then returning the number of elements in the first dimension
746         virtual int numberReductionMessages(){CkAssert(CkMyPe() == 0);return numInitial.data()[0];}
747         void broadcastHomeElements(void *data,CkLocRec *rec,CkArrayIndex *index);
748         static void staticBroadcastHomeElements(CkArray *arr,void *data,CkLocRec *rec,CkArrayIndex *index);
749 #endif
750
751 };
752
753
754
755 /*@}*/
756
757 #endif