通用C++内存池代码

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

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

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

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

 

//type and macro
#include <default.h>

//debug 信息
const	bool	DebugQMem=1;

struct	QMemDebugInfo{
	uint32_t		mask;
	uint32_t		size;
	byte			guard[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^y
template <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>	struct	table;
	template <>	struct table<4>{ enum{	Result= 4096	};};	//16b -> 64k
	template <>	struct table<5>{ enum{	Result= 4096	};};	//32b -> 128k
	template <>	struct table<6>{ enum{	Result= 4096	};};	//64b -> 256k
	template <>	struct table<7>{ enum{	Result= 4096	};};	//128b-> 512k
	template <>	struct table<8>{ enum{	Result= 2048	};};	//256b-> 512k
	template <>	struct table<9>{ enum{	Result= 2048	};};	//512b-> 1m
	template <>	struct table<10>{ enum{	Result= 2048	};};	//1k  -> 2m
	template <>	struct table<11>{ enum{	Result= 2048	};};	//2k  -> 4m
	template <>	struct table<12>{ enum{	Result= 1024	};};	//4k  -> 4m
	template <>	struct table<13>{ enum{	Result= 1024	};};	//8k  -> 8m
	template <>	struct table<14>{ enum{	Result= 1024	};};	//16k -> 16m
 //更多的使用时添加
	template <>	struct table<20>{ enum{	Result= 4		};};	//1m -> 4m
	struct	minCache{enum	{Result=2};};
	enum	{Result=TypeSelectT<index<20,table<logT<index,2>::Result>,minCache>::Result::Result };
};





//链表,用于可用空间回收
struct	QMemLink{
	QMemLink*	next;
};

class	QMemTest;

byte*	QAlloc(size_t s){
	return	new byte[s];
}

template <size_t size> 
class QFixAllocator{

friend	class	QMemTest;
	uint64_t	usageBytes;
	uint64_t	allocBytes;
	uint64_t	poolBytes;
	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;
			return	r;
		}

		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;
		return	p;

	}

	void free(void*p,size_t s){
		QMemLink*	l=(QMemLink*)p;
		l->next=memPool;
		memPool=l;
		usageBytes-=s;
		poolBytes+=size;
	}
	void	status(uint64_t &u,uint64_t &a,uint64_t& p)const{
		u=usageBytes;
		a=allocBytes;
		p=poolBytes;
	}

	typedef     QFixAllocator me;

	static me Instance;

	};



typedef	QFixAllocator<powerT<2,4>::Result>	QFixAllocator_4;
typedef	QFixAllocator<powerT<2,5>::Result>	QFixAllocator_5;
typedef	QFixAllocator<powerT<2,6>::Result>	QFixAllocator_6;
typedef	QFixAllocator<powerT<2,7>::Result>	QFixAllocator_7;
typedef	QFixAllocator<powerT<2,8>::Result>	QFixAllocator_8;
typedef	QFixAllocator<powerT<2,9>::Result>	QFixAllocator_9;
typedef	QFixAllocator<powerT<2,10>::Result>	QFixAllocator_10;
typedef	QFixAllocator<powerT<2,11>::Result>	QFixAllocator_11;
typedef	QFixAllocator<powerT<2,12>::Result>	QFixAllocator_12;
typedef	QFixAllocator<powerT<2,13>::Result>	QFixAllocator_13;
typedef	QFixAllocator<powerT<2,14>::Result>	QFixAllocator_14;
typedef	QFixAllocator<powerT<2,15>::Result>	QFixAllocator_15;
typedef	QFixAllocator<powerT<2,16>::Result>	QFixAllocator_16;
typedef	QFixAllocator<powerT<2,17>::Result>	QFixAllocator_17;
typedef	QFixAllocator<powerT<2,18>::Result>	QFixAllocator_18;
typedef	QFixAllocator<powerT<2,19>::Result>	QFixAllocator_19;
typedef	QFixAllocator<powerT<2,20>::Result>	QFixAllocator_20;
typedef	QFixAllocator<powerT<2,21>::Result>	QFixAllocator_21;


