游戏开发论坛

 找回密码
 立即注册
搜索
查看: 4768|回复: 12

俺写的一个顺序分配释放内存池算法,欢迎测试改进

[复制链接]

1

主题

3

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2006-6-26 16:35:00 | 显示全部楼层 |阅读模式
//---------------------------------------------------------------------------

#ifndef QueueMemH
#define QueueMemH
#include <vcl.h>
//---------------------------------------------------------------------------
typedef struct{
      long      nFlag;         //1 可分配 2 备用 3 已到末尾
      PBYTE     pPool;         //当前空闲起始地址
      long      nFreeSize;     //当前空闲尺寸
}QUE,*PQUE;

class TQueueMemPool
{
private:
      long       bWait;             //锁
      PBYTE      pPool;             //池起始地址
      long       nPoolSize;         //池尺寸

      QUE        que[2];
public:
       TQueueMemPool(void);
       ~TQueueMemPool(void);

       int    init(long  nTotalSize);
       void * Alloc(long  nSize);
       void   Free(void *pPtr, long nSize);
};

#endif
//===================================================

TQueueMemPool::TQueueMemPool(void)
{     bWait=false;
      pPool=NULL;             //池起始地址
      nPoolSize=0;            //池尺寸
      memset( que, 0, sizeof(QUE)*2 );
}
TQueueMemPool::~TQueueMemPool(void)
{
      if(pPool)
          SysFreeMem(pPool);

}
int   TQueueMemPool::init(long  nTotalSize)
{
      if(pPool)
          SysFreeMem(pPool);
      pPool=(PBYTE)SysGetMem(nTotalSize);             //池起始地址
      nPoolSize=nTotalSize;                           //池尺寸
      bWait=false;
      que[0].pPool=pPool;
      que[0].nFlag=1;
      que[0].nFreeSize= nPoolSize;

      que[1].pPool=pPool;
      que[1].nFlag=2;
      que[1].nFreeSize= 0;


      if(pPool)
          return 0;
      else
          return 1;
}

/*
* 分配 nSize大小的空间
* PVOID    分配的空间的起始地址
*/
void * TQueueMemPool::Alloc(long nSize)
{
      PBYTE pPtr=NULL;

      while(InterlockedExchange(&bWait, true))
          Sleep(0);
      if(que[0].nFlag==1)
      {
              if(que[0].nFreeSize>=nSize)
              {
                 que[0].nFreeSize -= nSize;
                 pPtr=que[0].pPool;
                 que[0].pPool+=nSize;
              }
              else
              {
                 if(que[1].nFlag==2)
                 {
                      if(que[1].nFreeSize>=nSize)
                      {
                         if(que[1].nFreeSize==que[0].pPool-pPool)
                         {
                                que[0].nFlag=2;//已经终止标志
                                que[0].nFreeSize=0;
                                que[0].pPool=pPool;
                                que[1].nFreeSize= nPoolSize;
                         }
                         else
                         {
                                que[0].nFlag=3;//已经终止标志
                         }
                         que[1].nFreeSize -= nSize;
                         pPtr=que[1].pPool;
                         que[1].pPool+=nSize;

                         que[1].nFlag=1;
                      }
                 }
              }
      }
      else if(que[1].nFlag==1)
      {
              if(que[1].nFreeSize>=nSize)
              {
                 que[1].nFreeSize -= nSize;
                 pPtr=que[1].pPool;
                 que[1].pPool+=nSize;
              }
              else
              {
                 if(que[0].nFlag==2)
                 {
                      if(que[0].nFreeSize>=nSize)
                      {
                         if(que[0].nFreeSize==que[1].pPool-pPool)
                         {
                                que[1].nFlag=2;//已经终止标志
                                que[1].nFreeSize=0;
                                que[1].pPool=pPool;
                                que[0].nFreeSize= nPoolSize;
                         }
                         else
                         {
                                que[1].nFlag=3;//已经终止标志
                         }

                         que[0].nFreeSize -= nSize;
                         pPtr=que[0].pPool;
                         que[0].pPool+=nSize;

                         que[0].nFlag=1;


                      }
                 }
              }
      }
      InterlockedExchange(&bWait, false);

      if(pPtr==NULL)
      {      //MessageBox(0,"没有空间分配!","",0);
             pPtr=(PBYTE)SysGetMem(nSize);
      }

      return pPtr;

}
/*
* 释放空间,必须指定内存空间大小
* PVOID pPtr   内存空间
* nSize 内存空间大小
*/

