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