读书人

【转】C++内存储器池

发布时间: 2012-12-28 10:29:04 作者: rapoo

【转】C++内存池

原文地址 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;}

?测试代码:

#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;}

?

读书人网 >C++

热点推荐