游戏服务器之自定义内存池管理器和空间配置器

设计上:

(1)内存分配器管理器(nMemoryAlloc):

内存分配器管理器含有针对不同内存大小的内存池数组。每个内存池对象含有空闲节点链表,管理分配和回收的节点对象内存。

(2)链表节点内存:

链表节点对象含有变长内存成员,适合分配各个长度的内存对象。但同一个内存池对象中的节点内存大小是一致的。

(3)内存分配原则:

1)内存分配器nMemoryAlloc对于内存大小在1~1024 * 1024 字节之间小对象使用内存池的管理,否则就使用系统默认的分配和删除接口,让系统管理内存。

2)内存分配器适用的是定长的类型。

(4)静态存储区使用:

内存池管理器中的内存池数组是静态的,对外提供静态接口。

(5)空间配置器:

空间配置器使用内存池管理器来管理器内存



1、内存池类型

内存池分配节点,没有内存就向系统申请,否则从空闲列表中获取。

内存池含空闲节点链表。

 

class MemPool2
{
private:
	struct _Node
	{
		_Node():next(NULL)
		{
		}
		~_Node()
		{
		}
	_Node* next;
	unsigned char data[0];//变长内存
	};
	
	_Node* mFreeNodeList;
	public: 
	unsigned long _all_alloc_size;//总共分配内存大小计数
	unsigned long _all_alloc_num;//分配节点计数
	unsigned long _all_use_num;//使用节点计数
	unsigned long _all_free_num;//空闲节点计数
	public: 
	
	MemPool2()
	: mFreeNodeList(NULL),_all_alloc_size(0),_all_alloc_num(0),_all_use_num(0),_all_free_num(0)
	{
	}
	
	void reset()//释放链表所有节点内存
	{
		_Node* p = mFreeNodeList;
		while(p)
		{
			_all_free_num ++;
			_Node* _p = p;
			p = p->next;
			char *tmp = (char *)_p;
			free(tmp);
		}
		mFreeNodeList = NULL;
	}
	~MemPool2(void)
	{
		_Node* p = mFreeNodeList;
		while(p)
		{
			_Node* _p = p;
			p = p->next;
			char *tmp = (char *)_p;
			free(tmp);
		}
		mFreeNodeList = NULL;
	}
	
	_Node* __allocData(int datasize)//实际分配节点(没有内存就向系统申请,否则从空闲列表中获取)
	{
		if(!mFreeNodeList)
		{
			_all_alloc_size += (sizeof(_Node) + datasize);//记录总分配大小
			_all_alloc_num ++;//记录分配节点数
			char *tmp = (char *)malloc(sizeof(_Node) + datasize);
			mFreeNodeList = (_Node *)tmp;
			constructInPlace(mFreeNodeList);
		}
		_all_use_num ++;
		_Node* p = mFreeNodeList;
		mFreeNodeList = mFreeNodeList->next;
		return p;//返回节点
	}
	
	unsigned char* alloc0(int datasize)//分配节点(没有内存就向系统申请,否则从空闲列表中获取)
	{
		_Node* p = __allocData(datasize);
		return (unsigned char*)(p->data);
	}
	
	void freePtr(unsigned char* &p)//回收节点的内存回链表表头
	{
		if (p)
		{
			_Node* pNod = (_Node*)(p - sizeof(_Node));//上一个链表节点(分配过的就会有)
			pNod->next = mFreeNodeList;
			mFreeNodeList = pNod;
			p = NULL;
			_all_use_num --;
		}
	}
	
	void freePtr(char* p)//回收节点的内存回链表表头(_Node + 实际内存)
	{
		if (p)
		{
			_Node* pNod = (_Node*)(p - sizeof(_Node));
			pNod->next = mFreeNodeList;
			mFreeNodeList = pNod;
			_all_use_num --;
		}
	}
};

其中:在指定地址构造对象
template<class T> 
inline void constructInPlace(T  *_Ptr)
{ // construct object at _Ptr with value _Val
	new ((void  *)_Ptr) T();
}



2、内存池分配管理器

