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 elementCopy(newblk,block+first,blklen-first);
00051 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 void insert(int pos, const T &elt) {
00089 while(len==blklen || pos>=blklen) _expand();
00090 for (int i=len; i>pos; i--)
00091 block[(i+first)&mask] = block[(i-1+first)&mask];
00092 block[(pos+first)&mask] = elt;
00093 if (pos > len) len = pos+1;
00094 else len++;
00095 }
00096
00097 T remove(int pos) {
00098 if (pos >= len) return T(0);
00099 T ret = block[(pos+first)&mask];
00100 for (int i=pos; i<len-1; i++)
00101 block[(i+first)&mask] = block[(i+1+first)&mask];
00102 len--;
00103 return ret;
00104 }
00105
00106 void removeFrom(int pos) {
00107 CmiAssert (pos < len && pos>=0);
00108 len = pos;
00109 }
00110
00111 T& operator[](size_t n)
00112 {
00113 n=(n+first)&mask;
00114 return block[n];
00115 }
00116
00117 T* getArray(void) {
00118 T *newblk = new T[len];
00119 int i,j;
00120 for(i=0,j=first;i<len;i++){
00121 newblk[i] = block[j];
00122 j = (j+1)&mask;
00123 }
00124 return newblk;
00125 }
00126 #ifdef _MSC_VER
00127
00128
00129 void pup(PUP::er &p) {
00130 pupCkQ(p,*this);
00131 }
00132 #endif
00133 };
00134
00136 template <class T>
00137 inline void pupCkQ(PUP::er &p,CkQ<T> &q) {
00138 p.syncComment(PUP::sync_begin_array);
00139 int l=q.length();
00140 p|l;
00141 for (int i=0;i<l;i++) {
00142 p.syncComment(PUP::sync_item);
00143 if (p.isUnpacking()) {
00144 T t;
00145 p|t;
00146 q.enq(t);
00147 } else {
00148 p|q[i];
00149 }
00150 }
00151 p.syncComment(PUP::sync_end_array);
00152 }
00153
00154 #ifndef _MSC_VER
00156 template <class T>
00157 inline void operator|(PUP::er &p,CkQ<T> &q) {pupCkQ(p,q);}
00158 #endif
00159
00163 class CkSkipInitialization {};
00164
00165
00166 template <class T> class CkVec;
00167 template <class T> void pupCkVec(PUP::er &p,CkVec<T> &vec);
00168
00174 template <class T>
00175 class CkVec : private CkSTLHelper<T> {
00176 typedef CkVec<T> this_type;
00177
00178 T *block;
00179 int blklen;
00180 int len;
00181 void makeBlock(int blklen_,int len_) {
00182 if (blklen_==0) block=NULL;
00183 else {
00184 block=new T[blklen_];
00185 if (block == NULL) blklen_=len_= 0;
00186 }
00187 blklen=blklen_; len=len_;
00188 }
00189 void freeBlock(void) {
00190 len=0; blklen=0;
00191 delete[] block;
00192 block=NULL;
00193 }
00194 void copyFrom(const this_type &src) {
00195 makeBlock(src.blklen, src.len);
00196 elementCopy(block,src.block,blklen);
00197 }
00198 public:
00199 CkVec(): block(NULL), blklen(0), len(0) {}
00200 ~CkVec() { freeBlock(); }
00201 CkVec(const this_type &src) {copyFrom(src);}
00202 CkVec(int size) { makeBlock(size,size); }
00203 CkVec(int size, int used) { makeBlock(size,used); }
00204 CkVec(const CkSkipInitialization &skip) {}
00205 this_type &operator=(const this_type &src) {
00206 freeBlock();
00207 copyFrom(src);
00208 return *this;
00209 }
00210
00211 int &length(void) { return len; }
00212 int length(void) const {return len;}
00213 T *getVec(void) { return block; }
00214 const T *getVec(void) const { return block; }
00215
00216 T& operator[](size_t n) {
00217 #if CMK_PARANOID
00218 if (n >= len || n < 0)
00219 CmiAbort("CkVec Out Of Bounds\n\n");
00220 #endif
00221 return block[n];
00222 }
00223
00224 const T& operator[](size_t n) const {
00225 #if CMK_PARANOID
00226 if (n >= len || n < 0)
00227 CmiAbort("CkVec Out Of Bounds\n\n");
00228 #endif
00229 return block[n];
00230 }
00231
00233 int reserve(int newcapacity) {
00234 if (newcapacity<=blklen) return 1;
00235 T *oldBlock=block;
00236 makeBlock(newcapacity,len);
00237 if (newcapacity != blklen) return 0;
00238 elementCopy(block,oldBlock,len);
00239 delete[] oldBlock;
00240 return 1;
00241 }
00242 inline int capacity(void) const {return blklen;}
00243
00245 int resize(int newsize) {
00246 if (!reserve(newsize)) return 0;
00247 len=newsize;
00248 return 1;
00249 }
00250
00252 void free() {
00253 freeBlock();
00254 }
00255
00256
00257 void growAtLeast(int pos) {
00258 if (pos>=blklen) reserve(pos*2+16);
00259 }
00260 void insert(int pos, const T &elt) {
00261 if (pos>=len) {
00262 growAtLeast(pos);
00263 len=pos+1;
00264 }
00265 block[pos] = elt;
00266 }
00267 void remove(int pos) {
00268 if (pos<0 || pos>=len)
00269 {
00270 CmiAbort("CkVec ERROR: out of bounds\n\n");
00271 return;
00272 }
00273 for (int i=pos; i<len-1; i++)
00274 block[i] = block[i+1];
00275 len--;
00276 }
00277 void removeAll() {
00278 len = 0;
00279 }
00280 void insertAtEnd(const T &elt) {insert(length(),elt);}
00281
00282
00283 void push_back(const T &elt) {insert(length(),elt);}
00284 int size(void) const {return len;}
00285
00286
00287 int push_back_v(const T &elt) {insert(length(),elt);return length()-1;}
00288
00289
00290
00291
00292 int pupbase(PUP::er &p) {
00293 int l=len;
00294 p(l);
00295 if (p.isUnpacking()) resize(l);
00296 return l;
00297 }
00298
00299 #ifdef _MSC_VER
00300
00301
00302 void pup(PUP::er &p) {
00303 pupCkVec(p,*this);
00304 }
00305 #endif
00306
00307 inline void quickSort(){
00308 q_sort(0, len - 1,128);
00309 }
00310
00311 inline void quickSort(int changeOverSize){
00312 q_sort(0,len-1,changeOverSize);
00313 }
00314
00315
00316 inline void q_sort(int left, int right,int changeOverSize){
00317 int l_hold, r_hold;
00318 int pivot;
00319
00320 if(left >= right)
00321 return;
00322
00323
00324 int mid = (left+right)/2;
00325 T temp = block[mid];
00326 block[mid] = block[left];
00327 block[left] = temp;
00328
00329 l_hold = left;
00330 r_hold = right;
00331 pivot = left;
00332 if(right - left <= changeOverSize){
00333 bubbleSort(left,right);
00334 return;
00335 }
00336 while (left < right)
00337 {
00338 while ((block[right] >= block[pivot]) && (left < right))
00339 right--;
00340 while ((block[left] <= block[pivot]) && (left < right))
00341 left++;
00342
00343 if(left < right){
00344 T val = block[left];
00345 block[left] = block[right];
00346 block[right] = val;
00347 }
00348 }
00349 T val = block[left];
00350 block[left] = block[pivot];
00351 block[pivot] = val;
00352 pivot = left;
00353 left = l_hold;
00354 right = r_hold;
00355 if (left < pivot)
00356 q_sort(left, pivot-1,changeOverSize);
00357 if (right > pivot)
00358 q_sort(pivot+1, right,changeOverSize);
00359 }
00360
00361 inline void bubbleSort(int left,int right){
00362 for(int i=left;i<=right;i++){
00363 for(int j=i+1;j<=right;j++){
00364 if(block[i] >= block[j]){
00365 T val = block[i];
00366 block[i] = block[j];
00367 block[j] = val;
00368 }
00369 }
00370 }
00371 }
00372
00373 };
00374
00376 template <class T>
00377 inline void pupCkVec(PUP::er &p,CkVec<T> &vec) {
00378 int len=vec.pupbase(p);
00379 if (len) PUParray(p,&vec[0],len);
00380 }
00381
00382 #ifndef _MSC_VER
00384 template <class T>
00385 inline void operator|(PUP::er &p,CkVec<T> &vec) {pupCkVec(p,vec);}
00386 #endif
00387
00388
00389 #define CkPupBasicVec CkVec
00390
00393 template <class T>
00394 class CkPupAlwaysAllocatePtr {
00395 public:
00396 void pup(PUP::er &p,T *&ptr) {
00397 if (p.isUnpacking()) ptr=new T;
00398 p|*ptr;
00399 }
00400 };
00401
00404 template <class T>
00405 class CkPupAllocatePtr {
00406 public:
00407 void pup(PUP::er &p,T *&ptr) {
00408 int isNull=(ptr==0);
00409 p(isNull);
00410 if (isNull) ptr=0;
00411 else {
00412 if (p.isUnpacking()) ptr=new T;
00413 p|*ptr;
00414 }
00415 }
00416 };
00417
00419 template <class T>
00420 class CkPupAblePtr {
00421 public:
00422 void pup(PUP::er &p,T *&ptr) {
00423 p|ptr;
00424 }
00425 };
00426
00428 template <class T, class PUP_PTR=CkPupAllocatePtr<T> >
00429 class CkZeroPtr {
00430 protected:
00431 T *storage;
00432 public:
00433 CkZeroPtr() {storage=0;}
00434 CkZeroPtr(T *sto) {storage=sto;}
00435 CkZeroPtr(const CkZeroPtr &src) { storage=src.storage; }
00436 CkZeroPtr &operator=(const CkZeroPtr &src) {
00437 storage=src.storage; return *this;
00438 }
00439 T *operator=(T *sto) {storage=sto; return sto;}
00440
00441 operator T* () const {return storage;}
00442
00443 T *release() {
00444 T *ret=storage; storage=0; return ret;
00445 }
00446
00447
00448 T & operator*() const
00449 { return *storage; }
00450 T * operator->() const
00451 { return storage; }
00452
00453
00454
00455 void destroy(void) {
00456 delete storage;
00457 storage=0;
00458 }
00459
00460 void pup(PUP::er &p) {
00461 PUP_PTR ppr;
00462 ppr.pup(p,storage);
00463 }
00464 friend void operator|(PUP::er &p,CkZeroPtr<T,PUP_PTR> &v) {v.pup(p);}
00465 };
00466
00467
00469 template <class T, class PUP_PTR=CkPupAllocatePtr<T> >
00470 class CkPupPtrVec : public CkVec< CkZeroPtr<T, PUP_PTR> > {
00471 public:
00472 typedef CkPupPtrVec<T,PUP_PTR> this_type;
00473 typedef CkVec< CkZeroPtr<T, PUP_PTR> > super;
00474 CkPupPtrVec() {}
00475 CkPupPtrVec(int size) :super(size) {}
00476
00477 ~CkPupPtrVec() {
00478 for (int i=0;i<this->length();i++)
00479 this->operator[] (i).destroy();
00480 }
00481 void pup(PUP::er &p) { pupCkVec(p,*this); }
00482 friend void operator|(PUP::er &p,this_type &v) {v.pup(p);}
00483 };
00484
00486 template <class T>
00487 class CkPupAblePtrVec : public CkVec< CkZeroPtr<T, CkPupAblePtr<T> > > {
00488 public:
00489 typedef CkPupAblePtrVec<T> this_type;
00490 typedef CkVec< CkZeroPtr<T, CkPupAblePtr<T> > > super;
00491 CkPupAblePtrVec() {}
00492 CkPupAblePtrVec(int size) :super(size) {}
00493 CkPupAblePtrVec(const this_type &t) {
00494 copy_from(t);
00495 }
00496 this_type &operator=(const this_type &t) {
00497 destroy();
00498 copy_from(t);
00499 return *this;
00500 }
00501 void copy_from(const this_type &t) {
00502 for (int i=0;i<t.length();i++)
00503 push_back((T *)t[i]->clone());
00504 }
00505 void destroy(void) {
00506 for (int i=0;i<this->length();i++)
00507 this->operator[] (i).destroy();
00508 this->length()=0;
00509 }
00510 ~CkPupAblePtrVec() {
00511 destroy();
00512 }
00513 void pup(PUP::er &p) { pupCkVec(p,*this); }
00514 friend void operator|(PUP::er &p,this_type &v) {v.pup(p);}
00515 };
00516
00517 #define MAXMSGS 32
00518
00519
00520 template <class T>
00521 class SafePool {
00522 protected:
00523 int num;
00524 T msgs[MAXMSGS];
00525 typedef T (*allocFn)();
00526 typedef void (*freeFn)(T);
00527 allocFn allocfn;
00528 freeFn freefn;
00529 public:
00530 SafePool(allocFn _afn, freeFn _ffn): allocfn(_afn), freefn(_ffn) {
00531 for(int i=0;i<MAXMSGS;i++)
00532 msgs[i] = allocfn();
00533 num = MAXMSGS;
00534 }
00535 T get(void) {
00536
00537 if (CmiImmIsRunning()) return allocfn();
00538 return (num ? msgs[--num] : allocfn());
00539 }
00540 void put(T m) {
00541 if (num==MAXMSGS || CmiImmIsRunning())
00542 freefn(m);
00543 else
00544 msgs[num++] = m;
00545 }
00546 };
00547
00562 template <class T>
00563 class CkPagedVector : private CkNoncopyable {
00568 enum {pageSize=256u};
00569 T **pages;
00570 int nPages;
00571 void allocatePages(int nEntries) {
00572 nPages=(nEntries+pageSize-1)/pageSize;
00573 pages=new T*[nPages];
00574 for (int pg=0;pg<nPages;pg++) pages[pg]=0;
00575 }
00576 void allocatePage(int pg) {
00577 T *np=new T[pageSize];
00578
00579 for (int of=0;of<pageSize;of++) np[of]=T();
00580 pages[pg]=np;
00581 }
00582 public:
00583 CkPagedVector() :pages(0), nPages(0) {}
00584 CkPagedVector(int nEntries) {init(nEntries);}
00585 ~CkPagedVector() {
00586 for (int pg=0;pg<nPages;pg++)
00587 if (pages[pg])
00588 delete[] pages[pg];
00589 delete[] pages;
00590 }
00591 void init(int nEntries) {
00592 allocatePages(nEntries);
00593 }
00594
00595 inline T &operator[] (unsigned int i) {
00596
00597
00598 int pg=i/pageSize;
00599 int of=i%pageSize;
00600 if (pages[pg]==NULL) allocatePage(pg);
00601 return pages[pg][of];
00602 }
00603
00604 inline T get (unsigned int i) {
00605 int pg=i/pageSize;
00606 int of=i%pageSize;
00607 return pages[pg]==NULL? T():pages[pg][of];
00608 }
00609
00610 void pupPage(PUP::er &p,int pg) {
00611 if (p.isUnpacking()) allocatePage(pg);
00612 for (int of=0;of<pageSize;of++)
00613 p|pages[pg][of];
00614 }
00615 void pup(PUP::er &p) {
00616 int pg, o;
00617 unsigned int i;
00618 p|nPages;
00619 if (!p.isUnpacking())
00620 {
00621 for (pg=0;pg<nPages;pg++)
00622 if (pages[pg]) {
00623 p|pg;
00624 pupPage(p,pg);
00625 }
00626 pg=-1;
00627 p|pg;
00628 } else
00629 {
00630 allocatePages(nPages*pageSize);
00631 p|pg;
00632 while (pg!=-1) {
00633 pupPage(p,pg);
00634 p|pg;
00635 }
00636 }
00637 }
00638 };
00639
00640
00641 #endif