简单的内存池

对于服务器开发,经常需要数据拷贝,需要使用new和delete动态生存内存,长期使用new和delete会出现内存碎片,特别对于服务程序,生存周期很长。那么会长生大量的内存碎片,直到没有没有内存new(new出的内存是以2,4,8,16的整数倍为基址)。那么解决办法可以使用内存池。

设计思路:

       网上百度了一下资料,用类似与十字链表来管理内存,相关结构如下:

<span style="font-family: Arial, Helvetica, sans-serif;">typedef struct tagMEM_BLOCK</span>
	{
		VOID *lpvMemObjectAddr; // 内存块的起始地址
		INT nBlockSize;         // 内存块大小
		INT nNextBlock;

	}MEM_BLOCK;

	typedef struct tagMEM_HEADER
	{
		VOID *lpvMemBaseAddr;           // 内存块信息
		INT nMemSize;
		INT nUsedMemBlock;		// 使用内存块信息
		INT nUnusedMemBlock;	// 未使用内存块信息
		INT nFreeMemBlock;		// 空闲内存块信息
		MEM_BLOCK *pMemBlockMap;
		INT nMemBlockNum;

		INT nMaxUnsedBlockSize;

	}MEM_HEADER;
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="cpp">/****************************************************************
 * ----------
 * |		|->正在使用的内存块节点
 * |头信息	|->没有使用的内存块节点
 * |		|
 * |		|->空闲的内存块节点
 * ----------
 * 	   |
 * 	   |
 * 	   |
 *-----------
 * |		|
 * |		|
 * |头信息	|
 * |		|
 * ----------
 ****************************************************************/


 
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">关于块的查找我使用的静态链表,这样可以提高访问速度。</span>

template <class T0, class T1 = CHAR *, class T2 = INT>
class CMemPool
{
	typedef struct tagMEM_BLOCK
	{
		VOID *lpvMemObjectAddr;
		INT nBlockSize;
		INT nNextBlock;

	}MEM_BLOCK;

	typedef struct tagMEM_HEADER
	{
		VOID *lpvMemBaseAddr;
		INT nMemSize;
		INT nUsedMemBlock;		// 使用内存块信息
		INT nUnusedMemBlock;	// 未使用内存块信息
		INT nFreeMemBlock;		// 空闲内存块信息
		MEM_BLOCK *pMemBlockMap;
		INT nMemBlockNum;

		INT nMaxUnsedBlockSize;

	}MEM_HEADER;

	typedef CMemPool::MEM_HEADER T_MEM_HEADER;
	typedef CMemPool::MEM_BLOCK T_MEM_BLOCK;

	//IMPLEMENT_SINGLE(CMemPool)

private:
	CMemPool()
	{
		m_nGrowNums= -1;
	}
	virtual ~CMemPool()
	{

	}

public:
	static CMemPool *CreateInstance()
	{
		ASSERT(m_lpInstance == NULL);

		m_lpInstance = new CMemPool<T0, T1, T2>;
	}
	static CMemPool *GetInstance()
	{
		ASSERT(m_lpInstance != NULL);

		return m_lpInstance;
	}

public:
	BOOL CreateMemPool(INT nObjectNums = 1000, INT nGrowNums = 100);
	T0 *Construct(INT nObjectNum = 1);
	T0 *Construct(INT nObjectNum, T1 &t1, T2 &t2);
	VOID Destory(T0 *pT0);
	VOID Free();
	VOID Release();

private:
	VOID *MemMalloc(T_MEM_HEADER &MemHeader, INT nMemSize);
	BOOL CreateNewMemHeader(INT nObjectNum, T_MEM_HEADER *pMemHeader);
	INT GetFreeBlock(T_MEM_HEADER &MemHeader);
	VOID FreeBlock(T_MEM_HEADER &MemHeader, INT nIndex);
	VOID InsertUsedBlock(T_MEM_HEADER &MemHeader, INT nIndex);

private:
	static CMemPool *m_lpInstance;

private:
	vector<MEM_HEADER >m_VecMemHeader;
	INT m_nGrowNums;

};

template <class T0, class T1, class T2>
CMemPool<T0, T1, T2> *CMemPool<T0, T1, T2>::m_lpInstance = NULL;