(1)内存池分配管理器定义

内存池分配管理器类型定义,需要重载new 操作符和delete操作符。
具体要使用自定义空间配置器的类型对象是需要继承该类才可以使用。
1)对象数据大小:在1024 * 1024字节 以内的对象才可以使用内存池分配和回收,否则使用系统函数分配和删除.
2)选用内存池:是按内存字节大小(包含节点头)来选取需要使用的内存池对象。
3)锁数组:

class nMemoryAlloc
{
	protected:
	nMemoryAlloc()
	{
	};
	
	~nMemoryAlloc()
	{
	};
	public:
	//锁(单线程不使用)
	static zMutex alloc_lock[1024 * 1024 + 1024];
	//内存池数组
	//数据大小在1024 * 1024字节 以内的对象才可以使用内存池分配和回收,否则使用系统函数分配和删除
	//使用哪个内存池是按字节大小(包含节点头)来获取需要使用的内存池
	static MemPool2 alloc[1024 * 1024 + 1024];
	public:
	static void* operator new( size_t Size , void *);
	static void* operator new( size_t Size , void *,const char* filename,int line );
	static void* operator new( size_t Size);
	static void* operator new( size_t Size,const char* filename,int line );
	static void operator delete( void* Ptr );
	static void operator delete( void* Ptr ,const char* , int);
	static void* operator new[]( size_t Size , void *);
	static void* operator new[]( size_t Size  , void *,const char* filename,int line);
	static void* operator new[]( size_t Size );
	static void* operator new[]( size_t Size ,const char* filename,int line);
	static void operator delete[]( void* Ptr );
	static void operator delete[]( void* Ptr ,const char* , int);
	public:
	static void *allocator(size_t Size);
	static void free(void* Ptr);
};


(2)内存池分配管理器操作符重载

数据大小在1024 * 1024字节 以内的才可以使用内存池分配和回收,否则使用系统函数分配和删除。

1)小对象分配使用内存分配器 

2)大对象就直接分配


//释放一个内存对象
void* nMemoryAlloc::operator new( size_t Size )
{
	assert(Size != 0);
	Size += sizeof(_Node);
	Size = (Size + 0X3F) & (0XFFFFFFFF - 0X3F);//64字节对齐
	//数据大小在1024 * 1024字节 以内的才可以使用内存池分配和回收,否则使用系统函数分配和删除
	if(Size < 1024 * 1024)//小对象分配使用内存分配器
	{
		zMutex_scope_lock lock(alloc_lock[Size]);
		void *tmp = alloc[Size].alloc0(Size);
		_Node *mFreeNodeList = (_Node *)tmp;
		constructInPlace(mFreeNodeList);
		mFreeNodeList->size = Size;
		return mFreeNodeList->data;
	}
	else//大对象就直接分配
	{
		void *tmp = malloc( Size );
		_Node *mFreeNodeList = (_Node *)tmp;
		constructInPlace(mFreeNodeList);
		mFreeNodeList->size = Size;
		return mFreeNodeList->data;
	}
}
//释放内存对象数组
void* nMemoryAlloc::operator new[]( size_t Size )
{
	assert(Size != 0);
	Size += sizeof(_Node);
	Size = (Size + 0X3F) & (0XFFFFFFFF - 0X3F);//64字节对齐
	//数据大小在1024 * 1024字节 以内的才可以使用内存池分配和回收,否则使用系统函数分配和删除
	if(Size < 1024 * 1024)//小对象分配使用内存分配器
	{
		zMutex_scope_lock lock(alloc_lock[Size]);
		void *tmp= alloc[Size].alloc0(Size);//内存池分配(内存池的选择跟分配的大小是一致的)
		_Node *mFreeNodeList = (_Node *)tmp;
		constructInPlace(mFreeNodeList);//placement new 构造对象
		mFreeNodeList->size = Size;
		return mFreeNodeList->data;
	}
	else//大对象就直接分配
	{
		void *tmp = malloc( Size );
		_Node *mFreeNodeList = (_Node *)tmp;
		constructInPlace(mFreeNodeList);
		mFreeNodeList->size = Size;
		return mFreeNodeList->data;
	}
}

