zoukankan      html  css  js  c++  java
  • 【转】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.     
    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. }
    阅读(786) | 评论(0) | 转发(1) |
    给主人留下些什么吧!~~
    评论热议
  • 相关阅读:
    GCD实现多个定时器,完美避过NSTimer的三大缺陷(RunLoop、Thread、Leaks)
    iOS适配UIViewView/WKWebView,H5生成长图,仿微信进度条
    翻译jquery官方的插件制作方法
    javascript引用和赋值
    薯片公司真实JS面试题(乐视TV)
    caller、call、apply、callee的用法和意思
    常用javascript类型判断
    Git 常用命令笔记(不定期持续记录)
    sublime text2 emmet 安装
    hash"#"
  • 原文地址:https://www.cnblogs.com/black/p/5171927.html
Copyright © 2011-2022 走看看