0a6d065aeb81e93559c882837ef475ff0773e050
[charm.git] / src / ck-core / cklocation.h
1 /*
2 Location manager: keeps track of an indexed set of migratable
3 objects.  Used by the array manager to locate array elements,
4 interact with the load balancer, and perform migrations.
5
6 Does not handle reductions (see ckreduction.h), broadcasts,
7 array proxies, or the details of element creation (see ckarray.h).
8 */
9 #ifndef __CKLOCATION_H
10 #define __CKLOCATION_H
11
12 /*********************** Array Messages ************************/
13 class CkArrayMessage : public CkMessage {
14 public:
15   //These routines are implementation utilities
16   inline CkArrayIndexMax &array_index(void);
17   unsigned short &array_ep(void);
18   unsigned short &array_ep_bcast(void);
19   unsigned char &array_hops(void);
20   unsigned int array_getSrcPe(void);
21   unsigned int array_ifNotThere(void);
22   void array_setIfNotThere(unsigned int);
23   
24   //This allows us to delete bare CkArrayMessages
25   void operator delete(void *p){CkFreeMsg(p);}
26 };
27
28 /* Utility */
29 //#if CMK_LBDB_ON
30 #include "LBDatabase.h"
31 class LBDatabase;
32 //#endif
33
34 //Forward declarations
35 class CkArray;
36 class ArrayElement;
37 //What to do if an entry method is invoked on
38 // an array element that does not (yet) exist:
39 typedef enum {
40         CkArray_IfNotThere_buffer=0, //Wait for it to be created
41         CkArray_IfNotThere_createhere=1, //Make it on sending Pe
42         CkArray_IfNotThere_createhome=2 //Make it on (a) home Pe
43 } CkArray_IfNotThere;
44
45 /// How to do a message delivery:
46 typedef enum {
47         CkDeliver_queue=0, //Deliver via the scheduler's queue
48         CkDeliver_inline=1  //Deliver via a regular call
49 } CkDeliver_t;
50
51 #include "CkLocation.decl.h"
52
53 /************************** Array Messages ****************************/
54 /**
55  *  This is the message type used to actually send a migrating array element.
56  */
57
58 class CkArrayElementMigrateMessage : public CMessage_CkArrayElementMigrateMessage {
59 public:
60         CkArrayIndexMax idx; // Array index that is migrating
61         int ignoreArrival;   // if to inform LB of arrival
62         int length;//Size in bytes of the packed data
63         CmiBool bounced;
64         double* packData;
65 };
66
67 /******************* Map object ******************/
68
69 extern CkGroupID _RRMapID;
70 class CkLocMgr;
71 class CkArrMgr;
72
73 /**
74 \addtogroup CkArray
75 */
76 /*@{*/
77
78 /** The "map" is used by the array manager to map an array index to 
79  * a home processor number.
80  */
81 class CkArrayMap : public IrrGroup // : public CkGroupReadyCallback
82 {
83 public:
84   CkArrayMap(void);
85   CkArrayMap(CkMigrateMessage *m): IrrGroup(m) {}
86   virtual ~CkArrayMap();
87   virtual int registerArray(int numElements,CkArrayID aid);
88   virtual void populateInitial(int arrayHdl,int numElements,void *ctorMsg,CkArrMgr *mgr);
89   virtual int procNum(int arrayHdl,const CkArrayIndex &element) =0;
90   virtual int homePe(int arrayHdl,const CkArrayIndex &element)
91              { return procNum(arrayHdl, element); }
92 //  virtual void pup(PUP::er &p) { CkGroupReadyCallback::pup(p); }
93 };
94 /*@}*/
95
96 /**
97 \addtogroup CkArrayImpl
98 \brief Migratable Chare Arrays: Implementation classes.
99 */
100 /*@{*/
101 static inline CkGroupID CkCreatePropMap(void)
102 {
103   return CProxy_PropMap::ckNew();
104 }
105
106 extern void _propMapInit(void);
107 extern void _CkMigratable_initInfoInit(void);
108
109
110 /*************************** CkLocRec ******************************/
111 class CkArray;//Array manager
112 class CkLocMgr;//Location manager
113 class CkMigratable;//Migratable object
114
115 /**
116  * A CkLocRec is our local representation of an array element.
117  * The location manager's main hashtable maps array indices to
118  * CkLocRec *'s.
119  */
120 class CkLocRec {
121 protected:
122   CkLocMgr *myLocMgr;
123   //int lastAccess;//Age when last accessed. Removed since unused and colliding with a inheriting class, Filippo
124   //Called when we discover we are obsolete before we delete ourselves
125   virtual void weAreObsolete(const CkArrayIndex &idx);
126 public:
127   CkLocRec(CkLocMgr *mgr) :myLocMgr(mgr) { }
128   virtual ~CkLocRec();
129   inline CkLocMgr *getLocMgr(void) const {return myLocMgr;}
130
131   /// Return the type of this ArrayRec:
132   typedef enum {
133     base=0,//Base class (invalid type)
134     local,//Array element that lives on this Pe
135     remote,//Array element that lives on some other Pe
136     buffering,//Array element that was just created
137     dead//Deleted element (for debugging)
138   } RecType;
139   virtual RecType type(void)=0;
140   
141   /// Accept a message for this element
142   virtual CmiBool deliver(CkArrayMessage *m,CkDeliver_t type,int opts=0)=0;
143   
144   /// This is called when this ArrayRec is about to be replaced.
145   /// It is only used to deliver buffered element messages.
146   virtual void beenReplaced(void);
147   
148   /// Return if this rec is now obsolete
149   virtual CmiBool isObsolete(int nSprings,const CkArrayIndex &idx)=0; 
150
151   /// Return the represented array element; or NULL if there is none
152   virtual CkMigratable *lookupElement(CkArrayID aid);
153
154   /// Return the last known processor; or -1 if none
155   virtual int lookupProcessor(void);
156 };
157
158 /**
159  * Represents a local array element.
160  */
161 class CkLocRec_local : public CkLocRec {
162   CkArrayIndexMax idx;/// Element's array index
163   int localIdx; /// Local index (into array manager's element lists)
164   CmiBool running; /// True when inside a startTiming/stopTiming pair
165   CmiBool *deletedMarker; /// Set this if we're deleted during processing
166   CkQ<CkArrayMessage *> halfCreated; /// Stores messages for nonexistent siblings of existing elements
167 public:
168   //Creation and Destruction:
169   CkLocRec_local(CkLocMgr *mgr,CmiBool fromMigration,CmiBool ignoreArrival,
170         const CkArrayIndex &idx_,int localIdx_);
171   void migrateMe(int toPe); //Leave this processor
172   void destroy(void); //User called destructor
173   virtual ~CkLocRec_local();
174
175   /// A new element has been added to this index
176   void addedElement(void);
177
178   /**
179    *  Accept a message for this element.
180    *  Returns false if the element died during the receive.
181    */
182   virtual CmiBool deliver(CkArrayMessage *m,CkDeliver_t type,int opts=0);
183
184   /** Invoke the given entry method on this element.
185    *   Returns false if the element died during the receive.
186    *   If doFree is true, the message is freed after send;
187    *    if false, the message can be reused.
188    */
189   CmiBool invokeEntry(CkMigratable *obj,void *msg,int idx,CmiBool doFree);
190
191   virtual RecType type(void);
192   virtual CmiBool isObsolete(int nSprings,const CkArrayIndex &idx);
193
194 #if CMK_LBDB_ON  //For load balancing:
195   /// Control the load balancer:
196   void startTiming(void);
197   void stopTiming(void);
198 #else
199   inline void startTiming(void) {  }
200   inline void stopTiming(void) { }
201 #endif
202   inline int getLocalIndex(void) const {return localIdx;}
203   inline const CkArrayIndex &getIndex(void) const {return idx;}
204   virtual CkMigratable *lookupElement(CkArrayID aid);
205   virtual int lookupProcessor(void);
206
207 #if CMK_LBDB_ON
208 public:
209   inline LBDatabase *getLBDB(void) const {return the_lbdb;}
210   static void staticMigrate(LDObjHandle h, int dest);
211   void recvMigrate(int dest);
212   void setMigratable(int migratable);   /// set migratable
213   void AsyncMigrate(CmiBool use);
214   CmiBool isAsyncMigrate()   { return asyncMigrate; }
215   void ReadyMigrate(CmiBool ready) { readyMigrate = ready; } ///called from user
216   int  isReadyMigrate() { return readyMigrate; }
217   CmiBool checkBufferedMigration();     // check and execute pending migration
218   int   MigrateToPe();
219 private:
220   LBDatabase *the_lbdb;
221   LDObjHandle ldHandle;
222   CmiBool  asyncMigrate;  /// if readyMove is inited
223   CmiBool  readyMigrate;    /// status whether it is ready to migrate
224   int  nextPe;              /// next migration dest processor
225 #else
226         void AsyncMigrate(CmiBool use){};
227 #endif
228 /**FAULT_EVAC*/
229 private:
230         CmiBool asyncEvacuate; //can the element be evacuated anytime, false for tcharm 
231         CmiBool bounced; //did this element try to immigrate into a processor which was evacuating
232                                                                                         // and was bounced away to some other processor. This is assumed to happen
233                                                                                         //only if this object was migrated by a load balancer, but the processor
234                                                                                         // started crashing soon after
235 public: 
236         CmiBool isAsyncEvacuate(){return asyncEvacuate;}
237         void AsyncEvacuate(CmiBool set){asyncEvacuate = set;}
238         CmiBool isBounced(){return bounced;}
239         void Bounced(CmiBool set){bounced = set;}
240 };
241 class CkLocRec_remote;
242
243 /*********************** CkMigratable ******************************/
244 /** This is the superclass of all migratable parallel objects.
245  *  Currently, that's just array elements.
246  */
247 #if CMK_OUT_OF_CORE
248 #  include "conv-ooc.h"
249 extern CooPrefetchManager CkArrayElementPrefetcher;
250 // If this flag is set, this creation/deletion is just 
251 //   a "fake" constructor/destructor call for prefetching.
252 CkpvExtern(int,CkSaveRestorePrefetch);
253 #endif
254
255 class CkMigratable : public Chare {
256 protected:
257   CkLocRec_local *myRec;
258 private:
259   int thisChareType;//My chare type
260   void commonInit(void);
261         bool asyncEvacuate;
262 public:
263   CkArrayIndexMax thisIndexMax;
264
265   CkMigratable(void);
266   CkMigratable(CkMigrateMessage *m);
267   virtual ~CkMigratable();
268   virtual void pup(PUP::er &p);
269   virtual void CkAddThreadListeners(CthThread tid, void *msg);
270
271   inline int ckGetChareType(void) const {return thisChareType;}
272   const CkArrayIndex &ckGetArrayIndex(void) const {return myRec->getIndex();}
273
274 #if CMK_LBDB_ON  //For load balancing:
275   //Suspend load balancer measurements (e.g., before CthSuspend)
276   inline void ckStopTiming(void) {myRec->stopTiming();}
277   //Begin load balancer measurements again (e.g., after CthSuspend)
278   inline void ckStartTiming(void) {myRec->startTiming();}
279   inline LBDatabase *getLBDB(void) const {return myRec->getLBDB();}
280 #else
281   inline void ckStopTiming(void) { }
282   inline void ckStartTiming(void) { }
283 #endif
284
285   /// for inline call
286   LDObjHandle timingBeforeCall(int *objstopped);
287   void timingAfterCall(LDObjHandle objHandle,int *objstopped);
288
289   //Initiate a migration to the given processor
290   inline void ckMigrate(int toPe) {myRec->migrateMe(toPe);}
291   
292   /// Called by the system just before and after migration to another processor:  
293   virtual void ckAboutToMigrate(void); /*default is empty*/
294   virtual void ckJustMigrated(void); /*default is empty*/
295
296   /// Delete this object
297   virtual void ckDestroy(void);
298
299   /// Execute the given entry method.  Returns false if the element 
300   /// deleted itself or migrated away during execution.
301   inline CmiBool ckInvokeEntry(int epIdx,void *msg,CmiBool doFree) 
302           {return myRec->invokeEntry(this,msg,epIdx,doFree);}
303
304 protected:
305   /// A more verbose form of abort
306   virtual void CkAbort(const char *str) const;
307
308   CmiBool usesAtSync;//You must set this in the constructor to use AtSync().
309   CmiBool barrierRegistered;//True iff barrier handle below is set
310
311 public:
312   virtual void ResumeFromSync(void);
313
314 #if CMK_LBDB_ON  //For load balancing:
315   void AtSync(int waitForMigration=1);
316   int MigrateToPe()  { return myRec->MigrateToPe(); }
317
318 private: //Load balancer state:
319   LDBarrierClient ldBarrierHandle;//Transient (not migrated)  
320   LDBarrierReceiver ldBarrierRecvHandle;//Transient (not migrated)  
321   static void staticResumeFromSync(void* data);
322 public:
323   void ReadyMigrate(CmiBool ready);
324   void ckFinishConstruction(void);
325   void setMigratable(int migratable);
326 #else
327   void AtSync(int waitForMigration=1) { ResumeFromSync();}
328   void setMigratable(int migratable)  { }
329 public:
330   void ckFinishConstruction(void) { }
331 #endif
332 #if CMK_OUT_OF_CORE
333 private:
334   friend class CkLocMgr;
335   friend int CkArrayPrefetch_msg2ObjId(void *msg);
336   friend void CkArrayPrefetch_writeToSwap(FILE *swapfile,void *objptr);
337   friend void CkArrayPrefetch_readFromSwap(FILE *swapfile,void *objptr);
338   int prefetchObjID; //From CooRegisterObject
339   CmiBool isInCore; //If true, the object is present in memory
340 #endif
341         /*
342                 FAULT_EVAC
343         */
344         void AsyncEvacuate(CmiBool set){myRec->AsyncEvacuate(set);asyncEvacuate = set;};
345         public:
346         bool isAsyncEvacuate(){return asyncEvacuate;};
347 };
348
349 /** 
350  * Stores a list of array elements.  These lists are 
351  * kept by the array managers. 
352  */
353 class CkMigratableList {
354         CkVec< CkZeroPtr<CkMigratable> > el;
355  public:
356         CkMigratableList();
357         ~CkMigratableList();
358         
359         void setSize(int s);
360         inline int length(void) const {return el.length();}
361
362         /// Add an element at the given location
363         void put(CkMigratable *v,int atIdx);
364
365         /// Return the element at the given location
366         inline CkMigratable *get(int localIdx) {return el[localIdx];}
367
368         /**
369          * Return the next non-empty element starting from the given index,
370          * or NULL if there is none.  Updates from to point past the returned index.
371         */
372         CkMigratable *next(int &from) {
373                 while (from<length()) {
374                         CkMigratable *ret=el[from];
375                         from++;
376                         if (ret!=NULL) return ret;
377                 }
378                 return NULL;
379         }
380
381         /// Remove the element at the given location
382         inline void empty(int localIdx) {el[localIdx]=NULL;}
383 };
384
385 /**
386  *A typed version of the above.
387  */
388 template <class T>
389 class CkMigratableListT : public CkMigratableList {
390         typedef CkMigratableList super;
391 public:
392         inline void put(T *v,int atIdx) {super::put((void *)v,atIdx);}
393         inline T *get(int localIdx) {return (T *)super::get(localIdx);}
394         inline T *next(int &from) {return (T *)super::next(from);}
395 };
396
397
398 /********************** CkLocMgr ********************/
399 /// A tiny class for detecting heap corruption
400 class CkMagicNumber_impl {
401  protected:
402         int magic;
403         void badMagicNumber(int expected,const char *file,int line,void *obj) const;
404         CkMagicNumber_impl(int m);
405 };
406 template<class T>
407 class CkMagicNumber : public CkMagicNumber_impl {
408         enum {good=sizeof(T)^0x7EDC0000};
409  public:
410         CkMagicNumber(void) :CkMagicNumber_impl(good) {}
411         inline void check(const char *file,int line,void *obj) const {
412                 if (magic!=good) badMagicNumber(good,file,line,obj);
413         }
414 #ifndef CMK_OPTIMIZE
415 #   define CK_MAGICNUMBER_CHECK magic.check(__FILE__,__LINE__,this);
416 #else
417 #   define CK_MAGICNUMBER_CHECK /*empty, for speed*/
418 #endif
419 };
420
421 /**
422  * The "data" class passed to a CkLocIterator, which refers to a bound
423  * glob of array elements.
424  * This is a transient class-- do not attempt to store it or send 
425  * it across processors.
426  */
427
428         
429 class CkLocation {
430         CkLocMgr *mgr;
431         CkLocRec_local *rec;
432 public:
433         CkLocation(CkLocMgr *mgr_, CkLocRec_local *rec_);
434         
435         /// Find our location manager
436         inline CkLocMgr *getManager(void) const {return mgr;}
437         
438         /// Find the local record that refers to this element
439         inline CkLocRec_local *getLocalRecord(void) const {return rec;}
440         
441         /// Look up and return the array index of this location.
442         const CkArrayIndex &getIndex(void) const;
443         
444         void destroyAll();
445
446         /// Pup all the array elements at this location.
447         void pup(PUP::er &p);
448 };
449
450 /**
451  * This interface describes the destination for an iterator over
452  * the locations in an array.
453  */
454 class CkLocIterator {
455 public:
456         virtual ~CkLocIterator();
457         
458         /// This location is part of the calling location manager.
459         virtual void addLocation(CkLocation &loc) =0;
460 };
461
462 enum CkElementCreation_t {
463   CkElementCreation_migrate=2, // Create object for normal migration arrival
464   CkElementCreation_resume=3 // Create object after checkpoint
465 };
466 /// Abstract superclass of all array manager objects 
467 class CkArrMgr {
468 public:
469         /// Insert this initial element on this processor
470         virtual void insertInitial(const CkArrayIndex &idx,void *ctorMsg, int local=1)=0;
471         
472         /// Done with initial insertions
473         virtual void doneInserting(void)=0;
474         
475         /// Create an uninitialized element after migration
476         ///  The element's constructor will be called immediately after.
477         virtual CkMigratable *allocateMigrated(int elChareType,
478                 const CkArrayIndex &idx,CkElementCreation_t type) =0;
479
480         /// Demand-create an element at this index on this processor
481         ///  Returns true if the element was successfully added;
482         ///  false if the element migrated away or deleted itself.
483         virtual CmiBool demandCreateElement(const CkArrayIndex &idx,
484                 int onPe,int ctor,CkDeliver_t type) =0;
485 };
486
487 /**
488  * A group which manages the location of an indexed set of
489  * migratable objects.  Knows about insertions, deletions,
490  * home processors, migration, and message forwarding.
491  */
492 class CkLocMgr : public IrrGroup {
493         CkMagicNumber<CkMigratable> magic; //To detect heap corruption
494 public:
495         CkLocMgr(CkGroupID map,CkGroupID _lbdb,int numInitial);
496         CkLocMgr(CkMigrateMessage *m);
497         inline CmiBool isLocMgr(void) { return CmiTrue; }
498         CkGroupID &getGroupID(void) {return thisgroup;}
499         inline CProxy_CkLocMgr &getProxy(void)
500                 {return thisProxy;}
501         inline CProxyElement_CkLocMgr &getLocalProxy(void)
502                 {return thislocalproxy;}
503
504 //Interface used by array manager and proxies
505         /// Add a new local array manager to our list.  Array managers
506         ///  must be registered in the same order on all processors.
507         /// Returns a list which will contain that array's local elements
508         CkMigratableList *addManager(CkArrayID aid,CkArrMgr *mgr);
509
510         /// Populate this array with initial elements
511         void populateInitial(int numElements,void *initMsg,CkArrMgr *mgr)
512                 {map->populateInitial(mapHandle,numElements,initMsg,mgr);}
513
514         /// Add a new local array element, calling element's constructor
515         ///  Returns true if the element was successfully added;
516         ///  false if the element migrated away or deleted itself.
517         CmiBool addElement(CkArrayID aid,const CkArrayIndex &idx,
518                 CkMigratable *elt,int ctorIdx,void *ctorMsg);
519
520         ///Deliver message to this element:
521         inline void deliverViaQueue(CkMessage *m) {deliver(m,CkDeliver_queue);}
522         inline void deliverInline(CkMessage *m) {deliver(m,CkDeliver_inline);}
523         void deliver(CkMessage *m, CkDeliver_t type, int opts=0);
524
525         ///Done inserting elements for now
526         void doneInserting(void);
527         void startInserting(void);
528
529 //Advisories:
530         ///This index now lives on the given processor-- update local records
531         void inform(const CkArrayIndex &idx,int nowOnPe);
532
533         ///This index now lives on the given processor-- tell the home processor
534         void informHome(const CkArrayIndex &idx,int nowOnPe);
535
536         ///This message took several hops to reach us-- fix it
537         void multiHop(CkArrayMessage *m);
538
539 //Interface used by CkLocRec_local
540         //Look up the object with this local index
541         inline CkMigratable *lookupLocal(int localIdx,CkArrayID arrayID) {
542 #ifndef CMK_OPTIMIZE
543                 if (managers.find(arrayID)->mgr==NULL)
544                         CkAbort("CkLocMgr::lookupLocal called for unknown array!\n");
545 #endif
546                 return managers.find(arrayID)->elts.get(localIdx);
547         }
548
549         //Migrate us to another processor
550         void emigrate(CkLocRec_local *rec,int toPe);
551
552 #if CMK_LBDB_ON
553         LBDatabase *getLBDB(void) const { return the_lbdb; }
554         const LDOMHandle &getOMHandle(void) const { return myLBHandle; }
555 #endif
556
557         //This index will no longer be used-- delete the associated elements
558         void reclaim(const CkArrayIndex &idx,int localIdx);
559
560         int getSpringCount(void) const { return nSprings; }
561
562         CmiBool demandCreateElement(CkArrayMessage *msg,int onPe,CkDeliver_t type);
563
564 //Interface used by external users:
565         /// Home mapping
566         inline int homePe(const CkArrayIndex &idx) const
567                 {return map->homePe(mapHandle,idx);}
568         inline int procNum(const CkArrayIndex &idx) const
569                 {return map->procNum(mapHandle,idx);}
570         inline CmiBool isHome(const CkArrayIndex &idx) const
571                 {return (CmiBool)(homePe(idx)==CkMyPe());}
572
573         /// Look up the object with this array index, or return NULL
574         CkMigratable *lookup(const CkArrayIndex &idx,CkArrayID aid);
575
576         /// Return the "last-known" location (returns a processor number)
577         int lastKnown(const CkArrayIndex &idx);
578
579         /// Return true if this array element lives on another processor
580         bool isRemote(const CkArrayIndex &idx,int *onPe) const;
581
582         /// Pass each of our locations (each separate array index) to this destination.
583         void iterate(CkLocIterator &dest);
584
585         /// Insert and unpack this array element from this checkpoint (e.g., from CkLocation::pup)
586         void resume(const CkArrayIndex &idx, PUP::er &p);
587
588 //Communication:
589         void immigrate(CkArrayElementMigrateMessage *msg);
590         void updateLocation(const CkArrayIndexMax &idx,int nowOnPe);
591         void reclaimRemote(const CkArrayIndexMax &idx,int deletedOnPe);
592         void dummyAtSync(void);
593
594         /// return a list of migratables in this local record
595         void migratableList(CkLocRec_local *rec, CkVec<CkMigratable *> &list);
596
597         void flushAllRecs(void);
598         void pup(PUP::er &p);
599         
600 private:
601 //Internal interface:
602         //Add given element array record at idx, replacing the existing record
603         void insertRec(CkLocRec *rec,const CkArrayIndex &idx);
604         //Add given record, when there is guarenteed to be no prior record
605         void insertRecN(CkLocRec *rec,const CkArrayIndex &idx);
606         //Insert a remote record at the given index
607         CkLocRec_remote *insertRemote(const CkArrayIndex &idx,int nowOnPe);
608
609         //Look up array element in hash table.  Index out-of-bounds if not found.
610         CkLocRec *elementRec(const CkArrayIndex &idx);
611         //Look up array element in hash table.  Return NULL if not there.
612         CkLocRec *elementNrec(const CkArrayIndex &idx);
613         //Remove this entry from the table (does not delete record)
614         void removeFromTable(const CkArrayIndex &idx);
615
616         friend class CkLocation; //so it can call pupElementsFor
617         friend class ArrayElement;
618         void pupElementsFor(PUP::er &p,CkLocRec_local *rec,
619                 CkElementCreation_t type);
620
621         /// Call this member function on each element of this location:
622         typedef void (CkMigratable::* CkMigratable_voidfn_t)(void);
623         void callMethod(CkLocRec_local *rec,CkMigratable_voidfn_t fn);
624
625         CmiBool deliverUnknown(CkArrayMessage *msg,CkDeliver_t type,int opts);
626
627         /// Create a new local record at this array index.
628         CkLocRec_local *createLocal(const CkArrayIndex &idx, 
629                 CmiBool forMigration, CmiBool ignoreArrival,
630                 CmiBool notifyHome);
631
632 //Data Members:
633         //Map array ID to manager and elements
634         class ManagerRec {
635         public:
636                 ManagerRec *next; //next non-null array manager
637                 CkArrMgr *mgr;
638                 CkMigratableList elts;
639                 ManagerRec() {
640                         next=NULL;
641                         mgr=NULL;
642                 }
643                 void init(void) { next=NULL; mgr=NULL; }
644                 CkMigratable *element(int localIdx) {
645                         return elts.get(localIdx);
646                 }
647         };
648         GroupIdxArray<ManagerRec *> managers;
649         int nManagers;
650         ManagerRec *firstManager; //First non-null array manager
651
652         CmiBool addElementToRec(CkLocRec_local *rec,ManagerRec *m,
653                 CkMigratable *elt,int ctorIdx,void *ctorMsg);
654
655         //For keeping track of free local indices
656         CkVec<int> freeList;//Linked list of free local indices
657         int firstFree;//First free local index
658         int localLen;//Last allocated local index plus one
659         int nextFree(void);
660
661         CProxy_CkLocMgr thisProxy;
662         CProxyElement_CkLocMgr thislocalproxy;
663         /// The core of the location manager: map array index to element representative
664         CkHashtableT<CkArrayIndexMax,CkLocRec *> hash;
665         CmiImmediateLockType hashImmLock;
666
667         /// This flag is set while we delete an old copy of a migrator
668         CmiBool duringMigration;
669
670         //Occasionally clear out stale remote pointers
671         static void staticSpringCleaning(void *mgr,double curWallTime);
672         void springCleaning(void);
673         int nSprings;
674
675         //Map object
676         CkGroupID mapID;
677         int mapHandle;
678         CkArrayMap *map;
679
680         CkGroupID lbdbID;
681 #if CMK_LBDB_ON
682         LBDatabase *the_lbdb;
683         LDBarrierClient dummyBarrierHandle;
684         static void staticDummyResumeFromSync(void* data);
685         void dummyResumeFromSync(void);
686         static void staticRecvAtSync(void* data);
687         void recvAtSync(void);
688         LDOMHandle myLBHandle;
689 #endif
690         void initLB(CkGroupID lbdbID);
691 };
692
693 /*@}*/
694
695 #endif /*def(thisHeader)*/