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