Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1685057
  • 博文数量: 347
  • 博客积分: 9328
  • 博客等级: 中将
  • 技术积分: 2680
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-29 23:45
文章分类

全部博文(347)

文章存档

2016年(1)

2013年(4)

2012年(207)

2011年(85)

2010年(50)

分类: C/C++

2011-01-09 19:20:09

原文地址 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.     
  21. private:
  22.     //申请内存OS

  23.     bool AllocateMemory(const std::size_t &sMemorySize);
  24.     void FreeAllAllocatedMemory();
  25.     SMemoryChunk* FindChunkHoldingPointerTo(void *ptrMemoryBlock);
  26.     void FreeChunks(SMemoryChunk *ptrChunk);
  27.     //计算可以分多少块

  28.     unsigned int CalculateNeededChunks(const std::size_t &sMemorySize);

  29.     //计算内存池最合适的大小

  30.     std::size_t CMemoryPool::CalculateBestMemoryBlockSize(const std::size_t &sRequestedMemoryBlockSize);
  31.     
  32.     //建立链表.每个结点Data指针指向内存池中的内存地址

  33.     bool LinkChunksToData(SMemoryChunk* ptrNewChunks, unsigned int uiChunkCount, TByte* ptrNewMemBlock);
  34.     
  35.     //重新计算块(Chunk)的大小1024--896--768--640--512------------

  36.     bool RecalcChunkMemorySize(SMemoryChunk* ptrChunk, unsigned int uiChunkCount);
  37.     
  38.     SMemoryChunk* SetChunkDefaults(SMemoryChunk *ptrChunk);
  39.     

  40.     //搜索链表找到一个能够持有被申请大小的内存块(Chunk).如果它返回NULL,那么在内存池中没有可用的内存

  41.     SMemoryChunk* FindChunkSuitableToHoldMemory(const std::size_t &sMemorySize);

  42.     std::size_t MaxValue(const std::size_t &sValueA, const std::size_t &sValueB) const;
  43.     
  44.     void SetMemoryChunkValues(SMemoryChunk *ptrChunk, const std::size_t &sMemBlockSize);

  45.     SMemoryChunk* SkipChunks(SMemoryChunk *ptrStartChunk, unsigned int uiChunksToSkip);
  46.     
  47.     void DeallocateAllChunks();

  48. private:

  49.     SMemoryChunk *m_ptrFirstChunk;
  50.     SMemoryChunk *m_ptrLastChunk;
  51.     SMemoryChunk *m_ptrCursorChunk;

  52.     std::size_t m_sTotalMemoryPoolSize; //内存池的总大小

  53.     std::size_t m_sUsedMemoryPoolSize; //以使用内存的大小

  54.     std::size_t m_sFreeMemoryPoolSize; //可用内存的大小


  55.     std::size_t m_sMemoryChunkSize; //块(Chunk)的大小

  56.     unsigned int m_uiMemoryChunkCount; //块(Chunk)的数量

  57.     unsigned int m_uiObjectCount;

  58.     bool m_bSetMemoryData ;
  59.     std::size_t m_sMinimalMemorySizeToAllocate;


  60. };

  61. #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. {
  85.     SMemoryChunk *ptrChunk = FindChunkHoldingPointerTo(ptrMemoryBlock);
  86.     if(ptrChunk)
  87.     {
  88.         FreeChunks(ptrChunk);
  89.     }
  90.     else
  91.     {
  92.         assert(false && "ERROR : Requested Pointer not in Memory Pool");
  93.     }
  94.     assert((m_uiObjectCount > 0) && "ERROR : Request to delete more Memory then allocated.");
  95.     m_uiObjectCount--;

  96. }

  97. void CMemoryPool::FreeChunks(SMemoryChunk *ptrChunk)
  98. {

  99.     SMemoryChunk *ptrCurrentChunk = ptrChunk ;
  100.     unsigned int uiChunkCount = CalculateNeededChunks(ptrCurrentChunk->UsedSize);
  101.     for(unsigned int i = 0; i < uiChunkCount; i++)
  102.     {
  103.         if(ptrCurrentChunk)
  104.         {

  105.             if(m_bSetMemoryData)
  106.             {
  107.                 memset(((void *) ptrCurrentChunk->Data), FREEED_MEMORY_CONTENT, m_sMemoryChunkSize) ;
  108.             }

  109.             ptrCurrentChunk->UsedSize = 0;

  110.             m_sUsedMemoryPoolSize -= m_sMemoryChunkSize;
  111.             ptrCurrentChunk = ptrCurrentChunk->Next;
  112.         }
  113.     }
  114. }

  115. SMemoryChunk *CMemoryPool::FindChunkHoldingPointerTo(void *ptrMemoryBlock)
  116. {
  117.     SMemoryChunk *ptrTempChunk = m_ptrFirstChunk;
  118.     while(ptrTempChunk)
  119.     {
  120.         if(ptrTempChunk->Data == ((TByte *) ptrMemoryBlock))
  121.         {
  122.             break;
  123.         }
  124.         ptrTempChunk = ptrTempChunk->Next;
  125.     }
  126.     return ptrTempChunk;
  127. }

  128. bool CMemoryPool::AllocateMemory(const std::size_t &sMemorySize)
  129. {
  130.     //计算可以分多少块(1000 / 128 = 8)

  131.     unsigned int uiNeededChunks = CalculateNeededChunks(sMemorySize);

  132.     //当内存池的初始大小为1000字节,块(Chunk)大小128字节,分8块还差24字节.怎么办?

  133.     //解决方案:多申请24字节

  134.     std::size_t sBestMemBlockSize = CalculateBestMemoryBlockSize(sMemorySize);

  135.     //向OS申请内存

  136.     TByte *ptrNewMemBlock = (TByte*) malloc(sBestMemBlockSize);

  137.     //分配一个结构体SmemoryChunk的数组来管理内存块

  138.     SMemoryChunk *ptrNewChunks = (SMemoryChunk*) malloc((uiNeededChunks * sizeof(SMemoryChunk)));


  139.     m_sTotalMemoryPoolSize += sBestMemBlockSize;
  140.     m_sFreeMemoryPoolSize += sBestMemBlockSize;
  141.     m_uiMemoryChunkCount += uiNeededChunks;


  142.     if(m_bSetMemoryData)
  143.     {
  144.         memset(((void *) ptrNewMemBlock), NEW_ALLOCATED_MEMORY_CONTENT, sBestMemBlockSize);
  145.     }

  146.     return LinkChunksToData(ptrNewChunks, uiNeededChunks, ptrNewMemBlock);

  147. }

  148. unsigned int CMemoryPool::CalculateNeededChunks(const std::size_t &sMemorySize)
  149. {
  150.     float f = (float) (((float)sMemorySize) / ((float)m_sMemoryChunkSize));
  151.     return ((unsigned int) ceil(f));
  152. }

  153. std::size_t CMemoryPool::CalculateBestMemoryBlockSize(const std::size_t &sRequestedMemoryBlockSize)
  154. {
  155.     unsigned int uiNeededChunks = CalculateNeededChunks(sRequestedMemoryBlockSize);
  156.     return std::size_t((uiNeededChunks * m_sMemoryChunkSize));
  157. }

  158. bool CMemoryPool::LinkChunksToData(SMemoryChunk* ptrNewChunks, unsigned int uiChunkCount, TByte* ptrNewMemBlock)
  159. {

  160.     SMemoryChunk *ptrNewChunk = NULL;
  161.     unsigned int uiMemOffSet = 0;
  162.     bool bAllocationChunkAssigned = false;
  163.     for(unsigned int i = 0; i < uiChunkCount; i++)
  164.     {
  165.         //建立链表

  166.         if(!m_ptrFirstChunk)
  167.         {
  168.             m_ptrFirstChunk = SetChunkDefaults(&(ptrNewChunks[0]));
  169.             m_ptrLastChunk = m_ptrFirstChunk;
  170.             m_ptrCursorChunk = m_ptrFirstChunk;
  171.         }
  172.         else
  173.         {
  174.             ptrNewChunk = SetChunkDefaults(&(ptrNewChunks[i]));
  175.             m_ptrLastChunk->Next = ptrNewChunk;
  176.             m_ptrLastChunk = ptrNewChunk;
  177.         }
  178.         //根据块(Chunk)的大小计算下一块的内存偏移地址

  179.         uiMemOffSet = (i * ((unsigned int) m_sMemoryChunkSize));

  180.         //结点指向内存偏移地址

  181.         m_ptrLastChunk->Data = &(ptrNewMemBlock[uiMemOffSet]);


  182.         if(!bAllocationChunkAssigned)
  183.         {
  184.             m_ptrLastChunk->IsAllocationChunk = true;
  185.             bAllocationChunkAssigned = true;
  186.         }
  187.     }


  188.     return RecalcChunkMemorySize(m_ptrFirstChunk, m_uiMemoryChunkCount);

  189. }


  190. bool CMemoryPool::RecalcChunkMemorySize(SMemoryChunk *ptrChunk, unsigned int uiChunkCount)
  191. {
  192.     unsigned int uiMemOffSet = 0 ;
  193.     for(unsigned int i = 0; i < uiChunkCount; i++)
  194.     {
  195.         if(ptrChunk)
  196.         {
  197.             uiMemOffSet = (i * ((unsigned int) m_sMemoryChunkSize)) ;
  198.             ptrChunk->DataSize = (((unsigned int) m_sTotalMemoryPoolSize) - uiMemOffSet);
  199.             ptrChunk = ptrChunk->Next;
  200.         }
  201.         else
  202.         {
  203.             assert(false && "Error : ptrChunk == NULL");
  204.             return false;
  205.         }
  206.     }
  207.     return true;
  208. }

  209. SMemoryChunk* CMemoryPool::SetChunkDefaults(SMemoryChunk* ptrChunk)
  210. {
  211.     if(ptrChunk)
  212.     {
  213.         ptrChunk->Data = NULL;
  214.         ptrChunk->DataSize = 0;
  215.         ptrChunk->UsedSize = 0;
  216.         ptrChunk->IsAllocationChunk = false;
  217.         ptrChunk->Next = NULL;
  218.     }
  219.     return ptrChunk;
  220. }

  221. //这里还没看明白

  222. SMemoryChunk *CMemoryPool::FindChunkSuitableToHoldMemory(const std::size_t &sMemorySize)
  223. {
  224.     unsigned int uiChunksToSkip = 0;
  225.     bool bContinueSearch = true;
  226.     SMemoryChunk *ptrChunk = m_ptrCursorChunk;
  227.     for(unsigned int i = 0; i < m_uiMemoryChunkCount; i++)
  228.     {
  229.         if(ptrChunk)
  230.         {
  231.             if(ptrChunk == m_ptrLastChunk)
  232.             {
  233.                 ptrChunk = m_ptrFirstChunk;
  234.             }

  235.             if(ptrChunk->DataSize >= sMemorySize)
  236.             {
  237.                 if(ptrChunk->UsedSize == 0)
  238.                 {
  239.                     m_ptrCursorChunk = ptrChunk;
  240.                     return ptrChunk;
  241.                 }
  242.             }
  243.             uiChunksToSkip = CalculateNeededChunks(ptrChunk->UsedSize);
  244.             if(uiChunksToSkip == 0) uiChunksToSkip = 1;
  245.             ptrChunk = SkipChunks(ptrChunk, uiChunksToSkip);
  246.         }
  247.         else
  248.         {
  249.             bContinueSearch = false;
  250.         }
  251.     }
  252.     return NULL;
  253. }

  254. std::size_t CMemoryPool::MaxValue(const std::size_t &sValueA, const std::size_t &sValueB) const
  255. {
  256.     if(sValueA > sValueB)
  257.     {
  258.         return sValueA;
  259.     }
  260.     return sValueB;
  261. }

  262. void CMemoryPool::SetMemoryChunkValues(SMemoryChunk *ptrChunk, const std::size_t &sMemBlockSize)
  263. {
  264.     if((ptrChunk))
  265.     {
  266.         ptrChunk->UsedSize = sMemBlockSize;
  267.     }
  268.     else
  269.     {
  270.         assert(false && "Error : Invalid NULL-Pointer passed");
  271.     }
  272. }

  273. SMemoryChunk *CMemoryPool::SkipChunks(SMemoryChunk *ptrStartChunk, unsigned int uiChunksToSkip)
  274. {
  275.     SMemoryChunk *ptrCurrentChunk = ptrStartChunk;
  276.     for(unsigned int i = 0; i < uiChunksToSkip; i++)
  277.     {
  278.         if(ptrCurrentChunk)
  279.         {
  280.             ptrCurrentChunk = ptrCurrentChunk->Next;
  281.         }
  282.         else
  283.         {

  284.             assert(false && "Error : Chunk == NULL was not expected.");
  285.             break ;
  286.         }
  287.     }
  288.     return ptrCurrentChunk;
  289. }