template <class T0, class T1, class T2>
BOOL CMemPool<T0, T1, T2>::CreateMemPool(INT nObjectNums, INT nGrowNums)
{
	INT nMemSize;
	VOID *lpvObjectPool;
	T_MEM_HEADER MemHeader = {0};

	m_nGrowNums = nGrowNums;
	if (!CreateNewMemHeader(nObjectNums, &MemHeader))
	{
		return FALSE;
	}

	m_VecMemHeader.push_back(MemHeader);
	return TRUE;
}

template <class T0, class T1, class T2>
T0 *CMemPool<T0, T1, T2>::Construct(INT nCreateNums)
{
	// 查找到空闲内存
	INT nBlockIndex;
	INT i;
	INT nMemSize;
	VOID *lpvCreateObjectAddr = NULL;

	nMemSize = sizeof(T0) * nCreateNums;
	for (i = 0; i < m_VecMemHeader.size(); ++ i)
	{
		lpvCreateObjectAddr = MemMalloc(m_VecMemHeader[i], nMemSize);
		if (lpvCreateObjectAddr != NULL)
		{
			break;
		}
	}
	if (i == m_VecMemHeader.size())
	{
		T_MEM_HEADER MemHeader;
		INT nGrowNums;

		nGrowNums = m_nGrowNums;
		if (nGrowNums < nCreateNums)
		{
			nGrowNums = nCreateNums;
		}
		// 创建新的块
		if (CreateNewMemHeader(nGrowNums, &MemHeader))
		{
			lpvCreateObjectAddr = MemMalloc(MemHeader, nMemSize);
			ASSERT(lpvCreateObjectAddr != NULL);
			m_VecMemHeader.push_back(MemHeader);
		}
	}

	return new(lpvCreateObjectAddr)T0[nCreateNums];
}

template <class T0, class T1, class T2>
T0 *CMemPool<T0, T1, T2>::Construct(INT nCreateNums, T1 &t1, T2 &t2)
{

}

template <class T0, class T1, class T2>
VOID CMemPool<T0, T1, T2>::Destory(T0 *pT0)
{
	INT i;
	INT nBlockIndex;
	T_MEM_BLOCK *pMemBlockMap;

	for (i = 0; i < m_VecMemHeader.size(); ++ i)
	{
		if ((VOID *)pT0 >= m_VecMemHeader[i].lpvMemBaseAddr &&
			(BYTE *)pT0 < ((BYTE *)m_VecMemHeader[i].lpvMemBaseAddr + m_VecMemHeader[i].nMemSize))
		{
			break;
		}
	}
	if (i != m_VecMemHeader.size())
	{
		pMemBlockMap = m_VecMemHeader[i].pMemBlockMap;
		nBlockIndex = pMemBlockMap[m_VecMemHeader[i].nUsedMemBlock].nNextBlock;

		while (nBlockIndex != -1)
		{
			if ((VOID *)pT0 == pMemBlockMap[nBlockIndex].lpvMemObjectAddr)
			{
				pT0->~T0();
				break;
			}
			nBlockIndex = pMemBlockMap[nBlockIndex].nNextBlock;
		}

		if (nBlockIndex != -1)
		{
			INT nUnusedBlockIndex;
			INT nPreUnUsedIndex;

			nPreUnUsedIndex	  = m_VecMemHeader[i].nUnusedMemBlock;
			nUnusedBlockIndex = pMemBlockMap[nPreUnUsedIndex].nNextBlock;
			while (nUnusedBlockIndex != -1)
			{
				if (BLOCK_UP_BANDARY(pMemBlockMap, nBlockIndex) <= BLOCK_DOWN_BANDARY(pMemBlockMap, nUnusedBlockIndex))
				{
					break;
				}

				nPreUnUsedIndex = nUnusedBlockIndex;
				nUnusedBlockIndex = pMemBlockMap[nUnusedBlockIndex].nNextBlock;
			}

			// insert and combine
			pMemBlockMap[nPreUnUsedIndex].nNextBlock = nBlockIndex;
			pMemBlockMap[nBlockIndex].nNextBlock = nUnusedBlockIndex;
			if (BLOCK_DOWN_BANDARY(pMemBlockMap, nPreUnUsedIndex) != NULL)
			{
				// he bing
				if (BLOCK_UP_BANDARY(pMemBlockMap, nPreUnUsedIndex) == BLOCK_DOWN_BANDARY(pMemBlockMap, nBlockIndex))
				{
					pMemBlockMap[nPreUnUsedIndex].nBlockSize += pMemBlockMap[nBlockIndex].nBlockSize;
					pMemBlockMap[nPreUnUsedIndex].nNextBlock = pMemBlockMap[nBlockIndex].nNextBlock;

					FreeBlock(m_VecMemHeader[i], nBlockIndex);
					nBlockIndex = nPreUnUsedIndex;

				}
			}
			if (nUnusedBlockIndex != -1)
			{
				if (BLOCK_UP_BANDARY(pMemBlockMap, nBlockIndex) == BLOCK_DOWN_BANDARY(pMemBlockMap, nUnusedBlockIndex))
				{
					// add
					pMemBlockMap[nBlockIndex].nBlockSize += pMemBlockMap[nUnusedBlockIndex].nBlockSize;
					pMemBlockMap[nBlockIndex].nNextBlock = pMemBlockMap[nUnusedBlockIndex].nNextBlock;

					FreeBlock(m_VecMemHeader[i], nUnusedBlockIndex);
				}
			}
		}
	}
}