//回收对象
//数据大小在1024 * 1024字节 以内的才可以使用内存池分配和回收,否则使用系统函数分配和删除
void nMemoryAlloc::operator delete( void* Ptr )
{
	if (!Ptr)
	{
		return;
	}
	_Node* pNod = (_Node*)((char *)Ptr - sizeof(_Node));//获取内存的节点头
	if(pNod->size && pNod->size < 1024 * 1024)//数据大小在1024 * 1024字节 以内的才可以使用内存池分配和回收,否则使用系统函数分配和删除
	{
		alloc[pNod->size].freePtr((char *)pNod);
		return;
	}
	else
	{
		::free( pNod );
	}
}


//删除对象数组
void nMemoryAlloc::operator delete[]( void* Ptr )
{
	if (!Ptr)
	{
		return;
	}
	_Node* pNod = (_Node*)((char *)Ptr - sizeof(_Node));
	if(pNod->size < 1024 * 1024 && pNod->size != 0)
	{
		alloc[pNod->size].freePtr((char *)pNod);
		return;
	}
	else
	{
		::free( pNod );
	}
}


(3)内存池分配管理器的内存分配和回收

 数据大小在1024 * 1024字节 以内的才可以使用内存池分配和回收,否则使用系统函数分配和删除。
1)小对象分配使用内存分配器 
2)大对象就使用系统函数分配和删除

void *nMemoryAlloc::allocator(size_t Size)
{
	Size += sizeof(_Node);
	Size = (Size + 0X3F) & (0XFFFFFFFF - 0X3F);//64字节对齐
	
	if(Size < 1024 * 1024)
	{
		void *tmp= alloc[Size].alloc0(Size);
		_Node *mFreeNodeList = (_Node *)tmp;
		constructInPlace(mFreeNodeList);
		mFreeNodeList->size = Size;
		return mFreeNodeList->data;
	}
	else
	{
		void *tmp = malloc( Size );
		_Node *mFreeNodeList = (_Node *)tmp;
		constructInPlace(mFreeNodeList);
		mFreeNodeList->size = Size;
		return mFreeNodeList->data;
	}
}

void nMemoryAlloc::free(void* Ptr)
{
	if (!Ptr)
	{
		return;
	}
	_Node* pNod = (_Node*)((char *)Ptr - sizeof(_Node));
	if(pNod->size && pNod->size < 1024 * 1024)
	{
		zMutex_scope_lock lock(alloc_lock[pNod->size]);
		alloc[pNod->size].freePtr((char *)pNod);
		return;
	}
	else
	{
		::free( pNod );
	}
}


(4)内存池分配管理器应用

1)基本类型应用

使用对象分配器的对象

struct StateObject:public nMemoryAlloc//使用的类型
{

....

};

2)在空间配置器中的使用


4、空间配置器 

(1)空间配置器定义

自定义空间配置器,内存的分配和回收是使用内存池分配管理器。空间配置器是在容器内加入元素和删除元素和容器析构时会使用。

template <class _Ty>
class nMemoryAllocator
{
public:
typedef size_tsize_type;
typedef _Ty  *pointer;
typedef _Ty & reference;
typedef const _Ty  *const_pointer;
typedef const _Ty & const_reference;
typedef _Ty value_type;
typedef int difference_type;
 
	nMemoryAllocator()
	{ // construct default allocator (do nothing)
	}
	
	//赋值函数重载
	template<class _Other>
	nMemoryAllocator<_Ty>& operator = (const nMemoryAllocator<_Other>& alr)
	{ // assign from a related allocator (do nothing)
		return (*this);
	}
	
	//拷贝构造函数重载
	template<class _Other>
	nMemoryAllocator(const nMemoryAllocator<_Other>& alr)
	{ // construct by copying (do nothing)
	}
	
	//重绑定类型到自定义的空间配置器
	template<class _Other>
	struct rebind
	{ // convert an allocator<_Ty> to an allocator <_Other>
	typedef nMemoryAllocator<_Other> other;
	};
	
