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