下图直观显示了内存池的概念
内存池的设计逻辑
内存池的实现基于重载运算符重载new和delete函数
Alloctor.h
#ifndef _ALLOCTOR_H_
#define _ALLOCTOR_H_
void* operator new(size_t size);
void operator delete(void* p);
void* operator new[](size_t size);
void operator delete[](void* p);
void* mem_alloc(size_t size);
void mem_free(void* p);
#endif // !_ALLOCTOR_H_
Alloctor.cpp
#include"Alloctor.h"
#include"MemoryMgr.hpp"
void* operator new(size_t nSize)
{
return MemoryMgr::Instance().allocMem(nSize);
}
void operator delete(void* p)
{
MemoryMgr::Instance().freeMem(p);
}
void* operator new[](size_t nSize)
{
return MemoryMgr::Instance().allocMem(nSize);
}
void operator delete[](void* p)
{
MemoryMgr::Instance().freeMem(p);
}
void* mem_alloc(size_t size)
{
return malloc(size);
}
void mem_free(void* p)
{
free(p);
}
其中具体的内存配分,使用一个单例模式的内存管理类MemoryMgr实现
内存池的实现,基本单元是使用一个内存块
class MemoryAlloc;
//内存块 最小单元
class MemoryBlock
{
public:
//所属大内存块(池)
MemoryAlloc* pAlloc;
//下一块位置
MemoryBlock* pNext;
//内存块编号
int nID;
//引用次数
int nRef;
//是否在内存池中
bool bPool;
private:
//预留
char c1;
char c2;
char c3;
};
内存池的实现
//内存池
class MemoryAlloc
{
protected:
//内存池地址
char* _pBuf;
//头部内存单元
MemoryBlock* _pHeader;
//内存单元的大小
size_t _nSzie;
//内存单元的数量
size_t _nBlockSzie;
std::mutex _mutex;
};
内存池的构造函数与析构函数
MemoryAlloc()
{
_pBuf = nullptr;
_pHeader = nullptr;
_nSzie = 0;
_nBlockSzie = 0;
xPrintf("MemoryAlloc\n");
}
~MemoryAlloc()
{
if (_pBuf)
free(_pBuf);
}
//初始化
void initMemory()
{
xPrintf("initMemory:_nSzie=%d,_nBlockSzie=%d\n", _nSzie, _nBlockSzie);
//断言
assert(nullptr == _pBuf);
if (_pBuf)
return;
//计算内存池的大小
size_t realSzie = _nSzie + sizeof(MemoryBlock);
size_t bufSize = realSzie*_nBlockSzie;
//向系统申请池的内存
_pBuf = (char*)malloc(bufSize);
//初始化内存池
_pHeader = (MemoryBlock*)_pBuf;
_pHeader->bPool = true;
_pHeader->nID = 0;
_pHeader->nRef = 0;
_pHeader->pAlloc = this;
_pHeader->pNext = nullptr;
//遍历内存块进行初始化
MemoryBlock* pTemp1 = _pHeader;
for (size_t n = 1; n < _nBlockSzie; n++)
{
MemoryBlock* pTemp2 = (MemoryBlock*)(_pBuf + (n* realSzie));
pTemp2->bPool = true;
pTemp2->nID = n;
pTemp2->nRef = 0;
pTemp2->pAlloc = this;
pTemp2->pNext = nullptr;
pTemp1->pNext = pTemp2;
pTemp1 = pTemp2;
}
}
释放和回收内存
//申请内存
void* allocMemory(size_t nSize)
{
std::lock_guard<std::mutex> lg(_mutex);
if (!_pBuf)
{
initMemory();
}
MemoryBlock* pReturn = nullptr;
if (nullptr == _pHeader)
{
pReturn = (MemoryBlock*)malloc(nSize+sizeof(MemoryBlock));
pReturn->bPool = false;
pReturn->nID = -1;
pReturn->nRef = 1;
pReturn->pAlloc = nullptr;
pReturn->pNext = nullptr;
}
else {
pReturn = _pHeader;
_pHeader = _pHeader->pNext;
assert(0 == pReturn->nRef);
pReturn->nRef = 1;
}
xPrintf("allocMem: %llx, id=%d, size=%d\n", pReturn, pReturn->nID, nSize);
return ((char*)pReturn + sizeof(MemoryBlock));
}
//释放内存
void freeMemory(void* pMem)
{
MemoryBlock* pBlock = (MemoryBlock*)( (char*)pMem - sizeof(MemoryBlock));
assert(1 == pBlock->nRef);
if (pBlock->bPool)
{
std::lock_guard<std::mutex> lg(_mutex);
if (--pBlock->nRef != 0)
{
return;
}
pBlock->pNext = _pHeader;
_pHeader = pBlock;
}
else {
if (--pBlock->nRef != 0)
{
return;
}
free(pBlock);
}
}