穩健記憶體管理:自訂記憶體塊管理類

來源:互聯網
上載者:User

/////////////////////////////////////////////////////////////////
//  自訂記憶體管理器
//
//  [總空閑數(4 byte)]
//  [資料區塊(ItemSize byte)][是否佔用(1 byte)][當前塊索引(4 byte)][下塊索引(4 byte)]
//  [資料區塊(ItemSize byte)][是否佔用(1 byte)][當前塊索引(4 byte)][下塊索引(4 byte)]
//  ......
//  [資料區塊(ItemSize byte)][是否佔用(1 byte)][當前塊索引(4 byte)][下塊索引(4 byte)]
//  [第1空閑塊索引][第2空閑塊索引]......[第N空閑塊索引]
//  塊索引 從1開始
/////////////////////////////////////////////////////////////////

class CMyMemoryManager
{
private:
 int               m_ItemCount;  //總塊數
 int               m_ItemSize;   //每塊位元組數
 int               m_BlockSize;  //每項大小=m_ItemSize+5
 int               m_FreeIndexAddr;//空閑索引區首地址
 LPVOID            pData;        //全域記憶體區首地址
 HANDLE            m_WaitEvent;  //等待事件(空閑記憶體不足時等待)
 CRITICAL_SECTION  m_lock;       //資料互斥鎖

 //初始化記憶體區(預留記憶體區)
 BOOL Init(int iItemSize,int iItemCount);
public:
 CMyMemoryManager(int iItemSize,int iItemCount);
 ~CMyMemoryManager();

 void Lock();
 void UnLock();

 //申請記憶體引用
 LPVOID New(int Len);
 //釋放記憶體引用
 BOOL Delete(LPVOID p);

 //擷取資料區塊位元組數
 int GetItemSize();
 //擷取總塊數
 int GetItemCount();
 //擷取總空閑數
 int GetFreeCount();

 //擷取資料區首地址
 int GetBeginAddr(){return (int)pData;};

};

 

//實現

#include "StdAfx.h"
#include "windows.h"
#include "MyMemoryManager.h"

CMyMemoryManager::CMyMemoryManager(int iItemSize,int iItemCount)
{
 m_WaitEvent =  ::CreateEvent(NULL,TRUE,FALSE,NULL);
 InitializeCriticalSection(&m_lock);

 if (!Init(iItemSize,iItemCount))
  AfxMessageBox("自訂記憶體區開闢失敗!");
};

CMyMemoryManager::~CMyMemoryManager()
{
 //::GlobalUnlock(hData);
 ::GlobalFree(pData);
 DeleteCriticalSection(&m_lock); 
 CloseHandle(m_WaitEvent);
};

//初始化記憶體區(預留記憶體區)
//iItemSize - 每塊位元組數 iItemCount - 總塊數
BOOL CMyMemoryManager::Init(int iItemSize,int iItemCount)
{
 int iIndexAddr;

 m_ItemSize  = iItemSize;
 m_ItemCount = iItemCount;
 m_BlockSize = iItemSize + 9;
 

 pData = ::GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
                    4 + iItemCount * (iItemSize + 9) +
        iItemCount * 4);
 if (!pData) return FALSE;

 //初始化空閑塊資訊
 *((int *)pData) = iItemCount;
 m_FreeIndexAddr = (int)pData + 4 + iItemCount * (iItemSize + 9);
 for(int i=1;i<=m_ItemCount;i++)
 {
  *((int *)(m_FreeIndexAddr + (i-1)*4)) = i; //空閑索引
  iIndexAddr = (int)pData + 4 + (i - 1) * m_BlockSize + m_ItemSize + 1;
  *((int *)iIndexAddr) = i;//各塊索引
 }

 return TRUE;
}

void CMyMemoryManager::Lock()
{
 EnterCriticalSection(&m_lock); 
}

void CMyMemoryManager::UnLock()
{
 LeaveCriticalSection(&m_lock); 
}

//申請記憶體引用
LPVOID CMyMemoryManager::New(int Len)
{
 BOOL blnGet = FALSE;
 int iIndex;
 int iNext = 0;
 int iNeedCount;
 int iFreeCount;
 int iRefAddr;

 LPVOID p = NULL;

 //計算需要申請的塊數
 iNeedCount = (int)(Len / m_ItemSize);
 if (iNeedCount * m_ItemSize < Len) iNeedCount++;

 while(!blnGet)
 {
  //檢查是否存在足夠空閑塊
  Lock();
        iFreeCount = *((int *)pData);
  if (iFreeCount * m_ItemSize < Len) 
  {
   //空間不足,進入等待
   UnLock();
   WaitForSingleObject(m_WaitEvent,200);
  }
  else
  {
   for(int i=iFreeCount;i>=1;i--)
   {
    //讀取空閑塊索引
    iIndex = *((int *)(m_FreeIndexAddr + (i-1)*4));
    iRefAddr = (int)pData + 4 + (iIndex - 1) * m_BlockSize + m_ItemSize;

    //寫入佔用標誌
    *((byte *)iRefAddr) = 1;

    //減少空閑總數
    *((int *)pData) = *((int *)pData) - 1;

    //寫下一塊索引
    *((int *)(iRefAddr+5)) = iNext;

    //擷取塊首地址
    p = (LPVOID)(iRefAddr - m_ItemSize);

    iNeedCount--;
    if (iNeedCount == 0) break;

    //儲存當前塊索引
    iNext = iIndex;
   }

   UnLock();
   blnGet = TRUE;
  }
 }
 
 return p;
}

//釋放記憶體引用
BOOL CMyMemoryManager::Delete(LPVOID p)
{
 byte *pRef;
 int  *pNext;
 int  iNext = 1;

 if (p == NULL) return TRUE;

 while(iNext >= 1)
 {
  //清除資料區塊內容
  //ZeroMemory(p,m_ItemSize);

  Lock();

  //清除引用
  pRef = (byte *)((int)p + m_ItemSize);
  //增加空閑數 寫空閑索引
  if (*pRef != 0)
  {
   int *pFree = (int *)pData;
   *pFree = *pFree + 1;
   *((int *)(m_FreeIndexAddr + (*pFree - 1) * 4)) = *((int *)((int)p + m_ItemSize + 1));
  }
  *pRef = 0;
  //讀取並清除下一塊索引
  pNext = (int *)((int)p + m_ItemSize + 5);
  iNext = *pNext;
  *pNext = 0;

  UnLock();

  //計算下一塊地址
  if(iNext >= 1)
   p = (LPVOID)((int)pData + 4 + (iNext - 1) * (m_ItemSize + 5));
 }

 p = NULL;
 return TRUE;
}

//擷取資料區塊位元組數
int CMyMemoryManager::GetItemSize()
{
 return m_ItemSize;
}

//擷取總塊數
int CMyMemoryManager::GetItemCount()
{
 return m_ItemCount;
}

//擷取總空閑數
int CMyMemoryManager::GetFreeCount()
{
 int iCnt;
 Lock();
 CopyMemory(&iCnt,pData,4);
 UnLock();
 return iCnt;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.