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