實作了變長記憶體池的申請和回收,其中回收包括在某種特定的情況下回收給系統
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[email protected]com
msn:wx_bir[email protected]
qq:44203734