void  TQueueMemPool::Free(void *pPtr,long nSize)
{

      if( pPtr>=pPool && pPtr<pPool+nPoolSize )
      {
             while(InterlockedExchange(&bWait, true))
                  Sleep(0);
             if(que[0].pPool + que[0].nFreeSize == pPtr)
             {

                  if(que[1].nFlag==3 && que[1].pPool-nSize==pPtr)
                  {
                        nSize=nPoolSize-((PBYTE)pPtr-pPool);
                        que[1].nFlag=2;
                        que[1].nFreeSize=0;
                        que[1].pPool=pPool;
                  }
                  que[0].nFreeSize += nSize;

             }
             else if(que[1].pPool + que[1].nFreeSize == pPtr)
             {

                  if(que[0].nFlag==3 && que[0].pPool-nSize==pPtr)
                  {
                        nSize=nPoolSize-((PBYTE)pPtr-pPool);
                        que[0].nFlag=2;
                        que[0].nFreeSize=0;
                        que[0].pPool=pPool;
                  }
                  que[1].nFreeSize += nSize;

             }
             else
                  MessageBox(0,"没有按顺序回收!","",0);
             InterlockedExchange(&bWait, false);
      }
      else
      {
             SysFreeMem(pPtr);
      }
}

18

主题

971

帖子

982

积分

高级会员

Rank: 4

积分
982
发表于 2006-6-26 17:11:00 | 显示全部楼层

Re:俺写的一个顺序分配释放内存池算法,欢迎测试改进

晕...
你那个池也太小了吧,又不能扩展大小......
强烈建议要写内存管理的兄弟们看看HL2的内存管理的那个类,除特殊情况下,一般在常数时间内分配和释放内存。池的大小是可扩展的。当然如果写个商业代码,还要加些东西进去,对初学者来说,那已经足够了。对应的可以看看《c++设计新思维》,有一章实现了一个小型的内存分配池,在网上找loki库就行了。同样,也可以看到stl和boost的分配算法,都开源的,结构什么的也很好.

1

主题

3

帖子

0

积分

新手上路

Rank: 1

积分
0
 楼主| 发表于 2006-6-26 17:15:00 | 显示全部楼层

Re: 俺写的一个顺序分配释放内存池算法,欢迎测试改进

在Init设置池大小。使用要求,先分配的先释放

18

主题

971

帖子

982

积分

高级会员

Rank: 4

积分
982
发表于 2006-6-26 20:32:00 | 显示全部楼层

Re:俺写的一个顺序分配释放内存池算法,欢迎测试改进

所以说基本上没什么用.....
当程序在init时怎么会知道后面共要用多大的内存中呢?像平台优化、内存齐位等等等等楼主都没做,实际上分配一个3字节的内存,然后转化成int,将会有不可预料的后果,而且谁也不能要求使用内存池的程序们要遵守先分配先释放的规则。

89

主题

4036

帖子

4132

积分

论坛元老

Rank: 8Rank: 8

积分
4132
发表于 2006-6-27 11:54:00 | 显示全部楼层

Re:俺写的一个顺序分配释放内存池算法,欢迎测试改进

弄不清楚楼主为什么要这么设计

16

主题

114

帖子

114

积分

注册会员

Rank: 2

积分
114
发表于 2006-6-27 15:28:00 | 显示全部楼层

Re:俺写的一个顺序分配释放内存池算法,欢迎测试改进

首先,把自己的代码贴上来交流,这是程序员很好的习惯。这样你会听到各位的意见和批评。不管代码有没有多少实用价值,权作练习。学习和坚持会让人成长

1

主题

3

帖子

0

积分

新手上路

Rank: 1

积分
0
 楼主| 发表于 2006-6-27 15:34:00 | 显示全部楼层

Re: 俺写的一个顺序分配释放内存池算法,欢迎测试改进

主要用在收到网络包的处理。一个线程负责接收数据并加入链表,另一个线程负责处理数据包,处理时先收到先处理。这样内存分配与回收不会产生碎片。

13

主题

978

帖子

978

积分

高级会员

Rank: 4

积分
978
发表于 2006-6-27 20:37:00 | 显示全部楼层

Re: Re:俺写的一个顺序分配释放内存池算法,欢迎测试改进

whb9633: Re:俺写的一个顺序分配释放内存池算法,欢迎测试改进
强烈建议要写内存管理的兄弟们看看HL2的内存管理的那个类

在哪(些)个文件下面?

HL2的代码太大了,一直不敢看~~~

18

主题

971

帖子

982

积分

高级会员

Rank: 4

积分
982
发表于 2006-6-28 12:54:00 | 显示全部楼层

Re:俺写的一个顺序分配释放内存池算法,欢迎测试改进

那就不记得了,大概在engine下面,打开engine.dsp,然后在项目文件里找.mempool.h/cpp,仿佛是这个名字.

另外,楼主在处理网络信息的时候用的这个么?如果是用的UDP,那那个算法没什么意义,大概要自己把包排序,如果是用的TCP,像这种时序依赖性的东西,仿佛应该用的数据结构是队列,直接用stl的队列就可以了,也不会产生内存碎片,而且楼主没做齐位等等,会有很多问题等着调呢......

13

主题

978

帖子

978

积分

高级会员

Rank: 4

积分
978
发表于 2006-6-28 21:27:00 | 显示全部楼层

Re:俺写的一个顺序分配释放内存池算法,欢迎测试改进

记得SGI的STL的alloc就带了内存管理,专门防止碎片……
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-24 20:38

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表