通用C++内存池代码

来源:互联网 发布:响应式博客模板知乎 编辑:程序博客网 时间:2024/05/16 15:51

原理在这里http://blog.csdn.net/kevin_qing/article/details/608891

以前代码找不到了,重写一次。

加上了一些简单的错误检测代码。帮助调试内存问题。

初步代码,还未仔细检查,有bug请留言。

 

//type and macro#include <default.h>//debug 信息constboolDebugQMem=1;structQMemDebugInfo{uint32_tmask;uint32_tsize;byteguard[128-8];};template <bool flag, typename T, typename U>struct TypeSelectT{private: template<bool> struct In  { typedef T Result; }; template<> struct In<false> { typedef U Result; };public: typedef typename In<flag>::Result Result;};//计算ln(x)/ln(y),向上转换为整形template <uint64_t x,uint64_t y>struct logT{protected: template <uint64_t x1> struct imp{  enum {   next=(x1+y-1)/y,  };  enum {Result=1+imp<next>::Result}; }; template <>struct imp<1>{  enum {Result=0}; };public: enum {Result=imp<x>::Result};};//x^ytemplate <uint64_t x,uint64_t y>struct powerT{protected: template <uint64_t y1> struct imp{  enum{   next=y1-1  };  enum{   Result=x*imp<next>::Result  }; }; template<> struct imp<0>{  enum{   Result=1  }; };public: enum{  Result=imp<y>::Result };};//缓存表,template <uint64_t index>struct cacheCount{ //table<>未实现0,1,2,3,所以不允许<16b的对象编译通过,避免空间太小不能容纳调试信息。template <uint64_t>structtable;template <>struct table<4>{ enum{Result= 4096};};//16b -> 64ktemplate <>struct table<5>{ enum{Result= 4096};};//32b -> 128ktemplate <>struct table<6>{ enum{Result= 4096};};//64b -> 256ktemplate <>struct table<7>{ enum{Result= 4096};};//128b-> 512ktemplate <>struct table<8>{ enum{Result= 2048};};//256b-> 512ktemplate <>struct table<9>{ enum{Result= 2048};};//512b-> 1mtemplate <>struct table<10>{ enum{Result= 2048};};//1k  -> 2mtemplate <>struct table<11>{ enum{Result= 2048};};//2k  -> 4mtemplate <>struct table<12>{ enum{Result= 1024};};//4k  -> 4mtemplate <>struct table<13>{ enum{Result= 1024};};//8k  -> 8mtemplate <>struct table<14>{ enum{Result= 1024};};//16k -> 16m //更多的使用时添加template <>struct table<20>{ enum{Result= 4};};//1m -> 4mstructminCache{enum{Result=2};};enum{Result=TypeSelectT<index<20,table<logT<index,2>::Result>,minCache>::Result::Result };};//链表,用于可用空间回收structQMemLink{QMemLink*next;};classQMemTest;byte*QAlloc(size_t s){returnnew byte[s];}template <size_t size> class QFixAllocator{friendclassQMemTest;uint64_tusageBytes;uint64_tallocBytes;uint64_tpoolBytes;QMemLink*memPool;enum{sizeFix=powerT<2,logT<size,2>::Result>::Result};enum{caches=cacheCount<sizeFix>::Result};protected:QFixAllocator(){usageBytes=0;allocBytes=0;poolBytes=0;memPool=NULL;}public:void* alloc(size_t s){assert(s<=sizeFix);//避免new[]call到错误的allocator,host class应该使用单独版本的new[](),而不是默认调用new()QMemLink*r;if(memPool){r=memPool;memPool=memPool->next;poolBytes-=sizeFix;usageBytes+=s;returnr;}byte*p=QAlloc(sizeFix*caches);memPool=(QMemLink*)p;for(int i=1;i<caches;++i){r=(QMemLink*)p;p+=sizeFix;r->next=(QMemLink*)p;;}r->next=NULL;poolBytes+=(caches-1)*sizeFix;usageBytes+=s;allocBytes+=caches*sizeFix;returnp;}void free(void*p,size_t s){QMemLink*l=(QMemLink*)p;l->next=memPool;memPool=l;usageBytes-=s;poolBytes+=size;}voidstatus(uint64_t &u,uint64_t &a,uint64_t& p)const{u=usageBytes;a=allocBytes;p=poolBytes;}typedef     QFixAllocator me;static me Instance;};typedefQFixAllocator<powerT<2,4>::Result>QFixAllocator_4;typedefQFixAllocator<powerT<2,5>::Result>QFixAllocator_5;typedefQFixAllocator<powerT<2,6>::Result>QFixAllocator_6;typedefQFixAllocator<powerT<2,7>::Result>QFixAllocator_7;typedefQFixAllocator<powerT<2,8>::Result>QFixAllocator_8;typedefQFixAllocator<powerT<2,9>::Result>QFixAllocator_9;typedefQFixAllocator<powerT<2,10>::Result>QFixAllocator_10;typedefQFixAllocator<powerT<2,11>::Result>QFixAllocator_11;typedefQFixAllocator<powerT<2,12>::Result>QFixAllocator_12;typedefQFixAllocator<powerT<2,13>::Result>QFixAllocator_13;typedefQFixAllocator<powerT<2,14>::Result>QFixAllocator_14;typedefQFixAllocator<powerT<2,15>::Result>QFixAllocator_15;typedefQFixAllocator<powerT<2,16>::Result>QFixAllocator_16;typedefQFixAllocator<powerT<2,17>::Result>QFixAllocator_17;typedefQFixAllocator<powerT<2,18>::Result>QFixAllocator_18;typedefQFixAllocator<powerT<2,19>::Result>QFixAllocator_19;typedefQFixAllocator<powerT<2,20>::Result>QFixAllocator_20;typedefQFixAllocator<powerT<2,21>::Result>QFixAllocator_21;QFixAllocator_10QFixAllocator_10::Instance;QFixAllocator_11QFixAllocator_11::Instance;QFixAllocator_12QFixAllocator_12::Instance;QFixAllocator_13QFixAllocator_13::Instance;QFixAllocator_14QFixAllocator_14::Instance;QFixAllocator_15QFixAllocator_15::Instance;QFixAllocator_16QFixAllocator_16::Instance;QFixAllocator_17QFixAllocator_17::Instance;QFixAllocator_18QFixAllocator_18::Instance;QFixAllocator_19QFixAllocator_19::Instance;QFixAllocator_20QFixAllocator_20::Instance;QFixAllocator_21QFixAllocator_21::Instance;template<class Host>classQMemImpl{public:void*operatornew(size_t size){returnQFixAllocator<powerT<2,logT<sizeof(Host),2>::Result>::Result>::Instance.alloc(size);}voidoperatordelete(void*p){returnQFixAllocator<powerT<2,logT<sizeof(Host),2>::Result>::Result>::Instance.free(p,sizeof(Host));}void*operatornew[](size_t size){size+=8;//x64 8字节对齐ULONGr,f;_BitScanReverse(&r,size);_BitScanReverse(&f,size);if(r!=f)//对齐++r;switch(r){case19://这里只处理了1m字节的分配{uint32_t *p=(uint32_t*)QFixAllocator_20::Instance.alloc(size);*p=19;//set mask++p;*p=size;return++p;}default:DebugBreak();}throw"bad alloc";}voidoperatordelete[](void*p){uint32_t*p32=(uint32_t*)p;p32-=2;switch(*p32){case19://这里只处理了1m字节的释放QFixAllocator_20::Instance.free(p32,*(p32+1));return;default:DebugBreak();}}};template<class Host>classQMemDebugImpl{public:void*operatornew(size_t size){QMemDebugInfo*p=(QMemDebugInfo*)QFixAllocator<powerT<2,logT<sizeof(Host)+sizeof(QMemDebugInfo),2>::Result>::Result>::Instance.alloc(size);memset(p->guard,0,sizeof(p->guard));p->mask=logT<sizeof(Host)+sizeof(QMemDebugInfo),2>::Result;p->mask|=0x12345600;p->size=size;return++p;}voidoperatordelete(void*p){QMemDebugInfo*pDebug=(QMemDebugInfo*)p;--pDebug;if((pDebug->mask&(~0xff))!=0x12345600){ //标志错,可能是乱用delete,new[]DebugBreak();}if(pDebug->size!=sizeof(Host)){//size错DebugBreak();}//其他检查returnQFixAllocator<powerT<2,logT<sizeof(Host)+sizeof(QMemDebugInfo),2>::Result>::Result>::Instance.free(pDebug,sizeof(Host));}void*operatornew[](size_t size){size+=sizeof(QMemDebugInfo);ULONGr,f;if(!_BitScanReverse(&r,size))DebugBreak();//size 0,不可能的情况_BitScanReverse(&f,size);if(r!=f)//对齐++r;QMemDebugInfo *p;switch(r){case19:p=(QMemDebugInfo*)QFixAllocator_20::Instance.alloc(size);p->mask=19;break;case20:p=(QMemDebugInfo*)QFixAllocator_21::Instance.alloc(size);p->mask=20;break;default:DebugBreak();}memset(p->guard,0,sizeof(p->guard));p->size=size;return++p;}voidoperatordelete[](void*p){QMemDebugInfo *pDebug=(QMemDebugInfo*)p;--pDebug;if(pDebug->mask&(~0xff)){ //标志错,可能是乱用delete[],newDebugBreak();}if(pDebug->size<sizeof(Host)){//size错DebugBreak();}ULONGr,f;_BitScanReverse(&r,pDebug->size);_BitScanReverse(&f,pDebug->size);if(r!=f)++r;if(pDebug->mask!=r)DebugBreak();switch(pDebug->mask){case19:QFixAllocator_20::Instance.free(pDebug,pDebug->size);return;case20:QFixAllocator_21::Instance.free(pDebug,pDebug->size);return;default:DebugBreak();}}};template<class Host>classQMemPool:public TypeSelectT<DebugQMem,QMemDebugImpl<Host>,QMemImpl<Host>>::Result{};classQMemTest:publicQMemPool<QMemTest>{chartmp[1000];};voidshowMemInfo(){uint64_tu,a,p;QFixAllocator_11::Instance.status(u,a,p);printf("_11 u=%I64u a=%I64u p=%I64u \n",u,a,p);QFixAllocator_20::Instance.status(u,a,p);printf("_20 u=%I64u a=%I64u p=%I64u \n",u,a,p);}void main(){QMemTest*pTest[4096];showMemInfo();for(int i=0;i<countof(pTest);++i){pTest[i]=newQMemTest;}printf("new\n");showMemInfo();for(int i=0;i<countof(pTest);++i){deletepTest[i];}printf("delete\n");showMemInfo();deletenewQMemTest[1024];printf("delete[] new[]\n");showMemInfo();}


 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 微信被骗充值Q币怎么办 微信给别人充q币怎么办 k歌别人送的k币怎么办 忘记了qq号码但记得密码怎么办 q自己的活干完了该怎么办 在应用宝下载的游戏搜不到了怎么办 衣服有图片在淘宝找不到同款怎么办 淘宝卖家小儿说质量不合格怎么办 订单显示显示已签收没收到货怎么办 网上买过的东西查不到订单号怎么办 亚航的组合机票飞机延误怎么办 在微信上面对面红包被骗了钱怎么办 人欠我钱不给我怎么办 微信号被骗走然后骗了朋友钱怎么办 微信手机充值不到帐怎么办 中银香港密码器坏了怎么办 香港恒生银行的编码器丢了怎么办 淘宝拍下订单发货物流不显示怎么办 wish查到仿品审核变慢怎么办 淘宝卖家订单号错误无法修改怎么办 顺丰快递运单号微信扫描取消怎么办 买的王者荣耀号有守护平台怎么办 融e联登录密码错三次怎么办 金融e家u盾密码忘了怎么办 用工行网银转账后想取消交易怎么办 工行融e借没有密码器怎么办 工行融e借密码器丢了怎么办 工行融e联手机登录密码忘记怎么办 领导给员工抱怨工作太烦怎么办 员工抱怨忙的忙死闲的闲死怎么办 爱上骗我进传销的人该怎么办 尚赫辟谷期间吃了东西怎么办 肾结石掉在输尿管里面好痛怎么办 寄的快递快递单号找不到了怎么办 手机停机但是快递是这个号码怎么办 百世通快递卡在一个地方没动怎么办 电信无限流量20g用完了怎么办 至尊宝qq密保手机被更换怎么办 至尊宝账户密保手机被改怎么办 照片放到私密相册找不到了怎么办 出口报关报错境内货源地怎么办?