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