头文件 MemoryPool.h:
#ifndef _MEMORY_POOL_H_
#define _MEMORY_POOL_H_
#ifndef NULL
#define NULL 0
#endif
typedef unsigned char Uint8;
typedef unsigned short Uint16;
typedef unsigned long Uint32;
struct MemoryBlock
{
Uint32 m_nSize; //数据缓冲总字节数
Uint16 m_nFree; //空闲元素的个数
Uint16 m_nFirst; //第一个空闲元素的索引
MemoryBlock* m_pNext; //下一个数据分配单元的地址
Uint8 m_aData[1]; //元素数组的第一个元素
static void* operator new(size_t size, Uint16 nUnitCount, Uint16 nUnitSize)
{
return ::operator new(sizeof(MemoryBlock) + nUnitCount * nUnitSize);
}
static void operator delete(void* p, size_t)
{
::operator delete(p);
}
MemoryBlock(Uint16 nUnitCount = 1, Uint16 nUnitSize = 0);
~MemoryBlock() {}
};
class MemoryPool
{
private:
MemoryBlock* m_pBlock;
Uint16 m_nUnitSize; //元素大小
Uint16 m_nInitSize; //内存池初始元素的个数
Uint16 m_nGrowSize; //内存池空间不够后每次元素增长的个数
public:
MemoryPool(Uint16 nUnitSize, Uint16 nInitSize = 1024, Uint16 nGrowSize = 256);
~MemoryPool();
void* Alloc();
void Free(void* p);
};
#endif //~_MEMORY_POOL_H_
实现文件 MemoryPool.cpp
#include "MemoryPool.h"
#define MEMORYPOOL_ALIGNMENT 4
/*-------------- MemoryBlock --------------*/
MemoryBlock::MemoryBlock(Uint16 nUnitCount, Uint16 nUnitSize) :
m_nSize(nUnitCount * nUnitSize),
m_nFree(nUnitCount - 1),
m_nFirst(1),
m_pNext(NULL)
{
Uint8* pData = m_aData;
for(Uint16 i = 1; i < nUnitCount; i++)
{
*reinterpret_cast<Uint16*>(pData) = i;
pData += nUnitSize;
}
}
/*-------------- MemoryPool --------------*/
MemoryPool::MemoryPool(Uint16 nUnitSize, Uint16 nInitSize/* = 1024*/, Uint16 nGrowSize/* = 256*/) :
m_pBlock(NULL),
m_nInitSize(nInitSize),
m_nGrowSize(nGrowSize)
{
if(nUnitSize > 4)
m_nUnitSize = (nUnitSize + (MEMORYPOOL_ALIGNMENT-1)) & ~(MEMORYPOOL_ALIGNMENT-1);
else if(nUnitSize <= 2)
m_nUnitSize = 2;
else
m_nUnitSize = 4;
}
void* MemoryPool::Alloc()
{
if(m_pBlock == NULL)
{
//......
m_pBlock = new(m_nInitSize, m_nUnitSize) MemoryBlock(m_nInitSize, m_nUnitSize);
if(!m_pBlock)
return NULL;
return (void*)m_pBlock->m_aData;
}
MemoryBlock* pMyBlock = m_pBlock;
while(pMyBlock && !pMyBlock->m_nFree)
pMyBlock = pMyBlock->m_pNext;
if(pMyBlock)
{
Uint8* pFree = pMyBlock->m_aData + (pMyBlock->m_nFirst * m_nUnitSize);
pMyBlock->m_nFirst = *(Uint16*)pFree;
pMyBlock->m_nFree--;
return (void*)pFree;
}
else
{
if(!m_nGrowSize)
return NULL;
pMyBlock = new(m_nGrowSize, m_nUnitSize) MemoryBlock(m_nGrowSize, m_nUnitSize);
if(!pMyBlock)
return NULL;
pMyBlock->m_pNext = m_pBlock;
m_pBlock = pMyBlock;
return (void*)(pMyBlock->m_aData);
}
}
void MemoryPool::Free(void* pFree)
{
//.....
MemoryBlock* pMyBlock = m_pBlock;
MemoryBlock* pPrevBlock = m_pBlock;
while((pMyBlock->m_aData > pFree) || (pFree >= (pMyBlock->m_aData + pMyBlock->m_nSize)))
{
//.....
pPrevBlock = pMyBlock;
pMyBlock = pMyBlock->m_pNext;
if(!pMyBlock)
return ;
}
pMyBlock->m_nFree++;
*((Uint16*)pFree) = pMyBlock->m_nFirst;
pMyBlock->m_nFirst = (Uint16)(((Uint32)pFree - (Uint32)pMyBlock->m_aData) / m_nUnitSize); //计算并设置当前释放的是第几个内存单元块的位置
if((Uint32)pMyBlock->m_nFree*(Uint32)m_nUnitSize == pMyBlock->m_nSize)
{
//所有内存单元块全部被释放 .....
pPrevBlock->m_pNext = pMyBlock->m_pNext;
delete pMyBlock;
}
}
MemoryPool::~MemoryPool()
{
MemoryBlock* pMyBlock = m_pBlock;
while(pMyBlock)
{
//.....
MemoryBlock* pDelBlock = pMyBlock;
pMyBlock = pMyBlock->m_pNext;
delete pDelBlock;
}
}
测试代码:
#include <stdio.h>
#include <tchar.h>
#include "MemoryPool.h"
#define _CRTDBG_MAP_ALLOC 1
#include <crtdbg.h>
#include <Windows.h>
const int MALLOC_COUNT = 500 * 10000;
int _tmain(int argc, _TCHAR* argv[])
{
MemoryPool* pPool = new MemoryPool(5, 20000, 20000);
Uint32 start = GetTickCount();
for(int i = 0; i < MALLOC_COUNT; i++)
{
void* pp = pPool->Alloc();
}
Uint32 tick0 = GetTickCount() - start;
start = GetTickCount();
for(int i = 0; i < MALLOC_COUNT; i++)
{
void* pp = malloc(5);
}
Uint32 tick1 = GetTickCount() - start;
printf("Mempool Alloc used time: %d\n", tick0);
printf("System malloc used time: %d\n", tick1);
void* p1 = pPool->Alloc();
void* p2 = pPool->Alloc();
void* p3 = pPool->Alloc();
void* p4 = pPool->Alloc();
void* p5 = pPool->Alloc();
pPool->Free(0);
pPool->Free(p1);
pPool->Free(p2);
pPool->Free(p5);
pPool->Free(p3);
p1 = pPool->Alloc();
delete pPool;
//_CrtDumpMemoryLeaks();
return 0;
}
测试结果:
测试环境: Win7 + VS2008 + Release + 2GRAM + Intel(R) Core(TM)2 Quad CPU Q8300 @ 2.50GHz