实现了变长内存池的申请和回收,其中回收包括在某种特定的情况下回收给系统
h文件:GenMemPool.h
#ifndef _SKIFFER_GENMEMPOOL_H
#define _SKIFFER_GENMEMPOOL_H
#include <stdlib.h>
//按此值向上取整申请所需内存大小,例如,如果申请内存为13字节,则返回14字节的内存
#define MEMPOOL_ALIGNMENT (2)
#define MAX_MEN_LIMIT (1<<16)
#pragma pack(1)
struct STMemBlk
{
//此内存块中内存单元的个数
unsigned short m_wAllUnitNum;
//空闲单元的个数
unsigned short m_wFreeUnitNum;
//第一个空闲单元的单元编号
unsigned short m_wFirstFreeUnitNo;
//next 指针
STMemBlk *m_pNextBlk;
//以上为内存块结构头部信息
//以下为外界可用内存
char m_pData[0];
STMemBlk()
{
m_wAllUnitNum = 0;
m_wFreeUnitNum = 0;
m_wFirstFreeUnitNo = 0;
m_pNextBlk = NULL;
}
~STMemBlk()
{
}
void* operator new(size_t wBlkSize, unsigned short wUnitNum, unsigned short wUnitSize)
{
return ::operator new (sizeof(STMemBlk) + wUnitNum * wUnitSize);
}
void operator delete(void *p)
{
::operator delete (p);
}
void operator delete(void *p, unsigned short wUnitNum, unsigned short wUnitSize)
{
::operator delete (p);
}
};
struct STInitParam
{
//每个内存单元的大小
unsigned short m_wUnitSize;
//第一次初始化时,每一块内存中,需要申请的内存单元个数
unsigned short m_wInitUnitNum;
//内存不足时,每一块内存中,需要申请的内存单元个数
unsigned short m_wGrowUnitNum;
STInitParam()
{
m_wUnitSize = 0;
m_wInitUnitNum = 0;
m_wGrowUnitNum = 0;
}
};
#pragma pack()
class CMemPool
{
public:
CMemPool();
~CMemPool();
//初始化
void Init(unsigned short wUnitSize, unsigned short wInitUnitNum, unsigned short wGrowUnitNum);
//分配内存块中的一个内存单元
void* Alloc();
//释放一个内存单元
void Free(void *pUnit);
//预处理块
void* PreAlloc(STMemBlk *pstMemBlk, int dwBlkFlag);
private:
//内存池头结点
STMemBlk *m_pstMemBlkHead;
//内存池块信息
STInitParam m_stInitBlkInfo;
};
class CVarLenMemPool
{
public:
CVarLenMemPool();
~CVarLenMemPool();
//申请dwMemSize字节的内存
void* Alloc(unsigned int dwMemSize);
//释放内存
void Free(void *p);
//初始化n个内存单元长度不同的固定内存池
void Init(const STInitParam *pstInitParam, unsigned short wMemPoolNum);
//退出
void Exit();
//向上对齐
void UpAlignment(STInitParam *pstInitParam, unsigned short wMemPoolNum);
public:
//内存单元大小不同的内存池
CMemPool **m_ppMemPoolList;
//n个内存单元长度不同的固定内存池
STInitParam *m_pstInitParam;
//内存池个数
unsigned short m_wMemPoolNum;
//最大的内存单元大小
unsigned short m_wMaxUnitSize;
};
#endif
.cpp文件:GenMemPool.cpp
#include "GenMemPool.h"
#include <string.h>
CMemPool::CMemPool()
{
m_pstMemBlkHead = NULL;
memset(&m_stInitBlkInfo, 0 , sizeof(m_stInitBlkInfo));
}
CMemPool::~CMemPool()
{
}
void CMemPool::Init(unsigned short wUnitSize, unsigned short wInitUnitNum, unsigned short wGrowUnitNum)
{
if(wUnitSize <= 4)
{
wUnitSize = 4;
}
else
{
wUnitSize = (wUnitSize + (MEMPOOL_ALIGNMENT - 1)) & ~(MEMPOOL_ALIGNMENT - 1);
}
m_stInitBlkInfo.m_wUnitSize = wUnitSize;
m_stInitBlkInfo.m_wInitUnitNum = wInitUnitNum;
m_stInitBlkInfo.m_wGrowUnitNum = wGrowUnitNum;
}
void* CMemPool::PreAlloc(STMemBlk *pstMemBlk, int dwBlkFlag)
{
char *pData = NULL;
unsigned short dwUnitNum = 0;
pData = pstMemBlk->m_pData;
if(dwBlkFlag == 1)
{
dwUnitNum = m_stInitBlkInfo.m_wInitUnitNum;
}
else
{
dwUnitNum = m_stInitBlkInfo.m_wGrowUnitNum;
}
pstMemBlk->m_wFreeUnitNum = dwUnitNum - 1;
pstMemBlk->m_wAllUnitNum = dwUnitNum;
pstMemBlk->m_wFirstFreeUnitNo = 1;
for(unsigned short dwUnit = 1; dwUnit < dwUnitNum - 1; ++dwUnit)
{
pData = pstMemBlk->m_pData + dwUnit * m_stInitBlkInfo.m_wUnitSize;
*(unsigned short*)pData = dwUnit + 1;
}
pData = pstMemBlk->m_pData;
return pData;
}
void* CMemPool::Alloc()
{
void *pData = NULL;
STMemBlk *pstMemBlk = NULL;
if(m_pstMemBlkHead == NULL)
{
m_pstMemBlkHead = ::new STMemBlk;
m_pstMemBlkHead->m_pNextBlk = new(m_stInitBlkInfo.m_wInitUnitNum, m_stInitBlkInfo.m_wUnitSize)STMemBlk;
pData = PreAlloc(m_pstMemBlkHead->m_pNextBlk, 1);
}
else
{
pstMemBlk = m_pstMemBlkHead->m_pNextBlk;
while(pstMemBlk != NULL)
{
if(pstMemBlk->m_wFreeUnitNum == 0)
{
pstMemBlk = pstMemBlk->m_pNextBlk;
continue;
}
else
{
break;
}
}
if(NULL == pstMemBlk)
{
pstMemBlk = new(m_stInitBlkInfo.m_wGrowUnitNum, m_stInitBlkInfo.m_wUnitSize)STMemBlk;
pData = PreAlloc(pstMemBlk, 2);
pstMemBlk->m_pNextBlk = m_pstMemBlkHead->m_pNextBlk;
m_pstMemBlkHead->m_pNextBlk = pstMemBlk;
}
else
{
pData = (void*)(pstMemBlk->m_pData + pstMemBlk->m_wFirstFreeUnitNo * m_stInitBlkInfo.m_wUnitSize);
--(pstMemBlk->m_wFreeUnitNum);
pstMemBlk->m_wFirstFreeUnitNo = *(unsigned short*)pData;
}
}
return pData;
}
void CMemPool::Free(void *pUnit)
{
STMemBlk *pstMemBlk = NULL;
STMemBlk *pstMemBlkPre = NULL;
unsigned short dwBlkNo = 0;
pstMemBlkPre = m_pstMemBlkHead;
pstMemBlk = m_pstMemBlkHead->m_pNextBlk;
while(pstMemBlk != NULL)
{
if(((unsigned int)pUnit) > (unsigned int)pstMemBlk &&
(unsigned int)pUnit <
(unsigned int)(pstMemBlk->m_pData + (pstMemBlk->m_wAllUnitNum + 1) * m_stInitBlkInfo.m_wUnitSize))
{
dwBlkNo = ((unsigned int)pUnit - (unsigned int)(pstMemBlk->m_pData))/m_stInitBlkInfo.m_wUnitSize;
break;
}
else
{
pstMemBlkPre = pstMemBlk;
pstMemBlk = pstMemBlk->m_pNextBlk;
}
}
if(pstMemBlk->m_wFreeUnitNum - 1 == pstMemBlk->m_wAllUnitNum)
{
pstMemBlkPre->m_pNextBlk = pstMemBlk->m_pNextBlk;
delete(pstMemBlk);
}
else
{
*(unsigned short*)pUnit = pstMemBlk->m_wFirstFreeUnitNo;
pstMemBlk->m_wFirstFreeUnitNo = dwBlkNo;
++(pstMemBlk->m_wFreeUnitNum);
}
}
CVarLenMemPool::CVarLenMemPool()
{
m_ppMemPoolList = NULL;
m_pstInitParam = NULL;
m_wMemPoolNum = 0;
m_wMaxUnitSize = 0;
}
CVarLenMemPool::~CVarLenMemPool()
{
}
void CVarLenMemPool::Init(const STInitParam *pstInitParam, unsigned short wMemPoolNum)
{
unsigned short wInitIdxBegin = 0;
unsigned short wInitIdxEnd = 0;
m_wMemPoolNum = wMemPoolNum;
m_pstInitParam = new STInitParam[m_wMemPoolNum];
memcpy(m_pstInitParam, pstInitParam, sizeof(*pstInitParam) * wMemPoolNum);
UpAlignment(m_pstInitParam, wMemPoolNum);
m_wMaxUnitSize = 0;
unsigned short i = 0;
for(i = 0; i < m_wMemPoolNum; ++i)
{
if(m_pstInitParam[i].m_wUnitSize > m_wMaxUnitSize)
{
m_wMaxUnitSize = m_pstInitParam[i].m_wUnitSize;
}
}
m_ppMemPoolList = new CMemPool*[m_wMaxUnitSize+1];
for(i = 0; i < m_wMemPoolNum; ++i)
{
CMemPool *pMemPool = new CMemPool;
pMemPool->Init(m_pstInitParam[i].m_wUnitSize, m_pstInitParam[i].m_wInitUnitNum,
m_pstInitParam[i].m_wGrowUnitNum);
wInitIdxEnd = m_pstInitParam[i].m_wUnitSize;
for(unsigned short j = wInitIdxBegin; j <= wInitIdxEnd; ++j)
{
m_ppMemPoolList[j] = pMemPool;
}
wInitIdxBegin = wInitIdxEnd + 1;
}
}
void* CVarLenMemPool::Alloc(unsigned int dwMemSize)
{
void *p = NULL;
if(dwMemSize+2 > m_wMaxUnitSize)
{
p = ::operator new(dwMemSize+2);
*(unsigned short*)p = 0;
}
else
{
p = m_ppMemPoolList[dwMemSize+2]->Alloc();
*(unsigned short*)p = dwMemSize+2;
}
return ((unsigned short*)p+1);
}
void CVarLenMemPool::Free(void *p)
{
unsigned short *pTmp = ((unsigned short*)p)-1;
unsigned short dwSize = *pTmp;
if(0 == dwSize)
{
::operator delete(pTmp);
}
else
{
m_ppMemPoolList[dwSize]->Free(p);
}
}
void CVarLenMemPool::UpAlignment(STInitParam *pstInitParam, unsigned short wMemPoolNum)
{
for(unsigned short wParam; wParam < wMemPoolNum; ++wParam)
{
if(pstInitParam[wParam].m_wUnitSize <= 4)
{
pstInitParam[wParam].m_wUnitSize = 4;
}
else
{
pstInitParam[wParam].m_wUnitSize = (pstInitParam[wParam].m_wUnitSize + (MEMPOOL_ALIGNMENT - 1)) &
~(MEMPOOL_ALIGNMENT - 1);
}
}
}
void CVarLenMemPool::Exit()
{
}
参考论文:http://www.ibm.com/developerworks/cn/linux/l-cn-ppp/index6.html
email:winx