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

来源:互联网 发布:阿里云资源库 编辑:程序博客网 时间:2024/05/22 06:38

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

 

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:winxu81@gmail.com
msn:wx_bird@msn.com
qq:44203734


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/preja2erec/archive/2008/09/09/2903282.aspx

原创粉丝点击