QFixAllocator_10	QFixAllocator_10::Instance;
QFixAllocator_11	QFixAllocator_11::Instance;
QFixAllocator_12	QFixAllocator_12::Instance;
QFixAllocator_13	QFixAllocator_13::Instance;
QFixAllocator_14	QFixAllocator_14::Instance;
QFixAllocator_15	QFixAllocator_15::Instance;
QFixAllocator_16	QFixAllocator_16::Instance;
QFixAllocator_17	QFixAllocator_17::Instance;
QFixAllocator_18	QFixAllocator_18::Instance;
QFixAllocator_19	QFixAllocator_19::Instance;
QFixAllocator_20	QFixAllocator_20::Instance;
QFixAllocator_21	QFixAllocator_21::Instance;












template	<class Host>
class	QMemImpl{
public:

	void*	operator	new(size_t size){
		return	QFixAllocator<powerT<2,logT<sizeof(Host),2>::Result>::Result>::Instance.alloc(size);
	}

	void	operator	delete(void*p){
		return	QFixAllocator<powerT<2,logT<sizeof(Host),2>::Result>::Result>::Instance.free(p,sizeof(Host));
	}

	void*	operator	new[](size_t size){
		
		size+=8;	//x64 8字节对齐

		ULONG	r,f;
		_BitScanReverse(&r,size);
		_BitScanReverse(&f,size);
		
		if(r!=f)	//对齐
			++r;

		switch(r){
			case	19://这里只处理了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";
	}

	void	operator	delete[](void*p){
		uint32_t*	p32=(uint32_t*)p;
		p32-=2;
		switch(*p32){
			case	19://这里只处理了1m字节的释放
				QFixAllocator_20::Instance.free(p32,*(p32+1));
				return;
			default:
				DebugBreak();
		}

	}
};

template	<class Host>
class	QMemDebugImpl{
public:
	void*	operator	new(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;

	}
	void	operator	delete(void*p){
		QMemDebugInfo*	pDebug=(QMemDebugInfo*)p;
		--pDebug;

		if((pDebug->mask&(~0xff))!=0x12345600){ //标志错,可能是乱用delete,new[]
			DebugBreak();
		}
		if(pDebug->size!=sizeof(Host)){		//size错
			DebugBreak();
		}

		//其他检查

		return	QFixAllocator<powerT<2,logT<sizeof(Host)+sizeof(QMemDebugInfo),2>::Result>::Result>::Instance.free(pDebug,sizeof(Host));
	}

	void*	operator	new[](size_t size){
		
		size+=sizeof(QMemDebugInfo);	
		ULONG	r,f;
		if(!_BitScanReverse(&r,size))
			DebugBreak();//size 0,不可能的情况
		_BitScanReverse(&f,size);
		
		if(r!=f)	//对齐
			++r;
		QMemDebugInfo *p;
		switch(r){
			case	19:
					p=(QMemDebugInfo*)QFixAllocator_20::Instance.alloc(size);
					p->mask=19;
					break;
			case	20:
					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;


	}

	void	operator	delete[](void*p){
		QMemDebugInfo *pDebug=(QMemDebugInfo*)p;
		--pDebug;

		if(pDebug->mask&(~0xff)){ //标志错,可能是乱用delete[],new
			DebugBreak();
		}
		if(pDebug->size<sizeof(Host)){		//size错
			DebugBreak();
		}

		ULONG	r,f;
		_BitScanReverse(&r,pDebug->size);
		_BitScanReverse(&f,pDebug->size);
		if(r!=f)
			++r;
		if(pDebug->mask!=r)
			DebugBreak();

		switch(pDebug->mask){
			case	19:
				QFixAllocator_20::Instance.free(pDebug,pDebug->size);
				return;
			case	20:
				QFixAllocator_21::Instance.free(pDebug,pDebug->size);
				return;

			default:
				DebugBreak();
		}

	}
};


template	<class Host>
class	QMemPool:public TypeSelectT<DebugQMem,QMemDebugImpl<Host>,QMemImpl<Host>>::Result	
{


};

class	QMemTest:public	QMemPool<QMemTest>{
	char	tmp[1000];
};


void	showMemInfo(){


	uint64_t	u,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]=new	QMemTest;
	}
	printf("new\n");

	showMemInfo();

	for(int i=0;i<countof(pTest);++i){
		delete	pTest[i];
	}
	printf("delete\n");


	showMemInfo();
	delete	new	QMemTest[1024];

	printf("delete[] new[]\n");

	showMemInfo();



	
}


 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值