谈谈 eMule 中的 内存管理器类 CMemPoolMgr

 1、内存管理器类CMemPoolMgr有一个成员m_MemoryUnitList,我们称作内存单元链表,每一个内存单元对象对应着一个正在下载的文件所使用的内存池(CMemPool)列表。当eMule客户端接收到其他客户端发来的文件数据时,内存管理器对象m_pMemoryPool,调用函数GetMemory()来分配内存。我们来看看GetMemory()
 TByte* CMemPoolMgr::GetMemory(CPartFile* pPartFile, unsigned int size)
 {
  TByte* pData;

  CMemoryUnit *pMemoryUnit = NULL;

  // 首先检查内存单元链表中有没有pPartFile,
  POSITION pos2, pos1 = m_MemoryUnitList.GetTailPosition();

  //从后往前查找
  for (; (pos2 = pos1) != NULL;)
  {
   m_MemoryUnitList.GetPrev(pos1);

   if (m_MemoryUnitList.GetAt(pos2)->GetPartFile() == pPartFile)
   {
    pMemoryUnit = m_MemoryUnitList.GetAt(pos2);
    break;
   }
  }

  if (pMemoryUnit) //找到该文件对应的内存单元
  {
   //检查该内存单元的内存池链表中有没有空闲的并且不小于size的内存单元
   if ((pData = pMemoryUnit->GetMemory(size)) != NULL)
   {
    return pData;
   }
   else //没有找到
   {
        //首先在内存管理器中查找有没有空闲内存池
        //如果有,将该空闲内存池加入到该内存单元的内存池链表尾部
       //如果没有,重新申请一段内存,分别加入内存管理器和该内存单元的内存池链表尾部
       CMemPool * pMemPool = GetMemPool(pMemoryUnit, m_nPoolUnitSize);
       //返回查找到的或申请的内存
       return pMemPool->GetMemory(size);
   }
  }
  else //没有找到
  {
   //重新申请一个内存单元
   pMemoryUnit = new CMemoryUnit(this, pPartFile);
   //加入到内存管理器的内存单元链表尾部
   m_MemoryUnitList.AddTail(pMemoryUnit);
   
   //同上
   CMemPool * pMemPool = GetMemPool(pMemoryUnit, m_nPoolUnitSize);
   return pMemPool->GetMemory(size);
  }
 }

2、再来看看内存池类CMemPool
   内存池对象又若干个(默认是1M)大小相等的内存块(默认是11K)组成,其在构造函数中调用InitMemPool()完成内存分配。
 void CMemPool::InitMemPool()
 {
  try
  {
   unsigned int blocksize = CalcBlockSize(m_nPoolSize);
   PMemoryBlock pMemBlock = new MemoryBlock[blocksize];
   
   //初始化所有内存块对象,加入链表中
   for (unsigned int i = 0; i < blocksize; i++)
   {
    m_MemoryUnitList.AddTail(&pMemBlock[i]);
   }
 
   //申请内存
   m_pPoolEntry = (TByte*) new TByte[m_nPoolSize];
   POSITION pos2, pos1 = m_MemoryUnitList.GetHeadPosition();
   
   //给所有内存块对象赋值
   for (unsigned int i = 0; (pos2 = pos1) != NULL; i++)
   {
    m_MemoryUnitList.GetNext(pos1);
    
    //内存块起始地址
    m_MemoryUnitList.GetAt(pos2)->pData      = (TByte*)(m_pPoolEntry + i * m_nBlockUnitSize);
    //该内存块处可用内存大小
    m_MemoryUnitList.GetAt(pos2)->DataSize   = m_nPoolSize - i * m_nBlockUnitSize;
   }
  }
  catch (...)
  {
   // TODO : Catch the Exception of Memory allocation
  }

  //初始化时,指针指向链表头部,标识所有内存可用
  m_CurUnitPos = m_MemoryUnitList.GetHeadPosition();
 }

  当调用GetMemory(int nSize)分配内存时,首先计算要分配的内存块数目,然后从内存块链表的尾部开始查找第一个大于nSize的内存 块对象,如果没有找到,返回NULL标志失败;如果找到,返回该内存块的指针。

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值