稳健内存管理

/
//  自定义内存管理器
//
//  [总空闲数(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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值