	//内存分配(参数分配对象个数)
	pointer allocate(size_type _Count)//分配原始的构造内存以保存T类型的n个对象
	{
		if(_Count == 0) _Count = 1;
		return (pointer)nMemoryAlloc::allocator(sizeof(_Ty) * _Count);//从内存管理器获取内存
	}
	
	//内存分配(参数分配对象个数)
	pointer allocate(size_type _Count,const void *)
	{
		if(_Count == 0) _Count = 1;
		return (pointer)nMemoryAlloc::allocator(sizeof(_Ty) * _Count);//从内存管理器获取内存
	}
	
	//返回引用地址
	pointer address(reference _Val) const
	{ // return address of mutable _Val
		return (&_Val);
	}
	
	//返回引用地址
	const_pointer address(const_reference _Val) const
	{ // return address of nonmutable _Val
		return (&_Val);
	}
	
	//构造对象(成员)
	void construct(pointer _Ptr, const _Ty& _Val)//指针p所指向的内存中构造一个新对象
	{
		::new(static_cast<void*>(<span style="font-family: Arial, Helvetica, sans-serif;">_Ptr</span>)) <span style="font-family: Arial, Helvetica, sans-serif;">_Ty</span>(<span style="font-family: Arial, Helvetica, sans-serif;">_Val</span>);//std::_Construct(_Ptr,_Val);
	}
	
	//析构对象(回收到内存池管理器)
	void deallocate(pointer _Ptr, size_type size) //释放内存,在名为p的T*指针含的地址处保存T类型的n个对象
<pre code_snippet_id="439793" snippet_file_name="blog_20140731_5_33916" name="code" class="cpp">        { // deallocate object at _Ptr, ignore size
nMemoryAlloc::free(_Ptr);}//销毁对象void destroy(pointer _Ptr){ // destroy object at _Ptr_Ptr->~_Ty();;//析构对象 std::_Destroy(_Ptr);}//能够分配的大小(准确的估计需要重新计算)size_t max_size() const{ // estimate maximum array sizesize_t _Count = (size_t)(-1) / sizeof (_Ty);return (0 < _Count ? _Count : 1);}};//重载等号操作符template<class _Ty,class _Other>inline bool operator == (const nMemoryAllocator<_Ty>& alr1,const nMemoryAllocator<_Other>& alr2){ // assign from a related allocator (do nothing)return true;} //重载不等操作符template<class _Ty,class _Other>inline bool operator != (const nMemoryAllocator<_Ty>& alr1,const nMemoryAllocator<_Other>& alr2){ // assign from a related allocator (do nothing)return false;}
 
 

 

(2)  空间配置器使用

使用空间配置器的类型
自定义的类型是继承stl中的 容器类型,容器的空间配置器是用自定义的空间配置器

1)字符串string类型
typedef std::basic_string<char, std::char_traits<char>, nMemoryAllocator<char> > string;
typedef std::string string;


2)基类写流basic_ostream类型
template<typename T>
struct basic_ostream: public std::basic_ostream<T, nMemoryAllocator<T> >{};
typedef std::basic_ostream<char, zMemoryAllocator<char> > basic_ostream;


3)基类读流basic_istream类型
template<typename T>
struct basic_istream: public std::basic_istream<T,  nMemoryAllocator<T> >{};
typedef std::basic_istream<char, zMemoryAllocator<char> > basic_istream;

4)vector类型
template<typename T>
struct vector: public std::vector<T ,nMemoryAllocator<T> >
{
vector(){}
vector(int size):std::vector<T ,nMemoryAllocator<T> >(size){}
vector(const Zebra::vector<T>& v):std::vector<T ,nMemoryAllocator<T> >(v){}
};


template<typename T>
struct list: public std::list<T ,nMemoryAllocator<T> >{};

空间配置器具体应用实例

容器使用

使用自定义空间配置器的对象列表

typedef Zebra::vector<StateObject *> stateVector; //使用的容器


你可能感兴趣的:(游戏服务器之自定义内存池管理器和空间配置器)