template <class T0, class T1, class T2>
BOOL CMemPool<T0, T1, T2>::CreateNewMemHeader(INT nObjectNums, T_MEM_HEADER *pMemHeader)
{
	INT nMemSize;
	VOID *lpvObjectPool;
	T_MEM_BLOCK *pMemBlockMap;
	INT i;
	INT nFreeBlock;

	nMemSize = nObjectNums * sizeof(T0);
	lpvObjectPool = malloc(nMemSize);
	if (lpvObjectPool == NULL)
	{
		return FALSE;
	}
	pMemHeader->lpvMemBaseAddr 	= lpvObjectPool;
	pMemHeader->nMemSize 		= nMemSize;

	nMemSize 					= (nObjectNums + 3)* sizeof(T_MEM_HEADER);
	pMemHeader->nMemBlockNum 	= nObjectNums + 3; // 除掉两个头结点, 起始空闲块需要一个节点,
	pMemBlockMap = (T_MEM_BLOCK *)malloc(nMemSize);
	if (pMemBlockMap == NULL)
	{
		delete [](T0 *)lpvObjectPool;
		return FALSE;
	}
	memset(pMemBlockMap, 0, nMemSize);

	pMemHeader->pMemBlockMap = pMemBlockMap;
	for (i = 2; i < nObjectNums + 3; ++ i)
	{
		pMemBlockMap[i].nNextBlock = i + 1;
	}
	pMemBlockMap[i - 1].nNextBlock = -1;

	// 头节点不予赋值,便于操作
	pMemHeader->nUsedMemBlock 	= 0;
	pMemHeader->nUnusedMemBlock = 1;
	pMemHeader->nFreeMemBlock 	= 2;

	pMemBlockMap[pMemHeader->nUsedMemBlock].nNextBlock = -1;
	pMemBlockMap[pMemHeader->nUnusedMemBlock].nNextBlock = -1;

	// 没有使用的内存
	nFreeBlock = GetFreeBlock(*pMemHeader);
	pMemBlockMap[pMemHeader->nUnusedMemBlock].nNextBlock = nFreeBlock;
	pMemBlockMap[nFreeBlock].lpvMemObjectAddr = lpvObjectPool;
	pMemBlockMap[nFreeBlock].nBlockSize = pMemHeader->nMemSize;
	pMemBlockMap[nFreeBlock].nNextBlock = -1;

	return TRUE;
}

template <class T0, class T1, class T2>
INT CMemPool<T0, T1, T2>::GetFreeBlock(T_MEM_HEADER &MemHeader)
{
	INT nBlockIndex;
	T_MEM_BLOCK *pMemBlockMap;

	pMemBlockMap = MemHeader.pMemBlockMap;
	nBlockIndex = MemHeader.nFreeMemBlock;

	if (nBlockIndex != -1)
	{
		MemHeader.nFreeMemBlock = pMemBlockMap[nBlockIndex].nNextBlock;
	}

	return nBlockIndex;
}

template <class T0, class T1, class T2>
VOID CMemPool<T0, T1, T2>::FreeBlock(T_MEM_HEADER &MemHeader, INT nIndex)
{
	INT nBlockIndex;
	T_MEM_BLOCK *pMemBlockMap;

	pMemBlockMap = MemHeader.pMemBlockMap;
	nBlockIndex = MemHeader.nFreeMemBlock;
	pMemBlockMap[nIndex].nNextBlock = nBlockIndex;
	MemHeader.nFreeMemBlock = nIndex;
}