测试方法:

  1. // 111.cpp : 定义控制台应用程序的入口点。

  2. //


  3. #include "stdafx.h"

  4. #include "CMemoryPool.h"

  5. CMemoryPool* g_pMemPool = NULL;

  6. class testMemoryPool
  7. {
  8. public:
  9.     testMemoryPool(){
  10.     }
  11.     virtual ~testMemoryPool(){
  12.     }
  13.     void *operator new(std::size_t ObjectSize)
  14.     {
  15.         return g_pMemPool->GetMemory(ObjectSize) ;
  16.     }

  17.     void operator delete(void *ptrObject, std::size_t ObjectSize)
  18.     {
  19.         g_pMemPool->FreeMemory(ptrObject, ObjectSize) ;
  20.     }

  21. public:
  22.     char a[512];
  23.     bool b;
  24.     long c;
  25. };//sizeof(32);



  26. int _tmain(int argc, _TCHAR* argv[])
  27. {

  28.     g_pMemPool = new CMemoryPool();

  29.     testMemoryPool* test = new testMemoryPool();
  30.     if(test){
  31.         delete test;
  32.         test = NULL;
  33.     }

  34.     if(g_pMemPool)
  35.         delete g_pMemPool ;

  36.     return 0;
  37. }
阅读(1355) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~