Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

allocators.hpp

Go to the documentation of this file.
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     //must be a power of 2
00047     static const size_t alignment=16;
00048 #ifdef __SSE__
00049     //    typedef int _v2q_t __attribute__((__mode__(V2DI)));
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       //  memset(p,0,len<<2);
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       //zero remaining
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       //round up the length to a multiple of alignment
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       //skip the size of a void* and align
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       //make place for the saved pointer
00104       void** saveptr=reinterpret_cast<void**>(nb);
00105       saveptr--;
00106       //save the original pointer
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       //round up the length to a multiple of alignment
00115       //zero the array
00116       // **** MMX/SSE memory zero routine!
00117       //      memset(array,0,tots);
00118       //      bzero(array,tots);
00119     }
00120     
00121 
00123     template<class T> static inline void DINLINE zero(T* array, size_t size) {
00124       // **** MMX/SSE memory zero routine!
00125       //      memset(array,0,tots);
00126       //      bzero(array,tots);        
00127       mymemzeroa(array,size*sizeof(T));
00128     }
00129 
00131     template<class T> static void NOINLINE free(T* array) {
00132       //look up the saved pointer
00133       void** ob = reinterpret_cast<void**>(array);
00134       ob--;
00135       //free
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       // **** MMX/SSE memory zero routine
00153       //bzero(array,size*sizeof(T));
00154       mymemzerola(array,size*sizeof(T));
00155     }
00156 
00157   };//class alignalloc
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       //alignalloc::alloc(cbigblk,bigblklen);
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       //alignalloc::alloc(cbigblk,bigblklen);
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        //alignalloc::free(*i);
00220 
00221     }
00222     //be prepared for another call of freeall() or allocate()
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 /*template<class T, int bigblklen> class singlealloc {
00265 public:
00266   singlealloc() :freelist(NULL){
00267   }
00268 
00270   T* DINLINE allocate() {
00271     if (freelist) {
00272       T* ret = (T*)freelist;
00273       freelist=freelist->next;
00274       return ret;
00275     }
00276     return (T*) allocator.allocate();
00277   }
00278 
00280   void freeall() {
00281     freelist=NULL;
00282     allocator.freeall();
00283   }
00284 
00286   void free(T* data) {
00287     newdata_t *d=static_cast<newdata_t*>(data);
00288     d->next=freelist;
00289     freelist=d;
00290   }
00291 
00292   ~singlealloc() {
00293     freeall();
00294   }
00295 
00296 private:
00298   typedef union newdata_t {
00299     T data;
00300     newdata_t *next;
00301   } newdata_t;
00302 
00304   typedef blockalloc<newdata_t, bigblklen> realalloc_t;
00305   
00307   realalloc_t allocator;
00308   
00310   T* freelist;
00311 }; //class singlealloc
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 }; //class singlealloc
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   }; //singleunionwrapper
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   }; //singlestructwrapper
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])) { //double parenthesis to avoid warnings
00420 >>>>>>> 1.5
00421       //we have a cached block
00422       T** d=(T**)ret;
00423       freelists[size]=*d;
00424       return ret;
00425     } else {
00426       //allocate a new block      
00427       size_t ns=BLOCKLEN(size);
00428       return thealloc.allocate(ns);
00429     }
00430   }//allocate
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   }//free
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   }; //class debugblockstack
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         //allocate block
00510         length+=length>>1;//allocate somewhat more memory
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   }; //class blockstack
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   };//class stacksingleblock
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   };//class stackmultiblock
00646 
00647 
00648 } //namespace bracz
00649 
00650 
00651 #endif //ALLOCATORS_HPP_050402

Generated on Sun Sep 17 17:50:37 2006 for FIM environment by  doxygen 1.4.4