template <class T0, class T1, class T2>
VOID *CMemPool<T0, T1, T2>::MemMalloc(T_MEM_HEADER &MemHeader, INT nMemSize)
{
	INT nBlockIndex;
	T_MEM_BLOCK *pMemBlockMap;
	VOID *lpvCreateAddr;
	INT nUsedBlockIndex;

	lpvCreateAddr = NULL;
	pMemBlockMap = MemHeader.pMemBlockMap;
	nBlockIndex = pMemBlockMap[MemHeader.nUnusedMemBlock].nNextBlock;
	while (nBlockIndex != -1)
	{
		// 找到足够的空间
		if (pMemBlockMap[nBlockIndex].nBlockSize >= nMemSize)
		{
			BYTE *lpbyMemObjectAddr;

			nUsedBlockIndex = GetFreeBlock(MemHeader);
			if (nUsedBlockIndex == -1)
			{
				break;
			}

			lpvCreateAddr = pMemBlockMap[nBlockIndex].lpvMemObjectAddr;
			lpbyMemObjectAddr = (BYTE *)lpvCreateAddr;
			lpbyMemObjectAddr += nMemSize;
			pMemBlockMap[nBlockIndex].lpvMemObjectAddr = lpbyMemObjectAddr;
			pMemBlockMap[nBlockIndex].nBlockSize -= nMemSize;

			pMemBlockMap[nUsedBlockIndex].lpvMemObjectAddr = lpvCreateAddr;
			pMemBlockMap[nUsedBlockIndex].nNextBlock = -1;
			pMemBlockMap[nUsedBlockIndex].nBlockSize = nMemSize;

			InsertUsedBlock(MemHeader, nUsedBlockIndex);

			//释放掉
			if (pMemBlockMap[nBlockIndex].nBlockSize == 0)
			{
				FreeBlock(MemHeader, nBlockIndex);
			}

			break;
		}

		nBlockIndex = pMemBlockMap[nBlockIndex].nNextBlock;
	}

	return lpvCreateAddr;
}

template<class T0, class T1, class T2>
VOID CMemPool<T0, T1, T2>::InsertUsedBlock(T_MEM_HEADER &MemHeader, INT nIndex)
{
	T_MEM_BLOCK *pMemBlockMap;
	INT nPreBlockIndex, nUsedBlockIndex;

	pMemBlockMap 	= MemHeader.pMemBlockMap;
	nPreBlockIndex 	= MemHeader.nUsedMemBlock;
	nUsedBlockIndex = pMemBlockMap[nPreBlockIndex].nNextBlock;

	while (nUsedBlockIndex != -1)
	{
		if (BLOCK_UP_BANDARY(pMemBlockMap, nIndex) <= BLOCK_DOWN_BANDARY(pMemBlockMap, nUsedBlockIndex))
		{
			break;
		}

		nPreBlockIndex = nUsedBlockIndex;
		nUsedBlockIndex = pMemBlockMap[nUsedBlockIndex].nNextBlock;
	}

	pMemBlockMap[nPreBlockIndex].nNextBlock = nIndex;
	pMemBlockMap[nIndex].nNextBlock = nUsedBlockIndex;
}

template<class T0, class T1, class T2>
VOID CMemPool<T0, T1, T2>::Release()
{
	Free();
	delete this;
}

template<class T0, class T1, class T2>
VOID CMemPool<T0, T1, T2>::Free()
{
	INT i;
		VOID *lpvMemBaseAddr;

		for (i = 0; i < m_VecMemHeader.size(); ++ i)
		{
			lpvMemBaseAddr = m_VecMemHeader[i].lpvMemBaseAddr;
			delete []lpvMemBaseAddr;
			delete [](m_VecMemHeader[i].pMemBlockMap);
		}

		m_VecMemHeader.clear();

}


使用类模板来实现,btw, 关于类模板说明一下,类模板,没有.cpp, 只有.h来实现,类模板是不参与编译的,只有实例了类之后才能够编译,所有只能够为.h文件

期间遇到的问题:

1.类模板只能够实现.h文件

2.你有可能申请的内存大于内存头规定的大小(m_nGrows),这个时候出现生请失败,所以动态更改了m_nGrows(比较生请的大小)

3.没有线程安全保护机制

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值