原文地址 http://www.cppblog.com/d3d/archive/2008/11/28/68097.aspx
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;
- }
阅读(1406) | 评论(0) | 转发(1) |