SMemoryChunk.h
#ifndef __SMEMORYCHUNK_H__ #define __SMEMORYCHUNK_H__
typedef unsigned char TByte ;
struct SMemoryChunk { TByte *Data; //数据 std::size_t DataSize; //该内存块的总大小 std::size_t UsedSize; //实际使用的大小 bool IsAllocationChunk; SMemoryChunk *Next; //指向链表中下一个块的指针。 };
#endif
IMemoryBlock.h
#ifndef __IMEMORYBLOCK_H__ #define __IMEMORYBLOCK_H__
class IMemoryBlock { public : virtual ~IMemoryBlock() {};
virtual void *GetMemory(const std::size_t &sMemorySize) = 0; virtual void FreeMemory(void *ptrMemoryBlock, const std::size_t &sMemoryBlockSize) = 0;
};
#endif
CMemoryPool.h
#ifndef __CMEMORYPOOL_H__ #define __CMEMORYPOOL_H__
#include "IMemoryBlock.h" #include "SMemoryChunk.h"
static const std::size_t DEFAULT_MEMORY_POOL_SIZE = 1000;//初始内存池的大小 static const std::size_t DEFAULT_MEMORY_CHUNK_SIZE = 128;//Chunk的大小 static const std::size_t DEFAULT_MEMORY_SIZE_TO_ALLOCATE = DEFAULT_MEMORY_CHUNK_SIZE * 2;
class CMemoryPool : public IMemoryBlock { public: CMemoryPool(const std::size_t &sInitialMemoryPoolSize = DEFAULT_MEMORY_POOL_SIZE, const std::size_t &sMemoryChunkSize = DEFAULT_MEMORY_CHUNK_SIZE, const std::size_t &sMinimalMemorySizeToAllocate = DEFAULT_MEMORY_SIZE_TO_ALLOCATE, bool bSetMemoryData = false );
virtual ~CMemoryPool();
//从内存池中申请内存 virtual void* GetMemory(const std::size_t &sMemorySize); virtual void FreeMemory(void *ptrMemoryBlock, const std::size_t &sMemoryBlockSize); private: //申请内存OS bool AllocateMemory(const std::size_t &sMemorySize); void FreeAllAllocatedMemory(); SMemoryChunk* FindChunkHoldingPointerTo(void *ptrMemoryBlock); void FreeChunks(SMemoryChunk *ptrChunk); //计算可以分多少块 unsigned int CalculateNeededChunks(const std::size_t &sMemorySize);
//计算内存池最合适的大小 std::size_t CMemoryPool::CalculateBestMemoryBlockSize(const std::size_t &sRequestedMemoryBlockSize); //建立链表.每个结点Data指针指向内存池中的内存地址 bool LinkChunksToData(SMemoryChunk* ptrNewChunks, unsigned int uiChunkCount, TByte* ptrNewMemBlock); //重新计算块(Chunk)的大小1024--896--768--640--512------------ bool RecalcChunkMemorySize(SMemoryChunk* ptrChunk, unsigned int uiChunkCount); SMemoryChunk* SetChunkDefaults(SMemoryChunk *ptrChunk);
//搜索链表找到一个能够持有被申请大小的内存块(Chunk).如果它返回NULL,那么在内存池中没有可用的内存 SMemoryChunk* FindChunkSuitableToHoldMemory(const std::size_t &sMemorySize);
std::size_t MaxValue(const std::size_t &sValueA, const std::size_t &sValueB) const; void SetMemoryChunkValues(SMemoryChunk *ptrChunk, const std::size_t &sMemBlockSize);
SMemoryChunk* SkipChunks(SMemoryChunk *ptrStartChunk, unsigned int uiChunksToSkip); void DeallocateAllChunks();
private:
SMemoryChunk *m_ptrFirstChunk; SMemoryChunk *m_ptrLastChunk; SMemoryChunk *m_ptrCursorChunk;
std::size_t m_sTotalMemoryPoolSize; //内存池的总大小 std::size_t m_sUsedMemoryPoolSize; //以使用内存的大小 std::size_t m_sFreeMemoryPoolSize; //可用内存的大小
std::size_t m_sMemoryChunkSize; //块(Chunk)的大小 unsigned int m_uiMemoryChunkCount; //块(Chunk)的数量 unsigned int m_uiObjectCount;
bool m_bSetMemoryData ; std::size_t m_sMinimalMemorySizeToAllocate;
};
#endif
CMemoryPool.cpp
#include "stdafx.h" #include "CMemorypool.h"
#include <math.h> #include <assert.h>
static const int FREEED_MEMORY_CONTENT = 0xAA;//填充释放的内存 static const int NEW_ALLOCATED_MEMORY_CONTENT = 0xFF;
CMemoryPool::CMemoryPool(const std::size_t &sInitialMemoryPoolSize, const std::size_t &sMemoryChunkSize, const std::size_t &sMinimalMemorySizeToAllocate, bool bSetMemoryData) { m_ptrFirstChunk = NULL; m_ptrLastChunk = NULL; m_ptrCursorChunk = NULL;
m_sTotalMemoryPoolSize = 0; m_sUsedMemoryPoolSize = 0; m_sFreeMemoryPoolSize = 0;
m_sMemoryChunkSize = sMemoryChunkSize; m_uiMemoryChunkCount = 0; m_uiObjectCount = 0;
m_bSetMemoryData = !bSetMemoryData; m_sMinimalMemorySizeToAllocate = sMinimalMemorySizeToAllocate;
AllocateMemory(sInitialMemoryPoolSize); }
CMemoryPool::~CMemoryPool() { FreeAllAllocatedMemory(); DeallocateAllChunks();
assert((m_uiObjectCount == 0) && "警告:内存-泄露:你没有释放全部申请的内存"); }
void CMemoryPool::FreeAllAllocatedMemory() { SMemoryChunk *ptrChunk = m_ptrFirstChunk; while(ptrChunk) { if(ptrChunk->IsAllocationChunk) { free(((void *) (ptrChunk->Data))); } ptrChunk = ptrChunk->Next; } }
void CMemoryPool::DeallocateAllChunks() { SMemoryChunk *ptrChunk = m_ptrFirstChunk; SMemoryChunk *ptrChunkToDelete = NULL; while(ptrChunk) { if(ptrChunk->IsAllocationChunk) { if(ptrChunkToDelete) { free(((void *) ptrChunkToDelete)); } ptrChunkToDelete = ptrChunk; } ptrChunk = ptrChunk->Next; } }
void* CMemoryPool::GetMemory(const std::size_t &sMemorySize) { std::size_t sBestMemBlockSize = CalculateBestMemoryBlockSize(sMemorySize); SMemoryChunk* ptrChunk = NULL; while(!ptrChunk) {
ptrChunk = FindChunkSuitableToHoldMemory(sBestMemBlockSize);
//ptrChunk等于NULL表示内存池内存不够用 if(!ptrChunk) { sBestMemBlockSize = MaxValue(sBestMemBlockSize, CalculateBestMemoryBlockSize(m_sMinimalMemorySizeToAllocate)); //从OS申请更多的内存 AllocateMemory(sBestMemBlockSize); } } //下面是找到可用的块(Chunk)代码 m_sUsedMemoryPoolSize += sBestMemBlockSize; m_sFreeMemoryPoolSize -= sBestMemBlockSize; m_uiObjectCount++; //标记该块(Chunk)已用 SetMemoryChunkValues(ptrChunk, sBestMemBlockSize);
return ((void *) ptrChunk->Data); }
void CMemoryPool::FreeMemory(void *ptrMemoryBlock, const std::size_t &sMemoryBlockSize) { SMemoryChunk *ptrChunk = FindChunkHoldingPointerTo(ptrMemoryBlock); if(ptrChunk) { FreeChunks(ptrChunk); } else { assert(false && "ERROR : Requested Pointer not in Memory Pool"); } assert((m_uiObjectCount > 0) && "ERROR : Request to delete more Memory then allocated."); m_uiObjectCount--;
}
void CMemoryPool::FreeChunks(SMemoryChunk *ptrChunk) {
SMemoryChunk *ptrCurrentChunk = ptrChunk ; unsigned int uiChunkCount = CalculateNeededChunks(ptrCurrentChunk->UsedSize); for(unsigned int i = 0; i < uiChunkCount; i++) { if(ptrCurrentChunk) {
if(m_bSetMemoryData) { memset(((void *) ptrCurrentChunk->Data), FREEED_MEMORY_CONTENT, m_sMemoryChunkSize) ; }
ptrCurrentChunk->UsedSize = 0;
m_sUsedMemoryPoolSize -= m_sMemoryChunkSize; ptrCurrentChunk = ptrCurrentChunk->Next; } } }
SMemoryChunk *CMemoryPool::FindChunkHoldingPointerTo(void *ptrMemoryBlock) { SMemoryChunk *ptrTempChunk = m_ptrFirstChunk; while(ptrTempChunk) { if(ptrTempChunk->Data == ((TByte *) ptrMemoryBlock)) { break; } ptrTempChunk = ptrTempChunk->Next; } return ptrTempChunk; }
bool CMemoryPool::AllocateMemory(const std::size_t &sMemorySize) { //计算可以分多少块(1000 / 128 = 8) unsigned int uiNeededChunks = CalculateNeededChunks(sMemorySize);
//当内存池的初始大小为1000字节,块(Chunk)大小128字节,分8块还差24字节.怎么办? //解决方案:多申请24字节 std::size_t sBestMemBlockSize = CalculateBestMemoryBlockSize(sMemorySize);
//向OS申请内存 TByte *ptrNewMemBlock = (TByte*) malloc(sBestMemBlockSize);
//分配一个结构体SmemoryChunk的数组来管理内存块 SMemoryChunk *ptrNewChunks = (SMemoryChunk*) malloc((uiNeededChunks * sizeof(SMemoryChunk)));
m_sTotalMemoryPoolSize += sBestMemBlockSize; m_sFreeMemoryPoolSize += sBestMemBlockSize; m_uiMemoryChunkCount += uiNeededChunks;
if(m_bSetMemoryData) { memset(((void *) ptrNewMemBlock), NEW_ALLOCATED_MEMORY_CONTENT, sBestMemBlockSize); }
return LinkChunksToData(ptrNewChunks, uiNeededChunks, ptrNewMemBlock);
}
unsigned int CMemoryPool::CalculateNeededChunks(const std::size_t &sMemorySize) { float f = (float) (((float)sMemorySize) / ((float)m_sMemoryChunkSize)); return ((unsigned int) ceil(f)); }
std::size_t CMemoryPool::CalculateBestMemoryBlockSize(const std::size_t &sRequestedMemoryBlockSize) { unsigned int uiNeededChunks = CalculateNeededChunks(sRequestedMemoryBlockSize); return std::size_t((uiNeededChunks * m_sMemoryChunkSize)); }
bool CMemoryPool::LinkChunksToData(SMemoryChunk* ptrNewChunks, unsigned int uiChunkCount, TByte* ptrNewMemBlock) {
SMemoryChunk *ptrNewChunk = NULL; unsigned int uiMemOffSet = 0; bool bAllocationChunkAssigned = false; for(unsigned int i = 0; i < uiChunkCount; i++) { //建立链表 if(!m_ptrFirstChunk) { m_ptrFirstChunk = SetChunkDefaults(&(ptrNewChunks[0])); m_ptrLastChunk = m_ptrFirstChunk; m_ptrCursorChunk = m_ptrFirstChunk; } else { ptrNewChunk = SetChunkDefaults(&(ptrNewChunks[i])); m_ptrLastChunk->Next = ptrNewChunk; m_ptrLastChunk = ptrNewChunk; } //根据块(Chunk)的大小计算下一块的内存偏移地址 uiMemOffSet = (i * ((unsigned int) m_sMemoryChunkSize));
//结点指向内存偏移地址 m_ptrLastChunk->Data = &(ptrNewMemBlock[uiMemOffSet]);
if(!bAllocationChunkAssigned) { m_ptrLastChunk->IsAllocationChunk = true; bAllocationChunkAssigned = true; } }
return RecalcChunkMemorySize(m_ptrFirstChunk, m_uiMemoryChunkCount);
}
bool CMemoryPool::RecalcChunkMemorySize(SMemoryChunk *ptrChunk, unsigned int uiChunkCount) { unsigned int uiMemOffSet = 0 ; for(unsigned int i = 0; i < uiChunkCount; i++) { if(ptrChunk) { uiMemOffSet = (i * ((unsigned int) m_sMemoryChunkSize)) ; ptrChunk->DataSize = (((unsigned int) m_sTotalMemoryPoolSize) - uiMemOffSet); ptrChunk = ptrChunk->Next; } else { assert(false && "Error : ptrChunk == NULL"); return false; } } return true; }
SMemoryChunk* CMemoryPool::SetChunkDefaults(SMemoryChunk* ptrChunk) { if(ptrChunk) { ptrChunk->Data = NULL; ptrChunk->DataSize = 0; ptrChunk->UsedSize = 0; ptrChunk->IsAllocationChunk = false; ptrChunk->Next = NULL; } return ptrChunk; }
//这里还没看明白 SMemoryChunk *CMemoryPool::FindChunkSuitableToHoldMemory(const std::size_t &sMemorySize) { unsigned int uiChunksToSkip = 0; bool bContinueSearch = true; SMemoryChunk *ptrChunk = m_ptrCursorChunk; for(unsigned int i = 0; i < m_uiMemoryChunkCount; i++) { if(ptrChunk) { if(ptrChunk == m_ptrLastChunk) { ptrChunk = m_ptrFirstChunk; }
if(ptrChunk->DataSize >= sMemorySize) { if(ptrChunk->UsedSize == 0) { m_ptrCursorChunk = ptrChunk; return ptrChunk; } } uiChunksToSkip = CalculateNeededChunks(ptrChunk->UsedSize); if(uiChunksToSkip == 0) uiChunksToSkip = 1; ptrChunk = SkipChunks(ptrChunk, uiChunksToSkip); } else { bContinueSearch = false; } } return NULL; }
std::size_t CMemoryPool::MaxValue(const std::size_t &sValueA, const std::size_t &sValueB) const { if(sValueA > sValueB) { return sValueA; } return sValueB; }
void CMemoryPool::SetMemoryChunkValues(SMemoryChunk *ptrChunk, const std::size_t &sMemBlockSize) { if((ptrChunk)) { ptrChunk->UsedSize = sMemBlockSize; } else { assert(false && "Error : Invalid NULL-Pointer passed"); } }
SMemoryChunk *CMemoryPool::SkipChunks(SMemoryChunk *ptrStartChunk, unsigned int uiChunksToSkip) { SMemoryChunk *ptrCurrentChunk = ptrStartChunk; for(unsigned int i = 0; i < uiChunksToSkip; i++) { if(ptrCurrentChunk) { ptrCurrentChunk = ptrCurrentChunk->Next; } else {
assert(false && "Error : Chunk == NULL was not expected."); break ; } } return ptrCurrentChunk; }
测试方法:
// 111.cpp : 定义控制台应用程序的入口点。 //
#include "stdafx.h"
#include "CMemoryPool.h"
CMemoryPool* g_pMemPool = NULL;
class testMemoryPool { public: testMemoryPool(){ } virtual ~testMemoryPool(){ } void *operator new(std::size_t ObjectSize) { return g_pMemPool->GetMemory(ObjectSize) ; }
void operator delete(void *ptrObject, std::size_t ObjectSize) { g_pMemPool->FreeMemory(ptrObject, ObjectSize) ; }
public: char a[512]; bool b; long c; };//sizeof(32);
int _tmain(int argc, _TCHAR* argv[]) {
g_pMemPool = new CMemoryPool();
testMemoryPool* test = new testMemoryPool(); if(test){ delete test; test = NULL; }
if(g_pMemPool) delete g_pMemPool ;
return 0; }
|
|