天天看点

简单变长内存池实现的实现

实现了变长内存池的申请和回收,其中回收包括在某种特定的情况下回收给系统

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