00001 #ifndef _CKLISTS_H
00002 #define _CKLISTS_H
00003 
00004 
00005 #include "pup.h"
00006 #include "pup_stl.h"
00007 #include <stdlib.h> 
00008 #include <string.h> 
00009 #include <vector>
00010 
00011 
00012 struct CkNoncopyable {
00013     CkNoncopyable(void) {}
00014     CkNoncopyable(const CkNoncopyable &c) = delete;
00015     CkNoncopyable& operator=(const CkNoncopyable &c) = delete;
00016     CkNoncopyable(CkNoncopyable&&) = default;
00017     CkNoncopyable& operator=(CkNoncopyable &&) = default;
00018     ~CkNoncopyable() = default;
00019 };
00020 
00021 
00022 template <class T>
00023 class CkSTLHelper {
00024 protected:
00025     
00026     void elementCopy(T *dest,const T *src,int nEl) {
00027       for (int i=0;i<nEl;i++) dest[i]=src[i];
00028     }
00029 };
00030 
00031 
00032 template <class T> class CkQ;
00033 template <class T> void pupCkQ(PUP::er &p,CkQ<T> &q);
00034 
00037 template <class T>
00038 class CkQ {
00039     std::vector<T> block;
00040     int first;
00041     int len;
00042     int mask;
00043     void _expand(void) {
00044       
00045       int blklen = block.size();
00046       int newlen = blklen<<1;
00047       mask |= blklen;
00048       if (blklen==0) {
00049     CmiAssert(first == 0);
00050     newlen = 16;
00051     mask = 0x0f;
00052       }
00053       block.resize(newlen);
00054       if (first != 0) {
00055         
00056         CmiAssert(first > 0 && first < blklen);
00057         CmiAssert(newlen >= 2*blklen);
00058         std::move(block.begin(), block.begin()+first, block.begin()+blklen);
00059         std::move(block.begin()+first, block.begin()+blklen, block.begin());
00060         std::move(block.begin()+blklen, block.begin()+(blklen+first), block.begin()+(blklen-first));
00061         first = 0;
00062       }
00063     }
00064   public:
00065     CkQ() : first(0),len(0),mask(0) {}
00066     CkQ(CkQ &&rhs)
00067       : block(rhs.block)
00068       , first(rhs.first)
00069       , len(rhs.len)
00070       , mask(rhs.mask)
00071     {
00072       rhs.block.clear();
00073       rhs.len = 0;
00074     }
00075     CkQ(int sz) :first(0),len(0) {
00076       int size = 2;
00077       mask = 0x03;
00078       while (1<<size < sz) { mask |= 1<<size; size++; }
00079       int blklen = 1<<size;
00080       block.resize(blklen);
00081     }
00082     CkQ(const CkQ&) = delete;
00083     void operator=(const CkQ&) = delete;
00084     void operator=(CkQ&&) = delete; 
00085     ~CkQ() {}
00086     inline int length() const { return len; }
00087     inline int isEmpty() const { return (len==0); }
00088     T deq() {
00089       if(len>0) {
00090         T &ret = block[first];
00091     first = (first+1)&mask;
00092         len--;
00093         return ret;
00094       } else return T(); 
00095     }
00096     void enq(const T &elt) {
00097       if((size_t)len==block.size()) _expand();
00098       block[(first+len)&mask] = elt;
00099       len++;
00100     }
00101     
00102     void push(const T &elt) {
00103       if(len==block.size()) _expand();
00104       first = (first-1+block.size())&mask;
00105       block[first] = elt;
00106       len++;
00107     }
00108     
00109     inline T& peek() {
00110       return block[first];
00111     }
00112     
00113     void insert(int pos, const T &elt) {
00114       while(len==block.size() || pos>=block.size()) _expand();
00115       for (int i=len; i>pos; i--)
00116         block[(i+first)&mask] = std::move(block[(i-1+first)&mask]);
00117       block[(pos+first)&mask] = elt;
00118       if (pos > len) len = pos+1;
00119       else len++;
00120     }
00121     
00122     T remove(int pos) {
00123       if (pos >= len) return T(0);
00124       T ret = block[(pos+first)&mask];
00125       for (int i=pos; i<len-1; i++)
00126         block[(i+first)&mask] = std::move(block[(i+1+first)&mask]);
00127       len--;
00128       return ret;
00129     }
00130     
00131     inline void removeFrom(int pos) {
00132       CmiAssert (pos < len && pos>=0);
00133       len = pos;
00134     }
00135     
00136     inline T& operator[](size_t n)
00137     {
00138         n=(n+first)&mask;
00139         return block[n];
00140     }
00141     
00142     T* getArray(void) {
00143       T *newblk = new T[len];
00144       int i,j;
00145       for(i=0,j=first;i<len;i++){
00146         newblk[i] = block[j];
00147         j = (j+1)&mask;
00148       }
00149       return newblk;
00150     }
00151      void pup(PUP::er &p) {
00152        p.syncComment(PUP::sync_begin_array);
00153        p|len;
00154        for (int i=0;i<len;i++) {
00155          p.syncComment(PUP::sync_item);
00156          if (p.isUnpacking()) {
00157            T t;
00158            p|t;
00159            enq(t);
00160          } else {
00161            p|block[(i+first)&mask];
00162          }
00163        }
00164        p.syncComment(PUP::sync_end_array);
00165      }
00166 };
00167 
00171 class CkSkipInitialization {};
00172 
00173 
00174 template <class T> class CkVec;
00175 template <class T> void pupCkVec(PUP::er &p,CkVec<T> &vec);
00176 
00182 template <class T>
00183 class CkVec : private CkSTLHelper<T> {
00184     typedef CkVec<T> this_type;
00185 
00186     T *block; 
00187     size_t blklen; 
00188     size_t len; 
00189     void makeBlock(int blklen_,int len_) {
00190        if (blklen_==0) block=NULL; 
00191        else {
00192          block=new T[blklen_];
00193          if (block == NULL) blklen_=len_= 0;
00194        }
00195        blklen=blklen_; len=len_;
00196     }
00197     void freeBlock(void) {
00198        len=0; blklen=0;
00199        delete[] block; 
00200        block=NULL;
00201     }
00202     void copyFrom(const this_type &src) {
00203        makeBlock(src.blklen, src.len);
00204        this->elementCopy(block,src.block,blklen);
00205     }
00206   public:
00207     CkVec(): block(NULL), blklen(0), len(0) {}
00208     ~CkVec() { freeBlock(); }
00209     CkVec(const this_type &src) {copyFrom(src);}
00210     CkVec(int size) { makeBlock(size,size); } 
00211     CkVec(int size, int used) { makeBlock(size,used); } 
00212     CkVec(const CkSkipInitialization &skip) {}
00213     this_type &operator=(const this_type &src) {
00214       freeBlock();
00215       copyFrom(src);
00216       return *this;
00217     }
00218 
00219     size_t &length(void) { return len; }
00220     size_t length(void) const {return len;}
00221     T *getVec(void) { return block; }
00222     const T *getVec(void) const { return block; }
00223     
00224     T& operator[](size_t n) {
00225       CmiAssert(n<len);
00226       return block[n]; 
00227     }
00228     
00229     const T& operator[](size_t n) const { 
00230       CmiAssert(n<len);
00231       return block[n]; 
00232     }
00233     
00235     int reserve(size_t newcapacity) {
00236       if (newcapacity<=blklen) return 1; 
00237       T *oldBlock=block; 
00238       makeBlock(newcapacity,len);
00239       if (newcapacity != blklen) return 0;
00240       this->elementCopy(block,oldBlock,len);
00241       delete[] oldBlock; 
00242       return 1;
00243     }
00244     inline size_t capacity(void) const {return blklen;}
00245 
00247     int resize(size_t newsize) {
00248       if (!reserve(newsize)) return 0;
00249       len=newsize;
00250       return 1;
00251     }
00252 
00254     void free() {
00255       freeBlock();
00256     }
00257 
00258     
00259     void growAtLeast(size_t pos) {
00260       if (pos>=blklen) reserve(pos*2+16);
00261     }
00262     void insert(size_t pos, const T &elt) {
00263       if (pos>=len) { 
00264         growAtLeast(pos);
00265         len=pos+1;
00266       }
00267       block[pos] = elt;
00268     }
00269     void remove(size_t pos) {
00270       if (pos>=len) 
00271     {
00272       CmiAbort("CkVec ERROR: out of bounds\n\n"); 
00273       return;
00274     }
00275       for (size_t i=pos; i<len-1; i++)
00276         block[i] = block[i+1];
00277       len--;
00278     }
00279     void removeAll() {
00280       len = 0;
00281     }
00282 
00283     void clear()
00284     {
00285     freeBlock();
00286     }
00287 
00288     void insertAtEnd(const T &elt) {insert(length(),elt);}
00289 
00290 
00291     void push_back(const T &elt) {insert(length(),elt);}
00292     size_t size(void) const {return len;}
00293 
00294 
00295     size_t push_back_v(const T &elt) {insert(length(),elt);return length()-1;}
00296 
00297  
00298 
00299     
00300     int pupbase(PUP::er &p) {
00301        size_t l=len;
00302        p(l);
00303        if (p.isUnpacking()) resize(l); 
00304        return l;
00305     }
00306     
00307 #ifdef _MSC_VER
00308 
00309 
00310      void pup(PUP::er &p) {
00311         pupCkVec(p,*this);
00312      }
00313 #endif
00314 
00315         inline void quickSort(){
00316           q_sort(0, len - 1,128);
00317         }
00318 
00319         inline void quickSort(int changeOverSize){
00320             q_sort(0,len-1,changeOverSize);
00321         }
00322         
00323 
00324         inline void q_sort(int left, int right,int changeOverSize){
00325           int l_hold, r_hold;
00326             int pivot;
00327             
00328             if(left >= right)
00329                 return;
00330             
00331             
00332             int mid =  (left+right)/2;
00333             T temp = block[mid];
00334             block[mid] = block[left];
00335             block[left] = temp;
00336             
00337           l_hold = left;
00338           r_hold = right;
00339             pivot = left;
00340             if(right - left <= changeOverSize){
00341                 bubbleSort(left,right);
00342                 return;
00343             }
00344           while (left < right)
00345           {
00346             while ((block[right] >= block[pivot]) && (left < right))
00347               right--;
00348             while ((block[left] <= block[pivot]) && (left < right))
00349               left++;
00350             
00351                 if(left < right){
00352                     T val = block[left];
00353                     block[left] = block[right];
00354                     block[right] = val;
00355                 }
00356             }
00357             T val = block[left];
00358             block[left] = block[pivot];
00359             block[pivot] = val;
00360           pivot = left;
00361           left = l_hold;
00362           right = r_hold;
00363           if (left < pivot)
00364             q_sort(left, pivot-1,changeOverSize);
00365           if (right > pivot)
00366             q_sort(pivot+1, right,changeOverSize);
00367         }
00368 
00369         inline void bubbleSort(int left,int right){
00370             for(int i=left;i<=right;i++){
00371                 for(int j=i+1;j<=right;j++){
00372                     if(block[i] >= block[j]){
00373                         T val = block[i];
00374                         block[i] = block[j];
00375                         block[j] = val;
00376                     }
00377                 }
00378             }
00379         }
00380 
00381 };
00382 
00384 template <class T>
00385 inline void pupCkVec(PUP::er &p,CkVec<T> &vec) {
00386     size_t len=vec.pupbase(p);
00387     if (len) PUParray(p,&vec[0],len);
00388 }
00389 
00390 #ifndef _MSC_VER
00392 template <class T>
00393 inline void operator|(PUP::er &p,CkVec<T> &vec) {pupCkVec(p,vec);}
00394 #endif
00395 
00396 
00397 #define CkPupBasicVec CkVec
00398 
00401 template <class T> 
00402 class CkPupAlwaysAllocatePtr {
00403 public:
00404     void pup(PUP::er &p,T *&ptr) {
00405         if (p.isUnpacking()) ptr=new T;
00406         p|*ptr;
00407     }
00408 };
00409 
00412 template <class T> 
00413 class CkPupAllocatePtr {
00414 public:
00415     void pup(PUP::er &p,T *&ptr) {
00416         int isNull=(ptr==0);
00417         p(isNull);
00418         if (isNull) ptr=0;
00419         else {
00420             if (p.isUnpacking()) ptr=new T;
00421             p|*ptr;
00422         }
00423     }
00424 };
00425 
00427 template <class T> 
00428 class CkPupAblePtr {
00429 public:
00430     void pup(PUP::er &p,T *&ptr) {
00431         p|ptr;
00432     }
00433 };
00434 
00436 template <class T, class PUP_PTR=CkPupAllocatePtr<T> > 
00437 class CkZeroPtr {
00438 protected:
00439     T *storage;
00440 public:
00441     CkZeroPtr() {storage=0;}
00442     CkZeroPtr(T *sto) {storage=sto;}
00443     CkZeroPtr(const CkZeroPtr &src) { storage=src.storage; }
00444     CkZeroPtr &operator=(const CkZeroPtr &src) {
00445         storage=src.storage; return *this;
00446     }
00447     T *operator=(T *sto) {storage=sto; return sto;}
00448     
00449     operator T* () const {return storage;}
00450 
00451     T *release() {
00452         T *ret=storage; storage=0; return ret;
00453     }
00454     
00455     
00456     T & operator*() const 
00457         { return *storage; }
00458     T * operator->() const 
00459         { return storage; }
00460 
00461     
00462     
00463     void destroy(void) {
00464         delete storage;
00465         storage=0;
00466     }
00467     
00468         void pup(PUP::er &p) {   
00469         PUP_PTR ppr;
00470         ppr.pup(p,storage);
00471         }
00472         friend void operator|(PUP::er &p,CkZeroPtr<T,PUP_PTR> &v) {v.pup(p);}
00473 };
00474 
00475 
00477 template <class T, class PUP_PTR=CkPupAllocatePtr<T> >
00478 class CkPupPtrVec : public CkVec< CkZeroPtr<T, PUP_PTR> > {
00479   public:
00480   typedef CkPupPtrVec<T,PUP_PTR> this_type;
00481   typedef CkVec< CkZeroPtr<T, PUP_PTR> > super;
00482   CkPupPtrVec() {}
00483   CkPupPtrVec(int size) :super(size) {}
00484   
00485   ~CkPupPtrVec() {
00486     for (size_t i=0;i<this->length();i++)
00487       this->operator[] (i).destroy();
00488   }
00489   void pup(PUP::er &p) { pupCkVec(p,*this); }
00490   friend void operator|(PUP::er &p,this_type &v) {v.pup(p);}
00491 };
00492 
00494 template <class T>
00495 class CkPupAblePtrVec : public CkVec< CkZeroPtr<T, CkPupAblePtr<T> > > {
00496  public:
00497     typedef CkPupAblePtrVec<T> this_type;
00498     typedef CkVec< CkZeroPtr<T, CkPupAblePtr<T> > > super;
00499     CkPupAblePtrVec() {}
00500     CkPupAblePtrVec(int size) :super(size) {}
00501     CkPupAblePtrVec(const this_type &t) {
00502         copy_from(t);
00503     }
00504     this_type &operator=(const this_type &t) {
00505         destroy();
00506         copy_from(t);
00507         return *this;
00508     }
00509     void copy_from(const this_type &t) {
00510         for (size_t i=0;i<t.length();i++)
00511             this->push_back((T *)t[i]->clone());
00512     }
00513     void destroy(void) {
00514         for (size_t i=0;i<this->length();i++)
00515             this->operator[] (i).destroy();
00516         this->length()=0;
00517     }
00518     ~CkPupAblePtrVec() {
00519         destroy();
00520     }
00521     void pup(PUP::er &p) { pupCkVec(p,*this); }
00522     friend void operator|(PUP::er &p,this_type &v) {v.pup(p);}
00523 };
00524 
00525 #define MAXMSGS 32
00526 
00527 
00528 template <class T>
00529 class SafePool {
00530   protected:
00531     int num;
00532     T msgs[MAXMSGS];
00533     typedef T (*allocFn)();
00534     typedef void (*freeFn)(T);
00535     typedef void (*resetFn)(T);
00536     allocFn allocfn;
00537     freeFn  freefn;
00538     resetFn resetfn;
00539   public:
00540     SafePool(allocFn _afn, freeFn _ffn, resetFn _rfn=NULL): allocfn(_afn), freefn(_ffn), resetfn(_rfn) {
00541       for(int i=0;i<MAXMSGS;i++)
00542         msgs[i] = allocfn();
00543       num = MAXMSGS;
00544     }
00545     T get(void) {
00546       
00547       if (CmiImmIsRunning()) return allocfn();
00548       return (num ? msgs[--num] : allocfn());
00549     }
00550     void put(T m) {
00551       if (num==MAXMSGS || CmiImmIsRunning())
00552         freefn(m);
00553       else {
00554         if (resetfn!=NULL) resetfn(m);
00555         msgs[num++] = m;
00556       }
00557     }
00558 };
00559 
00574 template <class T>
00575 class CkPagedVector : private CkNoncopyable {
00580     enum {pageSize=256u};
00581     T **pages;
00582     int nPages;
00583     void allocatePages(int nEntries) {
00584         nPages=(nEntries+pageSize-1)/pageSize; 
00585         pages=new T*[nPages];
00586         for (int pg=0;pg<nPages;pg++) pages[pg]=0;
00587     }
00588     void allocatePage(int pg) {
00589         T *np=new T[pageSize];
00590         
00591         for (int of=0;of<pageSize;of++) np[of]=T();
00592         pages[pg]=np;
00593     }
00594 public:
00595     CkPagedVector() :pages(0), nPages(0) {}
00596     CkPagedVector(int nEntries) {init(nEntries);}
00597     ~CkPagedVector() {
00598         for (int pg=0;pg<nPages;pg++) 
00599             if (pages[pg]) 
00600                 delete[] pages[pg];
00601         delete[] pages;
00602     }
00603     void init(int nEntries) {
00604         allocatePages(nEntries);
00605     }
00606     
00607     inline T &operator[] (unsigned int i) {
00608         
00609         
00610         int pg=i/pageSize; 
00611         int of=i%pageSize;
00612         if (pages[pg]==NULL) allocatePage(pg);
00613         return pages[pg][of];
00614     }
00615     
00616         inline T get (unsigned int i) {
00617         int pg=i/pageSize; 
00618         int of=i%pageSize;
00619                 return pages[pg]==NULL? T():pages[pg][of];
00620         }
00621 
00622     void pupPage(PUP::er &p,int pg) {
00623         if (p.isUnpacking()) allocatePage(pg);
00624         for (int of=0;of<pageSize;of++) 
00625             p|pages[pg][of];
00626     }
00627     void pup(PUP::er &p) {
00628         int pg;
00629         p|nPages;
00630         if (!p.isUnpacking()) 
00631         { 
00632             for (pg=0;pg<nPages;pg++) 
00633             if (pages[pg]) {
00634                 p|pg;
00635                 pupPage(p,pg);
00636             }
00637             pg=-1;
00638             p|pg;
00639         } else 
00640         { 
00641             allocatePages(nPages*pageSize);
00642             
00643             p|pg;
00644             while (pg!=-1) {
00645                 pupPage(p,pg);
00646                 p|pg;
00647             }
00648         }
00649     }
00650 };
00651 
00652 
00653 
00654 
00655 
00656 template <class T>
00657 class CkCompactVec : private CkSTLHelper<T> {
00658     typedef CkVec<T> this_type;
00659 
00660     T *block; 
00661     size_t blklen; 
00662     size_t len; 
00663     size_t offset;      
00664     size_t lastnull;    
00665     void makeBlock(int blklen_,int len_,int offset_=0,int lastnull_=-1) {
00666        if (blklen_==0) block=NULL; 
00667        else {
00668          block=new T[blklen_];
00669          if (block == NULL) blklen_=len_= 0;
00670        }
00671        blklen=blklen_; len=len_;
00672        offset=offset_; lastnull=lastnull_;
00673     }
00674     void freeBlock(void) {
00675        len=0; blklen=0;
00676        delete[] block; 
00677        block=NULL;
00678        offset=0; lastnull=-1;
00679     }
00680     void copyFrom(const this_type &src) {
00681        makeBlock(src.blklen, src.len, src.offset, src.lastnull);
00682        elementCopy(block,src.block,blklen);
00683     }
00684   public:
00685     CkCompactVec(): block(NULL), blklen(0), len(0), offset(0), lastnull(-1) {}
00686     ~CkCompactVec() { freeBlock(); }
00687     CkCompactVec(const this_type &src) {copyFrom(src);}
00688     CkCompactVec(int size) { makeBlock(size,size); } 
00689     CkCompactVec(int size, int used) { makeBlock(size,used); } 
00690     CkCompactVec(const CkSkipInitialization &skip) {}
00691     this_type &operator=(const this_type &src) {
00692       freeBlock();
00693       copyFrom(src);
00694       return *this;
00695     }
00696 
00697     size_t &length(void) { return len; }
00698     size_t length(void) const {return len;}
00699     T *getVec(void) { return block; }
00700     const T *getVec(void) const { return block; }
00701     
00702     T& operator[](size_t n) {
00703       CmiAssert(n<len && n>=offset);
00704       return block[n-offset]; 
00705     }
00706     
00707     const T& operator[](size_t n) const { 
00708       CmiAssert(n-offset<len);
00709       return n<offset?NULL:block[n-offset]; 
00710     }
00711     
00713     int reserve(size_t newcapacity) {
00714       if (newcapacity-offset<=blklen) return 1; 
00715       T *oldBlock=block; 
00716       makeBlock(newcapacity-offset-lastnull,len,offset,lastnull);
00717       
00718       elementCopy(block,oldBlock+lastnull+1,len-offset-lastnull-1);
00719       offset+=lastnull+1;   
00720       lastnull=-1;
00721       delete[] oldBlock; 
00722       return 1;
00723     }
00724     inline size_t capacity(void) const {return blklen;}
00725 
00727     int resize(size_t newsize) {
00728       if (!reserve(newsize)) return 0;
00729       len=newsize;
00730       return 1;
00731     }
00732 
00734     void free() {
00735       freeBlock();
00736     }
00737 
00738     
00739     void growAtLeast(size_t pos) {
00740       if (pos>=blklen+offset) reserve(pos*2+16);
00741     }
00742     void insert(size_t pos, const T &elt) {
00743       if (pos>=len) { 
00744         growAtLeast(pos);
00745         len=pos+1;
00746       }
00747       block[pos-offset] = elt;
00748     }
00749     void shrink() {
00750       for (size_t i=offset+lastnull+1; i<len; i++)
00751         block[i-offset-lastnull-1] = block[i-offset];
00752       offset+=lastnull+1; lastnull=-1;
00753       
00754     }
00755     void remove(size_t pos) {
00756       if (pos < offset) {
00757         CmiAbort("CkVec ERROR: try to remove non-exisitent element.\n\n");
00758         return;
00759       }
00760       if (pos>=len) 
00761     {
00762       CmiAbort("CkVec ERROR: out of bounds\n\n"); 
00763       return;
00764     }
00765       if (lastnull >= blklen/2) {   
00766         for (size_t i=offset+lastnull+1; i<pos; i++)
00767           block[i-offset-lastnull-1] = block[i-offset];
00768         for (size_t i=pos; i<len-1; i++)
00769           block[i-offset-lastnull-1] = block[i-offset+1];
00770         offset+=lastnull+1; lastnull=-1;
00771       }
00772       else {
00773       for (size_t i=pos; i<len-1; i++)
00774         block[i-offset] = block[i-offset+1];
00775       if (pos-offset==lastnull+1) lastnull++;
00776       }
00777       len--;
00778     }
00779     void marknull(size_t pos) {
00780       block[pos-offset] = T(0);
00781       if (pos == offset+lastnull+1) lastnull++;
00782       if (lastnull >= blklen/4) shrink();
00783     }
00784     void removeAll() {
00785       len = 0;
00786       offset=0; lastnull=-1;
00787     }
00788 
00789     void clear()
00790     {
00791     freeBlock();
00792     }
00793 
00794     void insertAtEnd(const T &elt) {insert(length(),elt);}
00795 
00796 
00797     void push_back(const T &elt) {insert(length(),elt);}
00798     size_t size(void) const {return len;}
00799 
00800 
00801     size_t push_back_v(const T &elt) {insert(length(),elt);return length()-1;}
00802 
00803  
00804 
00805     
00806     int pupbase(PUP::er &p) {
00807        size_t l=len;
00808        p(l);
00809        if (p.isUnpacking()) resize(l); 
00810        return l;
00811     }
00812     
00813 #ifdef _MSC_VER
00814 
00815 
00816      void pup(PUP::er &p) {
00817         pupCkVec(p,*this);
00818         p|offset;
00819         p|lastnull;
00820      }
00821 #endif
00822 
00823 };
00824 
00825 
00826 #endif