Changes for out-of-core emulation in BigSim. Details could be referred to Chao Mei...
[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(CkArrayIndexMax& numElements,CkArrayID aid);
88   virtual void populateInitial(int arrayHdl,CkArrayIndexMax& 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   void setObjTiming(double cputime);
199 #else
200   inline void startTiming(void) {  }
201   inline void stopTiming(void) { }
202 #endif
203   inline int getLocalIndex(void) const {return localIdx;}
204   inline const CkArrayIndex &getIndex(void) const {return idx;}
205   virtual CkMigratable *lookupElement(CkArrayID aid);
206   virtual int lookupProcessor(void);
207
208 #if CMK_LBDB_ON
209 public:
210   inline LBDatabase *getLBDB(void) const {return the_lbdb;}
211   inline LDObjHandle getLdHandle() const{return ldHandle;}
212   static void staticMigrate(LDObjHandle h, int dest);
213   void recvMigrate(int dest);
214   void setMigratable(int migratable);   /// set migratable
215   void AsyncMigrate(CmiBool use);
216   CmiBool isAsyncMigrate()   { return asyncMigrate; }
217   void ReadyMigrate(CmiBool ready) { readyMigrate = ready; } ///called from user
218   int  isReadyMigrate() { return readyMigrate; }
219   CmiBool checkBufferedMigration();     // check and execute pending migration
220   int   MigrateToPe();
221   inline void setMeasure(CmiBool status) { enable_measure = status; }
222 private:
223   LBDatabase *the_lbdb;
224   LDObjHandle ldHandle;
225   CmiBool  asyncMigrate;  /// if readyMove is inited
226   CmiBool  readyMigrate;    /// status whether it is ready to migrate
227   CmiBool  enable_measure;
228   int  nextPe;              /// next migration dest processor
229 #else
230   void AsyncMigrate(CmiBool use){};
231 #endif
232 /**FAULT_EVAC*/
233 private:
234         CmiBool asyncEvacuate; //can the element be evacuated anytime, false for tcharm 
235         CmiBool bounced; //did this element try to immigrate into a processor which was evacuating
236                                                                                         // and was bounced away to some other processor. This is assumed to happen
237                                                                                         //only if this object was migrated by a load balancer, but the processor
238                                                                                         // started crashing soon after
239 public: 
240         CmiBool isAsyncEvacuate(){return asyncEvacuate;}
241         void AsyncEvacuate(CmiBool set){asyncEvacuate = set;}
242         CmiBool isBounced(){return bounced;}
243         void Bounced(CmiBool set){bounced = set;}
244 };
245 class CkLocRec_remote;
246
247 /*********************** CkMigratable ******************************/
248 /** This is the superclass of all migratable parallel objects.
249  *  Currently, that's just array elements.
250  */
251 #if CMK_OUT_OF_CORE
252 #  include "conv-ooc.h"
253 extern CooPrefetchManager CkArrayElementPrefetcher;
254 // If this flag is set, this creation/deletion is just 
255 //   a "fake" constructor/destructor call for prefetching.
256 CkpvExtern(int,CkSaveRestorePrefetch);
257 #endif
258
259 class CkMigratable : public Chare {
260 protected:
261   CkLocRec_local *myRec;
262 private:
263   int thisChareType;//My chare type
264   void commonInit(void);
265         bool asyncEvacuate;
266 public:
267   CkArrayIndexMax thisIndexMax;
268
269   CkMigratable(void);
270   CkMigratable(CkMigrateMessage *m);
271   virtual ~CkMigratable();
272   virtual void pup(PUP::er &p);
273   virtual void CkAddThreadListeners(CthThread tid, void *msg);
274
275   virtual int ckGetChareType(void) const;// {return thisChareType;}
276   const CkArrayIndex &ckGetArrayIndex(void) const {return myRec->getIndex();}
277
278 #if CMK_LBDB_ON  //For load balancing:
279   //Suspend load balancer measurements (e.g., before CthSuspend)
280   inline void ckStopTiming(void) {myRec->stopTiming();}
281   //Begin load balancer measurements again (e.g., after CthSuspend)
282   inline void ckStartTiming(void) {myRec->startTiming();}
283   inline LBDatabase *getLBDB(void) const {return myRec->getLBDB();}
284 #else
285   inline void ckStopTiming(void) { }
286   inline void ckStartTiming(void) { }
287 #endif
288
289   /// for inline call
290   LDObjHandle timingBeforeCall(int *objstopped);
291   void timingAfterCall(LDObjHandle objHandle,int *objstopped);
292
293   //Initiate a migration to the given processor
294   inline void ckMigrate(int toPe) {myRec->migrateMe(toPe);}
295   
296   /// Called by the system just before and after migration to another processor:  
297   virtual void ckAboutToMigrate(void); /*default is empty*/
298   virtual void ckJustMigrated(void); /*default is empty*/
299
300   //used for out-of-core emulation
301   virtual void ckJustRestored(void); /*default is empty*/
302
303   /// Delete this object
304   virtual void ckDestroy(void);
305
306   /// Execute the given entry method.  Returns false if the element 
307   /// deleted itself or migrated away during execution.
308   inline CmiBool ckInvokeEntry(int epIdx,void *msg,CmiBool doFree) 
309           {return myRec->invokeEntry(this,msg,epIdx,doFree);}
310
311 protected:
312   /// A more verbose form of abort
313   virtual void CkAbort(const char *str) const;
314
315   CmiBool usesAtSync;//You must set this in the constructor to use AtSync().
316   CmiBool usesAutoMeasure; //You must set this to use auto lb instrumentation.
317   CmiBool barrierRegistered;//True iff barrier handle below is set
318
319 public:
320   virtual void ResumeFromSync(void);
321   virtual void UserSetLBLoad(void);  /// user define this when setLBLoad is true
322   void setObjTiming(double cputime);
323
324 #if CMK_LBDB_ON  //For load balancing:
325   void AtSync(int waitForMigration=1);
326   int MigrateToPe()  { return myRec->MigrateToPe(); }
327
328 private: //Load balancer state:
329   LDBarrierClient ldBarrierHandle;//Transient (not migrated)  
330   LDBarrierReceiver ldBarrierRecvHandle;//Transient (not migrated)  
331   static void staticResumeFromSync(void* data);
332 public:
333   void ReadyMigrate(CmiBool ready);
334   void ckFinishConstruction(void);
335   void setMigratable(int migratable);
336 #else
337   void AtSync(int waitForMigration=1) { ResumeFromSync();}
338   void setMigratable(int migratable)  { }
339 public:
340   void ckFinishConstruction(void) { }
341 #endif
342 #if CMK_OUT_OF_CORE
343 private:
344   friend class CkLocMgr;
345   friend int CkArrayPrefetch_msg2ObjId(void *msg);
346   friend void CkArrayPrefetch_writeToSwap(FILE *swapfile,void *objptr);
347   friend void CkArrayPrefetch_readFromSwap(FILE *swapfile,void *objptr);
348   int prefetchObjID; //From CooRegisterObject
349   CmiBool isInCore; //If true, the object is present in memory
350 #endif
351         /*
352                 FAULT_EVAC
353         */
354         void AsyncEvacuate(CmiBool set){myRec->AsyncEvacuate(set);asyncEvacuate = set;};
355         public:
356         bool isAsyncEvacuate(){return asyncEvacuate;};
357 };
358
359 /** 
360  * Stores a list of array elements.  These lists are 
361  * kept by the array managers. 
362  */
363 class CkMigratableList {
364         CkVec< CkZeroPtr<CkMigratable> > el;
365  public:
366         CkMigratableList();
367         ~CkMigratableList();
368         
369         void setSize(int s);
370         inline int length(void) const {return el.length();}
371
372         /// Add an element at the given location
373         void put(CkMigratable *v,int atIdx);
374
375         /// Return the element at the given location
376         inline CkMigratable *get(int localIdx) {return el[localIdx];}
377
378         /**
379          * Return the next non-empty element starting from the given index,
380          * or NULL if there is none.  Updates from to point past the returned index.
381         */
382         CkMigratable *next(int &from) {
383                 while (from<length()) {
384                         CkMigratable *ret=el[from];
385                         from++;
386                         if (ret!=NULL) return ret;
387                 }
388                 return NULL;
389         }
390
391         /// Remove the element at the given location
392         inline void empty(int localIdx) {el[localIdx]=NULL;}
393 };
394
395 /**
396  *A typed version of the above.
397  */
398 template <class T>
399 class CkMigratableListT : public CkMigratableList {
400         typedef CkMigratableList super;
401 public:
402         inline void put(T *v,int atIdx) {super::put((void *)v,atIdx);}
403         inline T *get(int localIdx) {return (T *)super::get(localIdx);}
404         inline T *next(int &from) {return (T *)super::next(from);}
405 };
406
407
408 /********************** CkLocMgr ********************/
409 /// A tiny class for detecting heap corruption
410 class CkMagicNumber_impl {
411  protected:
412         int magic;
413         void badMagicNumber(int expected,const char *file,int line,void *obj) const;
414         CkMagicNumber_impl(int m);
415 };
416 template<class T>
417 class CkMagicNumber : public CkMagicNumber_impl {
418         enum {good=sizeof(T)^0x7EDC0000};
419  public:
420         CkMagicNumber(void) :CkMagicNumber_impl(good) {}
421         inline void check(const char *file,int line,void *obj) const {
422                 if (magic!=good) badMagicNumber(good,file,line,obj);
423         }
424 #ifndef CMK_OPTIMIZE
425 #   define CK_MAGICNUMBER_CHECK magic.check(__FILE__,__LINE__,this);
426 #else
427 #   define CK_MAGICNUMBER_CHECK /*empty, for speed*/
428 #endif
429 };
430
431 /**
432  * The "data" class passed to a CkLocIterator, which refers to a bound
433  * glob of array elements.
434  * This is a transient class-- do not attempt to store it or send 
435  * it across processors.
436  */
437
438         
439 class CkLocation {
440         CkLocMgr *mgr;
441         CkLocRec_local *rec;
442 public:
443         CkLocation(CkLocMgr *mgr_, CkLocRec_local *rec_);
444         
445         /// Find our location manager
446         inline CkLocMgr *getManager(void) const {return mgr;}
447         
448         /// Find the local record that refers to this element
449         inline CkLocRec_local *getLocalRecord(void) const {return rec;}
450         
451         /// Look up and return the array index of this location.
452         const CkArrayIndex &getIndex(void) const;
453         
454         void destroyAll();
455
456         /// Pup all the array elements at this location.
457         void pup(PUP::er &p);
458 };
459
460 /**
461  * This interface describes the destination for an iterator over
462  * the locations in an array.
463  */
464 class CkLocIterator {
465 public:
466         virtual ~CkLocIterator();
467         
468         /// This location is part of the calling location manager.
469         virtual void addLocation(CkLocation &loc) =0;
470 };
471
472 enum CkElementCreation_t {
473   CkElementCreation_migrate=2, // Create object for normal migration arrival
474   CkElementCreation_resume=3,  // Create object after checkpoint
475   CkElementCreation_restore=4  // Create object after checkpoint, skip listeners
476 };
477 /// Abstract superclass of all array manager objects 
478 class CkArrMgr {
479 public:
480         virtual ~CkArrMgr() {}
481         /// Insert this initial element on this processor
482         virtual void insertInitial(const CkArrayIndex &idx,void *ctorMsg, int local=1)=0;
483         
484         /// Done with initial insertions
485         virtual void doneInserting(void)=0;
486         
487         /// Create an uninitialized element after migration
488         ///  The element's constructor will be called immediately after.
489         virtual CkMigratable *allocateMigrated(int elChareType,
490                 const CkArrayIndex &idx,CkElementCreation_t type) =0;
491
492         /// Demand-create an element at this index on this processor
493         ///  Returns true if the element was successfully added;
494         ///  false if the element migrated away or deleted itself.
495         virtual CmiBool demandCreateElement(const CkArrayIndex &idx,
496                 int onPe,int ctor,CkDeliver_t type) =0;
497 };
498
499 /**
500  * A group which manages the location of an indexed set of
501  * migratable objects.  Knows about insertions, deletions,
502  * home processors, migration, and message forwarding.
503  */
504 class CkLocMgr : public IrrGroup {
505         CkMagicNumber<CkMigratable> magic; //To detect heap corruption
506 public:
507         CkLocMgr(CkGroupID map,CkGroupID _lbdb,CkArrayIndexMax& numInitial);
508         CkLocMgr(CkMigrateMessage *m);
509         inline CmiBool isLocMgr(void) { return CmiTrue; }
510         CkGroupID &getGroupID(void) {return thisgroup;}
511         inline CProxy_CkLocMgr &getProxy(void)
512                 {return thisProxy;}
513         inline CProxyElement_CkLocMgr &getLocalProxy(void)
514                 {return thislocalproxy;}
515
516 //Interface used by array manager and proxies
517         /// Add a new local array manager to our list.  Array managers
518         ///  must be registered in the same order on all processors.
519         /// Returns a list which will contain that array's local elements
520         CkMigratableList *addManager(CkArrayID aid,CkArrMgr *mgr);
521
522         /// Populate this array with initial elements
523         void populateInitial(CkArrayIndexMax& numElements,void *initMsg,CkArrMgr *mgr)
524                 {map->populateInitial(mapHandle,numElements,initMsg,mgr);}
525
526         /// Add a new local array element, calling element's constructor
527         ///  Returns true if the element was successfully added;
528         ///  false if the element migrated away or deleted itself.
529         CmiBool addElement(CkArrayID aid,const CkArrayIndex &idx,
530                 CkMigratable *elt,int ctorIdx,void *ctorMsg);
531
532         ///Deliver message to this element:
533         inline void deliverViaQueue(CkMessage *m) {deliver(m,CkDeliver_queue);}
534         inline void deliverInline(CkMessage *m) {deliver(m,CkDeliver_inline);}
535         void deliver(CkMessage *m, CkDeliver_t type, int opts=0);
536
537         ///Done inserting elements for now
538         void doneInserting(void);
539         void startInserting(void);
540
541 //Advisories:
542         ///This index now lives on the given processor-- update local records
543         void inform(const CkArrayIndex &idx,int nowOnPe);
544
545         ///This index now lives on the given processor-- tell the home processor
546         void informHome(const CkArrayIndex &idx,int nowOnPe);
547
548         ///This message took several hops to reach us-- fix it
549         void multiHop(CkArrayMessage *m);
550
551 //Interface used by CkLocRec_local
552         //Look up the object with this local index
553         inline CkMigratable *lookupLocal(int localIdx,CkArrayID arrayID) {
554 #ifndef CMK_OPTIMIZE
555                 if (managers.find(arrayID)->mgr==NULL)
556                         CkAbort("CkLocMgr::lookupLocal called for unknown array!\n");
557 #endif
558                 return managers.find(arrayID)->elts.get(localIdx);
559         }
560
561         //Migrate us to another processor
562         void emigrate(CkLocRec_local *rec,int toPe);
563
564 #if CMK_LBDB_ON
565         LBDatabase *getLBDB(void) const { return the_lbdb; }
566         const LDOMHandle &getOMHandle(void) const { return myLBHandle; }
567 #endif
568
569         //This index will no longer be used-- delete the associated elements
570         void reclaim(const CkArrayIndex &idx,int localIdx);
571
572         int getSpringCount(void) const { return nSprings; }
573
574         CmiBool demandCreateElement(CkArrayMessage *msg,int onPe,CkDeliver_t type);
575
576 //Interface used by external users:
577         /// Home mapping
578         inline int homePe(const CkArrayIndex &idx) const
579                 {return map->homePe(mapHandle,idx);}
580         inline int procNum(const CkArrayIndex &idx) const
581                 {return map->procNum(mapHandle,idx);}
582         inline CmiBool isHome(const CkArrayIndex &idx) const
583                 {return (CmiBool)(homePe(idx)==CkMyPe());}
584
585         /// Look up the object with this array index, or return NULL
586         CkMigratable *lookup(const CkArrayIndex &idx,CkArrayID aid);
587
588         /// Return the "last-known" location (returns a processor number)
589         int lastKnown(const CkArrayIndex &idx);
590
591         /// Return true if this array element lives on another processor
592         bool isRemote(const CkArrayIndex &idx,int *onPe) const;
593
594         /// Pass each of our locations (each separate array index) to this destination.
595         void iterate(CkLocIterator &dest);
596
597         /// Insert and unpack this array element from this checkpoint (e.g., from CkLocation::pup), skip listeners
598         void restore(const CkArrayIndex &idx, PUP::er &p);
599         /// Insert and unpack this array element from this checkpoint (e.g., from CkLocation::pup)
600         void resume(const CkArrayIndex &idx, PUP::er &p);
601
602 //Communication:
603         void immigrate(CkArrayElementMigrateMessage *msg);
604         void updateLocation(const CkArrayIndexMax &idx,int nowOnPe);
605         void reclaimRemote(const CkArrayIndexMax &idx,int deletedOnPe);
606         void dummyAtSync(void);
607
608         /// return a list of migratables in this local record
609         void migratableList(CkLocRec_local *rec, CkVec<CkMigratable *> &list);
610
611         void flushAllRecs(void);
612         void pup(PUP::er &p);
613         
614 private:
615 //Internal interface:
616         //Add given element array record at idx, replacing the existing record
617         void insertRec(CkLocRec *rec,const CkArrayIndex &idx);
618         //Add given record, when there is guarenteed to be no prior record
619         void insertRecN(CkLocRec *rec,const CkArrayIndex &idx);
620         //Insert a remote record at the given index
621         CkLocRec_remote *insertRemote(const CkArrayIndex &idx,int nowOnPe);
622
623         //Look up array element in hash table.  Index out-of-bounds if not found.
624         CkLocRec *elementRec(const CkArrayIndex &idx);
625         //Look up array element in hash table.  Return NULL if not there.
626         CkLocRec *elementNrec(const CkArrayIndex &idx);
627         //Remove this entry from the table (does not delete record)
628         void removeFromTable(const CkArrayIndex &idx);
629
630         friend class CkLocation; //so it can call pupElementsFor
631         friend class ArrayElement;
632         void pupElementsFor(PUP::er &p,CkLocRec_local *rec,
633                 CkElementCreation_t type);
634
635         /// Call this member function on each element of this location:
636         typedef void (CkMigratable::* CkMigratable_voidfn_t)(void);
637         void callMethod(CkLocRec_local *rec,CkMigratable_voidfn_t fn);
638
639         CmiBool deliverUnknown(CkArrayMessage *msg,CkDeliver_t type,int opts);
640
641         /// Create a new local record at this array index.
642         CkLocRec_local *createLocal(const CkArrayIndex &idx, 
643                 CmiBool forMigration, CmiBool ignoreArrival,
644                 CmiBool notifyHome);
645
646 //Data Members:
647         //Map array ID to manager and elements
648         class ManagerRec {
649         public:
650                 ManagerRec *next; //next non-null array manager
651                 CkArrMgr *mgr;
652                 CkMigratableList elts;
653                 ManagerRec() {
654                         next=NULL;
655                         mgr=NULL;
656                 }
657                 void init(void) { next=NULL; mgr=NULL; }
658                 CkMigratable *element(int localIdx) {
659                         return elts.get(localIdx);
660                 }
661         };
662         GroupIdxArray<ManagerRec *> managers;
663         int nManagers;
664         ManagerRec *firstManager; //First non-null array manager
665
666         CmiBool addElementToRec(CkLocRec_local *rec,ManagerRec *m,
667                 CkMigratable *elt,int ctorIdx,void *ctorMsg);
668
669         //For keeping track of free local indices
670         CkVec<int> freeList;//Linked list of free local indices
671         int firstFree;//First free local index
672         int localLen;//Last allocated local index plus one
673         int nextFree(void);
674
675         CProxy_CkLocMgr thisProxy;
676         CProxyElement_CkLocMgr thislocalproxy;
677         /// The core of the location manager: map array index to element representative
678         CkHashtableT<CkArrayIndexMax,CkLocRec *> hash;
679         CmiImmediateLockType hashImmLock;
680
681         /// This flag is set while we delete an old copy of a migrator
682         CmiBool duringMigration;
683
684         //Occasionally clear out stale remote pointers
685         static void staticSpringCleaning(void *mgr,double curWallTime);
686         void springCleaning(void);
687         int nSprings;
688
689         //Map object
690         CkGroupID mapID;
691         int mapHandle;
692         CkArrayMap *map;
693
694         CkGroupID lbdbID;
695 #if CMK_LBDB_ON
696         LBDatabase *the_lbdb;
697         LDBarrierClient dummyBarrierHandle;
698         static void staticDummyResumeFromSync(void* data);
699         void dummyResumeFromSync(void);
700         static void staticRecvAtSync(void* data);
701         void recvAtSync(void);
702         LDOMHandle myLBHandle;
703 #endif
704         void initLB(CkGroupID lbdbID);
705 };
706
707 /*@}*/
708
709 #endif /*def(thisHeader)*/