00001 
00009 #ifndef ALLOCATORS_HPP_050402
00010 #define ALLOCATORS_HPP_050402
00011 
00012 #include <list>
00013 #include <vector>
00014 #include <stack>
00015 
00016 #include <malloc.h>
00017 #include <string.h>
00018 #include <stdlib.h>
00019 
00020 #ifdef __SSE__
00021 #include <xmmintrin.h>
00022 #endif
00023 
00024 #include "common/log.h"
00025 
00026 #include <inttypes.h>
00027 
00028 
00029 
00030 
00032 template<class T> class NewWrapperAlloc
00033 {
00034   public:
00035    NewWrapperAlloc(){}
00036    T* DINLINE allocate(){
00037       return new T();
00038    }
00039    void free(T* data){
00040       delete data;
00041    }   
00042 };
00043 
00044 namespace bracz {
00045   class alignalloc {
00046     
00047     static const size_t alignment=16;
00048 #ifdef __SSE__
00049     
00050     typedef __m128i _v2q_t;
00051 
00052     static inline void DINLINE mymemzeroa(void *p,size_t len) {
00053       register int l=((len)+15)>>4;
00054       register _v2q_t a = {0,0};
00055       register _v2q_t *b=(_v2q_t*)p;
00056       while (l) {
00057         *b=a;
00058         ++b;
00059         --l;
00060       }
00061       
00062     }
00063 
00064     static inline void DINLINE mymemzerola(void *p,size_t len) {
00065       register int l=((len))>>4;
00066       register _v2q_t a = {0,0};
00067       register _v2q_t *b=(_v2q_t*)p;
00068       while (l) {
00069         *b=a;
00070         ++b;
00071         --l;
00072       }
00073       
00074       if (len & 15) {
00075         bzero(b,len & 15);
00076       }
00077     }
00078 
00079 #else 
00080     #warning Enable SSE instructions to gain speed.
00081 
00082 #define mymemzeroa bzero
00083 #define mymemzerola bzero
00084     
00085 #endif
00086   public:
00087 
00089     template<class T> static void DINLINE alloc(T*& array, size_t size) {
00090       size_t tots=size*sizeof(T);
00091       
00092       tots+=2*(alignment-1)+sizeof(void*);
00093       void * base=malloc(tots);
00094       if(!base) {
00095         log_err(0,"Memory allocation failed.");
00096         abort();
00097       }
00098       
00099       uintptr_t nb = reinterpret_cast<uintptr_t>(base);
00100       nb+=sizeof(void*)+alignment-1;
00101       nb&=~(alignment-1);
00102       array=reinterpret_cast<T*>(nb);
00103       
00104       void** saveptr=reinterpret_cast<void**>(nb);
00105       saveptr--;
00106       
00107       *saveptr=base;
00108     }
00109 
00111     template<class T> static void DINLINE allocz(T*& array, size_t size) {
00112       alloc(array,size);
00113       mymemzeroa(array,size*sizeof(T));
00114       
00115       
00116       
00117       
00118       
00119     }
00120     
00121 
00123     template<class T> static inline void DINLINE zero(T* array, size_t size) {
00124       
00125       
00126       
00127       mymemzeroa(array,size*sizeof(T));
00128     }
00129 
00131     template<class T> static void NOINLINE free(T* array) {
00132       
00133       void** ob = reinterpret_cast<void**>(array);
00134       ob--;
00135       
00136       ::free(*ob);
00137     }
00138 
00140     template<class T> static void DINLINE freeifnonnull(T* array) {
00141       if (array)
00142         alignalloc::free(array);
00143     }
00144     
00146 
00151     template<class T> static inline void DINLINE zerola(T* array, size_t size) {
00152       
00153       
00154       mymemzerola(array,size*sizeof(T));
00155     }
00156 
00157   };
00158 
00159 
00178 template<class T, int bigblklen> class blockalloc {
00179 public:
00180   blockalloc() {
00181     cbigblk=NULL;
00182     cfree=0;
00183   }
00184 
00186   T* DINLINE allocate(int ns) {
00187     if ((int)cfree<ns) {
00188       cfree=bigblklen;
00189       cbigblk=new T[bigblklen];
00190       
00191       bigblocks.push_back(cbigblk);
00192     }
00193     T* ret=cbigblk;
00194     cfree-=ns;
00195     cbigblk+=ns;
00196     return ret;
00197   }
00198 
00200   T* DINLINE allocate() {
00201     if (!cfree) {
00202       cfree=bigblklen;
00203       cbigblk=new T[bigblklen];
00204       
00205 
00206       bigblocks.push_back(cbigblk);
00207     }
00208     T* ret=cbigblk;
00209     --cfree;
00210     ++cbigblk;
00211     return ret;
00212   }
00213 
00215   void freeall() {
00216     for (TYPENAME bigblocks_t::iterator i=bigblocks.begin();
00217          i!=bigblocks.end(); ++i) {
00218        delete [] *i;
00219        
00220 
00221     }
00222     
00223     bigblocks.clear();
00224     cbigblk=NULL;
00225     cfree=0;
00226   }
00227 
00228   ~blockalloc() {
00229     freeall();
00230   }
00231 
00232 private:
00233   typedef std::list<T*> bigblocks_t; 
00235   bigblocks_t bigblocks;
00236   
00238   T* cbigblk;
00239   
00241   size_t cfree;
00242 };
00243 
00264 
00265 
00266 
00267 
00268 
00270 
00271 
00272 
00273 
00274 
00275 
00276 
00277 
00278 
00280 
00281 
00282 
00283 
00284 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00298 
00299 
00300 
00301 
00302 
00304 
00305 
00307 
00308 
00310 
00311 
00312 
00313 
00314 template<class WRP, int bigblklen> class singlewrpalloc {
00315 public:
00316   typedef typename WRP::data_t data_t;
00317   singlewrpalloc() :freelist(NULL){
00318   }
00319 
00321   data_t* DINLINE allocate() {
00322     if (freelist) {
00323       WRP* ret = freelist;
00324       freelist=freelist->next;
00325       return ret->getData();
00326     }
00327     return allocator.allocate()->getData();
00328   }
00329 
00331   void freeall() {
00332     freelist=NULL;
00333     allocator.freeall();
00334   }
00335 
00337   void free(data_t* data) {
00338     WRP *d=(WRP*) data;
00339     d->next=freelist;
00340     freelist=d;
00341   }
00342 
00343   ~singlewrpalloc() {
00344     freeall();
00345   }
00346 
00347 private:
00349   typedef WRP newdata_t;
00350 
00352   typedef blockalloc<WRP, bigblklen> realalloc_t;
00353   
00355   realalloc_t allocator;
00356   
00358   WRP* freelist;
00359 }; 
00360 
00361 
00362   template<class T> class singleunionwrapper {
00363   public:
00364     typedef T data_t;
00365     union {
00366       T data;
00367       singleunionwrapper *next;
00368     };
00369     T* DINLINE getData() {
00370       return (T*) this;
00371     }
00372     singleunionwrapper *& DINLINE getNext() {
00373       return next;
00374     }
00375   }; 
00376 
00377   template<class T> class singlestructwrapper : T {
00378   public:
00379     typedef T data_t;
00380 
00381     singlestructwrapper *next;
00382 
00383     T* DINLINE getData() {
00384       return this;
00385     }
00386     singlestructwrapper *& DINLINE getNext() {
00387       return next;
00388     }
00389   }; 
00390 
00391   template<class T, int bigblklen> class singlesalloc: public singlewrpalloc<singlestructwrapper<T>, bigblklen> {};
00392 
00393   template<class T, int bigblklen> class singleualloc: public singlewrpalloc<singleunionwrapper<T>, bigblklen> {};
00394 
00395 
00404 template<class T,int base, int bigblklen> class arrayalloc{
00405 public:
00406   static  size_t DINLINE BLOCKLEN(int size)  {
00407     return (base << size);
00408   }
00409 
00411   T* DINLINE allocate(unsigned int size) {
00412     if (freelists.size()<=size) {
00413       freelists.resize(size+1);
00414     }
00415     T* ret;
00416 <<<<<<< allocators.hpp
00417     if ((ret=freelists[size])) {
00418 =======
00419     if ((ret=freelists[size])) { 
00420 >>>>>>> 1.5
00421       
00422       T** d=(T**)ret;
00423       freelists[size]=*d;
00424       return ret;
00425     } else {
00426       
00427       size_t ns=BLOCKLEN(size);
00428       return thealloc.allocate(ns);
00429     }
00430   }
00431 
00433   void DINLINE free(T* data,unsigned int size) {
00434     if (freelists.size()<=size) {
00435       freelists.resize(size+1);
00436     }
00437     T** d=(T**)data;
00438     *d=freelists[size];
00439     freelists[size]=data;
00440   }
00441   
00442   
00443   arrayalloc() :thealloc(){
00444   }
00445 
00446 private:
00447 
00449   std::vector<T*> freelists;
00450 
00452   blockalloc<T,bigblklen> thealloc;
00453 
00454 };
00455 
00456 
00457 
00458 
00464   template <class BLOCK> class debugblockstack {
00465   public:
00466     void DINLINE pushAndGetBlock(size_t length, typename BLOCK::dataget_t &d) {
00467       blocks.push(length);
00468       getCurrBlock().getData(d);
00469     }
00470 
00471     void DINLINE freeBlock() {
00472       if (blocks.empty()) {
00473         log_err(0,"freeBlock when stack is empty!");
00474       }
00475       blocks.pop();
00476     }
00477 
00478     BLOCK& getCurrBlock() {
00479       return blocks.top();
00480     }
00481 
00482     ~debugblockstack() {
00483       while (!blocks.empty()) {
00484         log_dbg(0,"Freeing block");
00485         blocks.top().free();
00486         blocks.pop();
00487       }
00488     }
00489 
00490   private:
00491     class smemblock_t : public BLOCK {
00492     public:
00493       size_t length;
00494       smemblock_t(size_t _length): BLOCK(_length),length(_length){}
00495     };
00496 
00498     typedef std::stack<smemblock_t> blocklist_t;
00499     
00501     blocklist_t blocks;
00502 
00503   }; 
00504 
00505   template <class BLOCK> class blockstack {
00506   public:
00507     void DINLINE ensureCurrBlock(size_t length) {
00508       if ((currblock==blocks.end())||(length>currblock->length)) {
00509         
00510         length+=length>>1;
00511         smemblock_t newblock(length);
00512         blocks.insert(currblock,newblock);
00513         --currblock;
00514       }
00515     }
00516 
00517     void DINLINE stepBlock() {
00518       ++currblock;
00519     }
00520 
00521     void DINLINE pushAndGetBlock(size_t length, typename BLOCK::dataget_t &d) {
00522       ensureCurrBlock(length);
00523       getCurrBlock().getData(d);
00524       stepBlock();
00525     }
00526 
00527     void DINLINE freeBlock() {
00528       --currblock;
00529     }
00530 
00531     BLOCK& getCurrBlock() {
00532       return *currblock;
00533     }
00534 
00535     blockstack() {
00536       currblock=blocks.end();
00537     }
00538 
00539     ~blockstack() {
00540       for (typename blocklist_t::iterator it=blocks.begin();it!=blocks.end();++it) {
00541         it->free();
00542       }
00543     }
00544 
00545   private:
00546     class smemblock_t : public BLOCK {
00547     public:
00548       size_t length;
00549       smemblock_t(size_t _length): BLOCK(_length),length(_length){}
00550     };
00551 
00553     typedef std::list<smemblock_t> blocklist_t;
00554     
00556     blocklist_t blocks;
00557     
00559     TYPENAME blocklist_t::iterator currblock;
00560 
00561   }; 
00562 
00563 
00579   template<class T, bool PREZERO> class stacksingleblock {
00580   public:
00581     stacksingleblock(size_t length) {
00582       if (PREZERO) {
00583         alignalloc::allocz(data,length);
00584       } else {
00585         alignalloc::alloc(data,length);
00586       }
00587     }
00588 
00589     typedef T* dataget_t;
00590 
00591     void getData(dataget_t & r) {
00592       r=data;
00593     }
00594     
00595     void free() {
00596       alignalloc::freeifnonnull(data);
00597       data=NULL;
00598     }
00599 
00600   private:
00601     T* data;
00602   };
00603 
00621   template<class T, bool PREZERO, class PARENT> class stackmultiblock : PARENT {
00622   public:
00623     stackmultiblock(size_t length) : PARENT(length) {
00624       if (PREZERO) {
00625         alignalloc::allocz(data,length);
00626       } else {
00627         alignalloc::alloc(data,length);
00628       }
00629     }
00630 
00631     typedef std::pair<T*, typename PARENT::dataget_t> dataget_t;
00632     void DINLINE getData(dataget_t &r) {
00633       PARENT::getData(r.second);
00634       r.first=data;
00635     }
00636 
00637     void free() {
00638       PARENT::free();
00639       alignalloc::freeifnonnull(data);
00640       data=NULL;
00641     }
00642 
00643   private:
00644     T* data;
00645   };
00646 
00647 
00648 } 
00649 
00650 
00651 #endif //ALLOCATORS_HPP_050402