内存池,源码发布

    技术2022-05-19  27

    #pragma once     #include <Windows.h>   #define POOLAPI __fastcall     /*  一个MEMORY_BLOCK的内存大小是SIZE_BLOCK_BYTE  分成COUNT_ALL_BLOCK个块,每个块的大小是SIZE_ONE_BLOCK  当用户申请的内存大小超过SIZE_BLOCK_BYTE时,使用系统函数来分配  */  #define SIZE_ONE_BLOCK      0x00000100                      //内存颗粒度(256Byte)   #define COUNT_ALL_BLOCK     0x000007FD                      //分成几部分   #define SIZE_BLOCK_BYTE (SIZE_ONE_BLOCK * COUNT_ALL_BLOCK)  //默认内存分配大小(511KB)     typedef struct  _MEMPOOL_NODE       //记录使用及剩余量的链表   {       DWORD           Phy_Start;      //起始偏移(相对于内存块)       DWORD           dwAllocateSize; //分配内存大小       _MEMPOOL_NODE   *pNext;         //指向下一节点       BYTE            bUsed;          //是否使用了   }MEMPOOL_NODE, *PMEMPOOL_NODE;     typedef struct  _MEMORY_BLOCK       //内存块数据结构,双向链表   {       PVOID           pAddress;       //内存地址       DWORD           dwRemain;       //尚未使用的内存空间大小       CRITICAL_SECTION m_Critical;    //每一个内存块分配一个临界       PMEMPOOL_NODE   pLink_Allocated;//已分配内存的链表       PMEMPOOL_NODE   pLink_Free;     //尚未使用内存的链表       _MEMORY_BLOCK   *pPrev;         //指向上一节点       _MEMORY_BLOCK   *pNext;         //指向下一节点       _MEMPOOL_NODE   NodeReserved[COUNT_ALL_BLOCK];//存放节点,免得频繁申请释放内存   }MEMORY_BLOCK, *PMEMORY_BLOCK;     class CMemPool   {   public:       CMemPool(void);       ~CMemPool(void);         PVOID   POOLAPI Allocate(DWORD dwSize); //分配内存,失败返回NULL       BOOL    POOLAPI Free(PVOID pAddress);   //释放内存,成功返回非0   #ifdef _DEBUG       void    PrintLink();   #endif   private:       DWORD           m_dwCount;          //计数器(正在操作的线程数)       HANDLE          m_Event_Pause;      //暂停信号,用于清理内存       HANDLE          m_Sign_Kill;       HANDLE          m_hClear;           //清理线程       PMEMORY_BLOCK   m_pBlockHeader;     //头结点       CRITICAL_SECTION m_CS_Block;        //修改BLOCK链表的临界         void    POOLAPI InitializeBlock(PMEMORY_BLOCK pBlock);       void    POOLAPI UnInitializeBlock(PMEMORY_BLOCK pBlock);       static  DWORD   WINAPI  ClearThread(LPVOID pData);       void    POOLAPI InsertNode(PMEMORY_BLOCK pBlock, PMEMPOOL_NODE pNode, BOOL isFreeLink);       void    POOLAPI DeleteNode(PMEMORY_BLOCK pBlock, PMEMPOOL_NODE pNode, BOOL isFreeLink);       void    POOLAPI CombineNode(PMEMORY_BLOCK pBlock);//合并空余空间       PVOID   POOLAPI AllocByBlock(PMEMORY_BLOCK pBlock, DWORD dwSize);//根据BLOCK分配空间       PMEMPOOL_NODE   POOLAPI FindFreeNode(PMEMORY_BLOCK pBlock);     }; 

     

     

     #include "MemPool.h"   #ifdef _DEBUG   #include <stdio.h>   #endif     CMemPool::CMemPool(void)   {       m_dwCount = 0;       m_pBlockHeader = NULL;       InitializeCriticalSection(&m_CS_Block);       m_Event_Pause = CreateEvent(NULL, TRUE, TRUE, NULL);//匿名,手动置信号,初始有信号       m_Sign_Kill = CreateEvent(NULL, TRUE, FALSE, NULL);       m_hClear = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClearThread, this, NULL, NULL);   }     CMemPool::~CMemPool(void)   {       PMEMORY_BLOCK pBlock, pBlockTmp;         SetEvent(m_Sign_Kill);       WaitForSingleObject(m_hClear, INFINITE);       CloseHandle(m_hClear);       CloseHandle(m_Sign_Kill);       CloseHandle(m_Event_Pause);       DeleteCriticalSection(&m_CS_Block);       //回收所有释放的资源       for (pBlock = m_pBlockHeader; pBlock; pBlock = pBlockTmp)       {           pBlockTmp = pBlock->pNext;           UnInitializeBlock(pBlock);       }   }     void CMemPool::InitializeBlock(PMEMORY_BLOCK pBlock)   {       ZeroMemory(pBlock, sizeof(MEMORY_BLOCK));       InitializeCriticalSection(&pBlock->m_Critical);       pBlock->pAddress = VirtualAllocEx(INVALID_HANDLE_VALUE, NULL, SIZE_BLOCK_BYTE, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);       pBlock->pLink_Free = &pBlock->NodeReserved[0];       pBlock->pLink_Free->bUsed = TRUE;       pBlock->pLink_Free->Phy_Start = 0;       pBlock->pLink_Free->dwAllocateSize = SIZE_BLOCK_BYTE;       pBlock->dwRemain = SIZE_BLOCK_BYTE;   }     void CMemPool::UnInitializeBlock(PMEMORY_BLOCK pBlock)   {       if (pBlock->dwRemain < SIZE_BLOCK_BYTE) return;       if (m_pBlockHeader == pBlock)//是头结点       {           m_pBlockHeader = m_pBlockHeader->pNext;           if (m_pBlockHeader) m_pBlockHeader->pPrev = NULL;       }       else//不是头结点       {           pBlock->pPrev->pNext = pBlock->pNext;           if (pBlock->pPrev->pNext) pBlock->pNext->pPrev = pBlock->pPrev;       }       DeleteCriticalSection(&pBlock->m_Critical);       VirtualFreeEx(INVALID_HANDLE_VALUE, pBlock->pAddress, 0, MEM_RELEASE);       VirtualFreeEx(INVALID_HANDLE_VALUE, pBlock, 0, MEM_RELEASE);       return;   }     void CMemPool::InsertNode(PMEMORY_BLOCK pBlock, PMEMPOOL_NODE pNode, BOOL isFreeLink)   {       PMEMPOOL_NODE pCurrNode;         pNode->bUsed = TRUE;       if (isFreeLink)       {           if (pBlock->pLink_Free)           {               pCurrNode = pBlock->pLink_Free;               if (pCurrNode->Phy_Start > pNode->Phy_Start)//NODE最小               {                   pNode->pNext = pBlock->pLink_Free;                   pBlock->pLink_Free = pNode;                   return;               }           }           else//头结点NULL           {               pBlock->pLink_Free = pNode;               pNode->pNext = NULL;               return;           }       }       else//已分配链表       {           if (pBlock->pLink_Allocated)           {               pCurrNode = pBlock->pLink_Allocated;               if (pNode->Phy_Start < pCurrNode->Phy_Start)//NODE最小               {                   pNode->pNext = pBlock->pLink_Allocated;                   pBlock->pLink_Free = pNode;                   return;               }           }           else//头结点NULL           {               pBlock->pLink_Allocated = pNode;               pNode->pNext = NULL;               return;           }       }       for (;pCurrNode->pNext; pCurrNode = pCurrNode->pNext)       {           if (pNode->Phy_Start > pCurrNode->Phy_Start && pNode->Phy_Start < pCurrNode->pNext->Phy_Start)//大于当前的小于下一个           {               pNode->pNext = pCurrNode->pNext;               pCurrNode->pNext = pNode;               return;           }       }       //pNode最大       pCurrNode->pNext = pNode;       pNode->pNext = NULL;       return;   }     void CMemPool::DeleteNode(PMEMORY_BLOCK pBlock, PMEMPOOL_NODE pNode, BOOL isFreeLink)   {       PMEMPOOL_NODE pCurrNode;         if (isFreeLink)       {           if (!pBlock->pLink_Free) return;           pCurrNode = pBlock->pLink_Free;           if (pCurrNode == pNode)//是头结点           {               pBlock->pLink_Free = pCurrNode->pNext;               pNode->bUsed = FALSE;               return;           }       }       else      {           if (!pBlock->pLink_Allocated) return;           pCurrNode = pBlock->pLink_Allocated;           if (pCurrNode == pNode)//是头结点           {               pBlock->pLink_Allocated = pCurrNode->pNext;               pNode->bUsed = FALSE;               return;           }       }       for (; pCurrNode->pNext; pCurrNode = pCurrNode->pNext)       {           if (pCurrNode->pNext == pNode)           {               pCurrNode->pNext = pCurrNode->pNext->pNext;               pNode->bUsed = FALSE;               break;//for           }       }       //难道都没找到???       return;   }     PMEMPOOL_NODE CMemPool::FindFreeNode(PMEMORY_BLOCK pBlock)   {       PMEMPOOL_NODE pRet = NULL;       for (pRet = pBlock->NodeReserved; pRet; pRet++)       {           if (pRet->bUsed == FALSE) break;       }       ZeroMemory(pRet, sizeof(MEMPOOL_NODE));       return pRet;   }     void CMemPool::CombineNode(PMEMORY_BLOCK pBlock)   {       PMEMPOOL_NODE pNode = pBlock->pLink_Free;         while (pNode && pNode->pNext)       {           if (pNode->Phy_Start + pNode->dwAllocateSize == pNode->pNext->Phy_Start)           {               pNode->dwAllocateSize += pNode->pNext->dwAllocateSize;               pNode->pNext->bUsed = FALSE;               pNode->pNext = pNode->pNext->pNext;           }           else          {               pNode = pNode->pNext;           }       }   }     PVOID CMemPool::AllocByBlock(PMEMORY_BLOCK pBlock, DWORD dwSize)   {       PVOID pRet = NULL;       PMEMPOOL_NODE pNode, pNewNode;         for (pNode = pBlock->pLink_Free; pNode; pNode = pNode->pNext)       {           if (pNode->dwAllocateSize >= dwSize)           {               if (pNode->dwAllocateSize == dwSize)               {                   DeleteNode(pBlock, pNode, TRUE);                   InsertNode(pBlock, pNode, FALSE);                   pRet = (PVOID)( (DWORD)pBlock->pAddress + pNode->Phy_Start );                   pBlock->dwRemain -= dwSize;                   break;//for               }               else// >               {                   pNewNode = FindFreeNode(pBlock);                   pNewNode->Phy_Start = pNode->Phy_Start;                   pNode->Phy_Start += dwSize;                   pNewNode->dwAllocateSize = dwSize;                   pNode->dwAllocateSize -= dwSize;                   InsertNode(pBlock, pNewNode, FALSE);                   pRet = (PVOID)( (ULONG)pBlock->pAddress + pNewNode->Phy_Start );                   pBlock->dwRemain -= dwSize;                   break;//for               }           }       }       if (pRet) ZeroMemory(pRet, dwSize);       return pRet;   }     PVOID CMemPool::Allocate(DWORD dwSize)   {       PVOID pRet = NULL;       DWORD dwAllocSize;       PMEMORY_BLOCK pBlock;         if (dwSize <= 0) return pRet;       if (dwSize > SIZE_BLOCK_BYTE) return VirtualAllocEx(INVALID_HANDLE_VALUE, NULL, dwSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);       InterlockedExchangeAdd((PLONG)&m_dwCount, 1);//计数器 + 1       if (WaitForSingleObject(m_Event_Pause, 1) != WAIT_OBJECT_0)//正在整理内存则暂停       {           InterlockedExchangeAdd((PLONG)&m_dwCount, -1);//计数器 - 1           WaitForSingleObject(m_Event_Pause, INFINITE);           InterlockedExchangeAdd((PLONG)&m_dwCount, 1);//计数器 + 1       }       dwAllocSize = dwSize % SIZE_ONE_BLOCK ? dwSize / SIZE_ONE_BLOCK + 1 : dwSize / SIZE_ONE_BLOCK;//SIZE_ONE_BLOCK取整       dwAllocSize *= SIZE_ONE_BLOCK;       for (pBlock = m_pBlockHeader; pBlock; pBlock = pBlock->pNext)       {           if (pBlock->dwRemain >= dwAllocSize)           {               EnterCriticalSection(&pBlock->m_Critical);               pRet = AllocByBlock(pBlock, dwAllocSize);               LeaveCriticalSection(&pBlock->m_Critical);           }       }       if (pRet == NULL)//都没有符合的,新建个BLOCK,继续       {           pBlock = (PMEMORY_BLOCK)VirtualAllocEx(INVALID_HANDLE_VALUE, NULL, sizeof(MEMORY_BLOCK), MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);           InitializeBlock(pBlock);           EnterCriticalSection(&m_CS_Block);           if (m_pBlockHeader)//头前插           {               pBlock->pNext = m_pBlockHeader;               m_pBlockHeader->pPrev = pBlock;               m_pBlockHeader = pBlock;           }           else//头结点NULL           {               m_pBlockHeader = pBlock;           }           LeaveCriticalSection(&m_CS_Block);           EnterCriticalSection(&pBlock->m_Critical);           pRet = AllocByBlock(pBlock, dwAllocSize);//不能再失败了吧           LeaveCriticalSection(&pBlock->m_Critical);       }       InterlockedExchangeAdd((PLONG)&m_dwCount, -1);//计数器 - 1       return pRet;   }     BOOL CMemPool::Free(PVOID pAddress)   {       BOOL bRet = FALSE;       PMEMORY_BLOCK pBlock;       PMEMPOOL_NODE pNode;       DWORD dwPhy;         if (pAddress == NULL) return bRet;       InterlockedExchangeAdd((PLONG)&m_dwCount, 1);//计数器 + 1       if (WaitForSingleObject(m_Event_Pause, 1) != WAIT_OBJECT_0)//正在整理内存则暂停       {           InterlockedExchangeAdd((PLONG)&m_dwCount, -1);//计数器 - 1           WaitForSingleObject(m_Event_Pause, INFINITE);           InterlockedExchangeAdd((PLONG)&m_dwCount, 1);//计数器 + 1       }       EnterCriticalSection(&m_CS_Block);       for (pBlock = m_pBlockHeader; pBlock; pBlock = pBlock->pNext)       {           if ((ULONG)pBlock->pAddress <= (ULONG)pAddress && (ULONG)pBlock->pAddress + SIZE_BLOCK_BYTE > (ULONG)pAddress) break;       }       LeaveCriticalSection(&m_CS_Block);       if (pBlock)//找到了这个BLOCK       {           dwPhy = (ULONG)pAddress - (ULONG)pBlock->pAddress;           EnterCriticalSection(&pBlock->m_Critical);           for (pNode = pBlock->pLink_Allocated; pNode; pNode = pNode->pNext)           {               if (pNode->Phy_Start == dwPhy) break;           }           if (pNode)//找到该节点了           {               pBlock->dwRemain += pNode->dwAllocateSize;               DeleteNode(pBlock, pNode, FALSE);               InsertNode(pBlock, pNode, TRUE);               //整合空闲内存               CombineNode(pBlock);               bRet = TRUE;           }           LeaveCriticalSection(&pBlock->m_Critical);       }       else      {           bRet = VirtualFreeEx(INVALID_HANDLE_VALUE, pAddress, 0, MEM_RELEASE);//都找不到,应该是这个了       }       InterlockedExchangeAdd((PLONG)&m_dwCount, -1);//计数器 - 1       return bRet;   }     DWORD WINAPI CMemPool::ClearThread(LPVOID pData)   {       DWORD dwCount;       PMEMORY_BLOCK pBlock, pBlockTmp;       CMemPool *pThis = (CMemPool *)pData;         while (1)       {   #ifdef _DEBUG           for (dwCount = 0; dwCount < 10 * 5; dwCount++)//5秒   #else           for (dwCount = 0; dwCount < 10 * 60 * 10; dwCount++)//10分钟   #endif           {               if (WaitForSingleObject(pThis->m_Sign_Kill, 100) == WAIT_OBJECT_0) return 0;//有退出信号则EXIT           }           ResetEvent(pThis->m_Event_Pause);           while (InterlockedExchangeAdd((PLONG)&pThis->m_dwCount, 0)) Sleep(0);           for (pBlock = pThis->m_pBlockHeader; pBlock; pBlock = pBlockTmp)           {               pBlockTmp = pBlock->pNext;               pThis->UnInitializeBlock(pBlock);           }           SetEvent(pThis->m_Event_Pause);       }       return -1;   }     /   // Debug   #ifdef _DEBUG   void CMemPool::PrintLink()   {       PMEMORY_BLOCK pBlock;       PMEMPOOL_NODE pNode;       EnterCriticalSection(&m_CS_Block);       for (pBlock = m_pBlockHeader; pBlock; pBlock = pBlock->pNext)       {           printf("[BLOCK]基地址:X 剩余大小:X/n", pBlock->pAddress, pBlock->dwRemain);           for (pNode = pBlock->pLink_Allocated; pNode; pNode = pNode->pNext)           {               printf("[已分配] 起始偏移:X 占用大小:X/n", pNode->Phy_Start, pNode->dwAllocateSize);           }           for (pNode = pBlock->pLink_Free; pNode; pNode = pNode->pNext)           {               printf("[空闲中] 起始偏移:X 占用大小:X/n", pNode->Phy_Start, pNode->dwAllocateSize);           }       }       LeaveCriticalSection(&m_CS_Block);   }   #endif 


    最新回复(0)