C++内存池

原文地址 http://www.cppblog.com/d3d/archive/2008/11/28/68097.aspx

SMemoryChunk.h

  1. #ifndef __SMEMORYCHUNK_H__
  2. #define __SMEMORYCHUNK_H__
  3. typedef unsigned char TByte ;
  4. struct SMemoryChunk
  5. {
  6.   TByte *Data; //数据
  7.   std::size_t DataSize; //该内存块的总大小
  8.   std::size_t UsedSize; //实际使用的大小
  9.   bool IsAllocationChunk;
  10.   SMemoryChunk *Next; //指向链表中下一个块的指针。
  11. };
  12. #endif

IMemoryBlock.h
  1. #ifndef __IMEMORYBLOCK_H__
  2. #define __IMEMORYBLOCK_H__
  3. class IMemoryBlock
  4. {
  5.   public :
  6.     virtual ~IMemoryBlock() {};
  7.     virtual void *GetMemory(const std::size_t &sMemorySize) = 0;
  8.     virtual void FreeMemory(void *ptrMemoryBlock, const std::size_t &sMemoryBlockSize) = 0;
  9. };
  10. #endif

CMemoryPool.h
  1. #ifndef __CMEMORYPOOL_H__
  2. #define __CMEMORYPOOL_H__
  3. #include "IMemoryBlock.h"
  4. #include "SMemoryChunk.h"
  5. static const std::size_t DEFAULT_MEMORY_POOL_SIZE = 1000;//初始内存池的大小
  6. static const std::size_t DEFAULT_MEMORY_CHUNK_SIZE = 128;//Chunk的大小
  7. static const std::size_t DEFAULT_MEMORY_SIZE_TO_ALLOCATE = DEFAULT_MEMORY_CHUNK_SIZE * 2;
  8. class CMemoryPool : public IMemoryBlock
  9. {
  10. public:
  11.     CMemoryPool(const std::size_t &sInitialMemoryPoolSize = DEFAULT_MEMORY_POOL_SIZE,
  12.                 const std::size_t &sMemoryChunkSize = DEFAULT_MEMORY_CHUNK_SIZE,
  13.                 const std::size_t &sMinimalMemorySizeToAllocate = DEFAULT_MEMORY_SIZE_TO_ALLOCATE,
  14.                 bool bSetMemoryData = false
  15.                 );
  16.     virtual ~CMemoryPool();
  17.     //从内存池中申请内存
  18.     virtual void* GetMemory(const std::size_t &sMemorySize);
  19.     virtual void FreeMemory(void *ptrMemoryBlock, const std::size_t &sMemoryBlockSize);
  20. private:
  21.     //申请内存OS
  22.     bool AllocateMemory(const std::size_t &sMemorySize);
  23.     void FreeAllAllocatedMemory();
  24.     SMemoryChunk* FindChunkHoldingPointerTo(void *ptrMemoryBlock);
  25.     void FreeChunks(SMemoryChunk *ptrChunk);
  26.     //计算可以分多少块
  27.   unsigned int CalculateNeededChunks(const std::size_t &sMemorySize);
  28.     //计算内存池最合适的大小
  29.     std::size_t CMemoryPool::CalculateBestMemoryBlockSize(const std::size_t &sRequestedMemoryBlockSize); 
  30.     //建立链表.每个结点Data指针指向内存池中的内存地址
  31.     bool LinkChunksToData(SMemoryChunk* ptrNewChunks, unsigned int uiChunkCount, TByte* ptrNewMemBlock);
  32.    //重新计算块(Chunk)的大小1024--896--768--640--512------------
  33.     bool RecalcChunkMemorySize(SMemoryChunk* ptrChunk, unsigned int uiChunkCount);  
  34.     SMemoryChunk* SetChunkDefaults(SMemoryChunk *ptrChunk); 
  35.     //搜索链表找到一个能够持有被申请大小的内存块(Chunk).如果它返回NULL,那么在内存池中没有可用的内存
  36.     SMemoryChunk* FindChunkSuitableToHoldMemory(const std::size_t &sMemorySize);
  37.     std::size_t MaxValue(const std::size_t &sValueA, const std::size_t &sValueB) const; 
  38.     void SetMemoryChunkValues(SMemoryChunk *ptrChunk, const std::size_t &sMemBlockSize);
  39.    SMemoryChunk* SkipChunks(SMemoryChunk *ptrStartChunk, unsigned int uiChunksToSkip);    
  40.     void DeallocateAllChunks();
  41. private:
  42.     SMemoryChunk *m_ptrFirstChunk;
  43.     SMemoryChunk *m_ptrLastChunk;
  44.     SMemoryChunk *m_ptrCursorChunk;
  45.     std::size_t m_sTotalMemoryPoolSize; //内存池的总大小
  46.     std::size_t m_sUsedMemoryPoolSize; //以使用内存的大小
  47.     std::size_t m_sFreeMemoryPoolSize; //可用内存的大小
  48.     std::size_t m_sMemoryChunkSize; //块(Chunk)的大小    
  49.      unsigned int m_uiMemoryChunkCount; //块(Chunk)的数量
  50.     unsigned int m_uiObjectCount;
  51.     bool m_bSetMemoryData ;
  52.     std::size_t m_sMinimalMemorySizeToAllocate;
  53. };
  54. #endif

