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