CMemoryPool.cpp 

  1. #include "stdafx.h"
  2. #include "CMemorypool.h"
  3. #include <math.h>
  4. #include <assert.h>
  5. static const int FREEED_MEMORY_CONTENT = 0xAA;//填充释放的内存
  6. static const int NEW_ALLOCATED_MEMORY_CONTENT = 0xFF;
  7. CMemoryPool::CMemoryPool(const std::size_t &sInitialMemoryPoolSize,
  8.                          const std::size_t &sMemoryChunkSize,
  9.                          const std::size_t &sMinimalMemorySizeToAllocate,
  10.                          bool bSetMemoryData)
  11. {
  12.     m_ptrFirstChunk = NULL;
  13.     m_ptrLastChunk = NULL;
  14.     m_ptrCursorChunk = NULL;
  15.     m_sTotalMemoryPoolSize = 0;
  16.     m_sUsedMemoryPoolSize = 0;
  17.     m_sFreeMemoryPoolSize = 0;
  18.      m_sMemoryChunkSize = sMemoryChunkSize;
  19.     m_uiMemoryChunkCount = 0;
  20.     m_uiObjectCount = 0;
  21.     m_bSetMemoryData = !bSetMemoryData;
  22.     m_sMinimalMemorySizeToAllocate = sMinimalMemorySizeToAllocate;
  23.     AllocateMemory(sInitialMemoryPoolSize);
  24. }
  25. CMemoryPool::~CMemoryPool()
  26. {
  27.     FreeAllAllocatedMemory();
  28.     DeallocateAllChunks();
  29.     assert((m_uiObjectCount == 0) && "警告:内存-泄露:你没有释放全部申请的内存");
  30. }
  31. void CMemoryPool::FreeAllAllocatedMemory()
  32. {
  33.     SMemoryChunk *ptrChunk = m_ptrFirstChunk;
  34.     while(ptrChunk)
  35.     {
  36.         if(ptrChunk->IsAllocationChunk)
  37.         {
  38.             free(((void *) (ptrChunk->Data)));
  39.         }
  40.         ptrChunk = ptrChunk->Next;
  41.     }
  42. }
  43. void CMemoryPool::DeallocateAllChunks()
  44. {
  45.     SMemoryChunk *ptrChunk = m_ptrFirstChunk;
  46.     SMemoryChunk *ptrChunkToDelete = NULL;
  47.     while(ptrChunk)
  48.     {
  49.         if(ptrChunk->IsAllocationChunk)
  50.         {
  51.             if(ptrChunkToDelete)
  52.             {
  53.                 free(((void *) ptrChunkToDelete));
  54.             }
  55.             ptrChunkToDelete = ptrChunk;       
  56.         }
  57.         ptrChunk = ptrChunk->Next;
  58.     }
  59. }
  60. void* CMemoryPool::GetMemory(const std::size_t &sMemorySize)
  61. {
  62.     std::size_t sBestMemBlockSize = CalculateBestMemoryBlockSize(sMemorySize);
  63.     SMemoryChunk* ptrChunk = NULL;
  64.     while(!ptrChunk)
  65.     {
  66.         ptrChunk = FindChunkSuitableToHoldMemory(sBestMemBlockSize);
  67.         //ptrChunk等于NULL表示内存池内存不够用
  68.         if(!ptrChunk)
  69.         {
  70.             sBestMemBlockSize = MaxValue(sBestMemBlockSize, CalculateBestMemoryBlockSize(m_sMinimalMemorySizeToAllocate));
  71.             //从OS申请更多的内存
  72.             AllocateMemory(sBestMemBlockSize);
  73.         }
  74.     }
  75.     //下面是找到可用的块(Chunk)代码
  76.     m_sUsedMemoryPoolSize += sBestMemBlockSize;
  77.     m_sFreeMemoryPoolSize -= sBestMemBlockSize;
  78.     m_uiObjectCount++;
  79.     //标记该块(Chunk)已用
  80.     SetMemoryChunkValues(ptrChunk, sBestMemBlockSize);
  81.     return ((void *) ptrChunk->Data);
  82. }
  83. void CMemoryPool::FreeMemory(void *ptrMemoryBlock, const std::size_t &sMemoryBlockSize)
    {
  84.     SMemoryChunk *ptrChunk = FindChunkHoldingPointerTo(ptrMemoryBlock);
  85.     if(ptrChunk)
  86.     {
  87.         FreeChunks(ptrChunk);
  88.     }
  89.     else
  90.     {
  91.         assert(false && "ERROR : Requested Pointer not in Memory Pool");
  92.     }
        assert((m_uiObjectCount > 0) && "ERROR : Request to delete more Memory then allocated.");
        m_uiObjectCount--;
  93. }
  94. void CMemoryPool::FreeChunks(SMemoryChunk *ptrChunk)
  95. {
  96.     SMemoryChunk *ptrCurrentChunk = ptrChunk ;
  97.     unsigned int uiChunkCount = CalculateNeededChunks(ptrCurrentChunk->UsedSize);
  98.     for(unsigned int i = 0; i < uiChunkCount; i++)
  99.     {
  100.         if(ptrCurrentChunk)
  101.         {
  102.             if(m_bSetMemoryData)
  103.             {
  104.                 memset(((void *) ptrCurrentChunk->Data), FREEED_MEMORY_CONTENT, m_sMemoryChunkSize) ;
  105.             }
  106.             ptrCurrentChunk->UsedSize = 0;
               m_sUsedMemoryPoolSize -= m_sMemoryChunkSize;
  107.             ptrCurrentChunk = ptrCurrentChunk->Next;
  108.         }
  109.     }
  110. }
  111. SMemoryChunk *CMemoryPool::FindChunkHoldingPointerTo(void *ptrMemoryBlock)
  112. {
        SMemoryChunk *ptrTempChunk = m_ptrFirstChunk;
  113.     while(ptrTempChunk)
  114.     {
  115.         if(ptrTempChunk->Data == ((TByte *) ptrMemoryBlock))
  116.         {
  117.             break;
  118.         }
  119.         ptrTempChunk = ptrTempChunk->Next;
  120.     }
  121.     return ptrTempChunk;
  122. }
  123. bool CMemoryPool::AllocateMemory(const std::size_t &sMemorySize)
  124. {
  125.     //计算可以分多少块(1000 / 128 = 8)
  126.     unsigned int uiNeededChunks = CalculateNeededChunks(sMemorySize);
  127.     //当内存池的初始大小为1000字节,块(Chunk)大小128字节,分8块还差24字节.怎么办?
  128.     //解决方案:多申请24字节
  129.     std::size_t sBestMemBlockSize = CalculateBestMemoryBlockSize(sMemorySize);
  130.     
  131.      //向OS申请内存
  132.     TByte *ptrNewMemBlock = (TByte*) malloc(sBestMemBlockSize);
  133.     //分配一个结构体SmemoryChunk的数组来管理内存块
  134.     SMemoryChunk *ptrNewChunks = (SMemoryChunk*) malloc((uiNeededChunks * sizeof(SMemoryChunk)));
  135.     m_sTotalMemoryPoolSize += sBestMemBlockSize;
  136.     m_sFreeMemoryPoolSize += sBestMemBlockSize;
  137.     m_uiMemoryChunkCount += uiNeededChunks;
  138.     if(m_bSetMemoryData)
  139.     {
  140.         memset(((void *) ptrNewMemBlock), NEW_ALLOCATED_MEMORY_CONTENT, sBestMemBlockSize);
  141.     }
  142.     return LinkChunksToData(ptrNewChunks, uiNeededChunks, ptrNewMemBlock);
  143. }
  144. unsigned int CMemoryPool::CalculateNeededChunks(const std::size_t &sMemorySize)
    {
        float f = (float) (((float)sMemorySize) / ((float)m_sMemoryChunkSize));
  145.     return ((unsigned int) ceil(f));
  146. }
  147. std::size_t CMemoryPool::CalculateBestMemoryBlockSize(const std::size_t &sRequestedMemoryBlockSize)
  148. {
  149.     unsigned int uiNeededChunks = CalculateNeededChunks(sRequestedMemoryBlockSize);
  150.     return std::size_t((uiNeededChunks * m_sMemoryChunkSize));
  151. }
  152. bool CMemoryPool::LinkChunksToData(SMemoryChunk* ptrNewChunks, unsigned int uiChunkCount, TByte* ptrNewMemBlock)
    {
  153.     SMemoryChunk *ptrNewChunk = NULL;
  154.     unsigned int uiMemOffSet = 0;
  155.     bool bAllocationChunkAssigned = false;
  156.     for(unsigned int i = 0; i < uiChunkCount; i++)
  157.     {
  158.         //建立链表
  159.         if(!m_ptrFirstChunk)
  160.         {
  161.             m_ptrFirstChunk = SetChunkDefaults(&(ptrNewChunks[0]));
  162.             m_ptrLastChunk = m_ptrFirstChunk;
  163.             m_ptrCursorChunk = m_ptrFirstChunk;
  164.         }
  165.         else
  166.         {
  167.             ptrNewChunk = SetChunkDefaults(&(ptrNewChunks[i]));
  168.             m_ptrLastChunk->Next = ptrNewChunk;
  169.             m_ptrLastChunk = ptrNewChunk;
  170.         }
  171.         //根据块(Chunk)的大小计算下一块的内存偏移地址
  172.         uiMemOffSet = (i * ((unsigned int) m_sMemoryChunkSize));
  173.         //结点指向内存偏移地址
  174.         m_ptrLastChunk->Data = &(ptrNewMemBlock[uiMemOffSet]);
  175.         if(!bAllocationChunkAssigned)
  176.         {
  177.             m_ptrLastChunk->IsAllocationChunk = true;
  178.             bAllocationChunkAssigned = true;
  179.         }
  180.     }
  181.     return RecalcChunkMemorySize(m_ptrFirstChunk, m_uiMemoryChunkCount);
  182. }
  183. bool CMemoryPool::RecalcChunkMemorySize(SMemoryChunk *ptrChunk, unsigned int uiChunkCount)
  184. {
  185.     unsigned int uiMemOffSet = 0 ;
  186.     for(unsigned int i = 0; i < uiChunkCount; i++)
  187.     {
  188.         if(ptrChunk)
  189.         {
  190.             uiMemOffSet = (i * ((unsigned int) m_sMemoryChunkSize)) ;
  191.             ptrChunk->DataSize = (((unsigned int) m_sTotalMemoryPoolSize) - uiMemOffSet);
  192.             ptrChunk = ptrChunk->Next;
  193.         }
  194.         else
  195.         {
  196.             assert(false && "Error : ptrChunk == NULL");
  197.             return false;
  198.         }
  199.     }
  200.     return true;
  201. }
  202. SMemoryChunk* CMemoryPool::SetChunkDefaults(SMemoryChunk* ptrChunk)
  203. {
        if(ptrChunk)
  204.     {
  205.         ptrChunk->Data = NULL;
  206.         ptrChunk->DataSize = 0;
  207.         ptrChunk->UsedSize = 0;
  208.         ptrChunk->IsAllocationChunk = false;
  209.         ptrChunk->Next = NULL;
  210.     }
  211.     return ptrChunk;
  212. }
  213. //这里还没看明白
  214. SMemoryChunk *CMemoryPool::FindChunkSuitableToHoldMemory(const std::size_t &sMemorySize)
  215. {
  216.     unsigned int uiChunksToSkip = 0;
  217.     bool bContinueSearch = true;
  218.     SMemoryChunk *ptrChunk = m_ptrCursorChunk;
  219.     for(unsigned int i = 0; i < m_uiMemoryChunkCount; i++)
        {
            if(ptrChunk)
            {
                if(ptrChunk == m_ptrLastChunk)
                {
                    ptrChunk = m_ptrFirstChunk;
                }
  220.             if(ptrChunk->DataSize >= sMemorySize)
                {
                    if(ptrChunk->UsedSize == 0)
                    {
                        m_ptrCursorChunk = ptrChunk;
                        return ptrChunk;
                    }
  221.             }
  222.             uiChunksToSkip = CalculateNeededChunks(ptrChunk->UsedSize);
  223.             if(uiChunksToSkip == 0)
  224.                   uiChunksToSkip = 1;
  225.             ptrChunk = SkipChunks(ptrChunk, uiChunksToSkip);
  226.         }
  227.         else
  228.         {
  229.             bContinueSearch = false;
  230.         }
  231.     }
  232.     return NULL;
  233. }
  234. std::size_t CMemoryPool::MaxValue(const std::size_t &sValueA, const std::size_t &sValueB) const
  235. {
  236.     if(sValueA > sValueB)
  237.     {
  238.         return sValueA;
  239.     }
  240.     return sValueB;
  241. }
  242. void CMemoryPool::SetMemoryChunkValues(SMemoryChunk *ptrChunk, const std::size_t &sMemBlockSize)
  243. {
  244.     if((ptrChunk))
  245.     {
  246.         ptrChunk->UsedSize = sMemBlockSize;
  247.     }
  248.     else
  249.     {
  250.         assert(false && "Error : Invalid NULL-Pointer passed");
  251.     }
  252. }
  253. SMemoryChunk *CMemoryPool::SkipChunks(SMemoryChunk *ptrStartChunk, unsigned int uiChunksToSkip)
  254. {
  255.     SMemoryChunk *ptrCurrentChunk = ptrStartChunk;
  256.     for(unsigned int i = 0; i < uiChunksToSkip; i++)
  257.     {
  258.         if(ptrCurrentChunk)
  259.         {
  260.             ptrCurrentChunk = ptrCurrentChunk->Next;
  261.         }
  262.         else
  263.         {
  264.             assert(false && "Error : Chunk == NULL was not expected.");
  265.             break ;
  266.         }
  267.     }
  268.     return ptrCurrentChunk;
  269. }


测试方法:

  1. // 111.cpp : 定义控制台应用程序的入口点。
    #include "stdafx.h"
    #include "CMemoryPool.h"
  2. CMemoryPool* g_pMemPool = NULL;

  3. class testMemoryPool
  4. {
  5. public:
  6.     testMemoryPool(){
  7.     }
  8.     virtual ~testMemoryPool(){
  9.     }
  10.     void *operator new(std::size_t ObjectSize)
  11.     {
  12.         return g_pMemPool->GetMemory(ObjectSize) ;
        }
  13.     void operator delete(void *ptrObject, std::size_t ObjectSize)
  14.     {
  15.         g_pMemPool->FreeMemory(ptrObject, ObjectSize) ;
  16.     }
  17. public:
  18.     char a[512];
  19.     bool b;
  20.     long c;
  21. };//sizeof(32);
  22. int _tmain(int argc, _TCHAR* argv[])
    {
        g_pMemPool = new CMemoryPool();
        testMemoryPool* test = new testMemoryPool();
  23.     if(test){
  24.         delete test;
  25.         test = NULL;
  26.     }
  27.     if(g_pMemPool)
  28.         delete g_pMemPool ;
        return 0;
  29. }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值