一个超简单的内存池.docx

上传人:b****6 文档编号:3917465 上传时间:2022-11-26 格式:DOCX 页数:10 大小:153.81KB
下载 相关 举报
一个超简单的内存池.docx_第1页
第1页 / 共10页
一个超简单的内存池.docx_第2页
第2页 / 共10页
一个超简单的内存池.docx_第3页
第3页 / 共10页
一个超简单的内存池.docx_第4页
第4页 / 共10页
一个超简单的内存池.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

一个超简单的内存池.docx

《一个超简单的内存池.docx》由会员分享,可在线阅读,更多相关《一个超简单的内存池.docx(10页珍藏版)》请在冰豆网上搜索。

一个超简单的内存池.docx

一个超简单的内存池

一个简单的内存池Memory-Pool

SUNNY.MAN

内存池(MemoryPool)是一种内存分配方式。

通常我们习惯直接使用new、malloc等API申请分配内存,这样做的缺点在于:

由于所申请内存块的大小不定,当频繁使用时会造成大量的内存碎片并进而降低性能。

内存池则是在真正使用内存之前,先申请分配一定数量的、大小相等的内存块留作备用。

当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存。

这样做的一个显著优点是尽量避免了内存碎片,使得内存分配效率得到提升。

有不少地方内存分配不允许失败.作为在这些情况下确保分配的方式开发者创建了一个已知为内存池(或者是"mempool")的抽象.这种内存的分配方式优点是内存分配肯定成功,缺点在于占用大量内存。

一般来说做为缓存我强烈建议使用循环队列。

当然不得不用的情况下可以使用所谓的“内存池”。

一块固定的内存,被分成很多小块应用在不同的地方。

当不再使用时把这小块归还给内存池,再使用的时候,内存池根据一定的算法,重新划分一块符合要求的内存给需要的线程。

一般来说内存池的结构如下图所示:

结构中主要包含block、list和pool这三个结构体,block结构包含指向实际内存空间的指针,前向和后向指针让block能够组成双向链表;list结构中free指针指向空闲内存块组成的链表,used指针指向程序使用中的内存块组成的链表,size值为内存块的大小,list之间组成单向链表;pool结构记录list链表的头和尾。

本例中仅有一个list链表所以pool结构没有使用.所以结构如下图所示:

其中每一个block为分配的内存块,在本例中每一个内存块对应内存大小+12个字节。

4个字节为开始的位置,4个字节为结束的位置,4个字节为指针的位置。

为什么要记录指针的值呢,因为释放的时候,我们要找到这个空间并把它归还给内存池。

内存池的内存申请:

根据所申请内存的大小,遍历Freelist链表,查看是否存在相匹配size,在这里这个”匹配”是需要根据算法来遍历计算的。

我这个例子中,仅是找一个大小最为相近的来分配。

如果所有Freelist链表中都没有符合这个SIZE的块,则分配失败。

分配成功后移动刚才块的头指针到新位置,并把新分配的块信息块加入到Allocate链表中。

内存池的内存释放:

把已经不再使用的内存释放还给内存池。

释放时首先从分配链表里,把那个信息块删除。

然后再未分配链表中,把这信息块加入。

如果头或是尾或是头尾有和链表中已经存在的块重合的,则合并。

如果都没有,则把它插按开始的顺序进行插入。

简单代码如下:

1.定义信息块描述结构

typedefstructNodeinfo

{

intnStart;//开始位置

intnEnd;//结束位置

BYTE*pBuf;//所在的内存地址值

}_tagNodeinfo;

2.成员变量

BYTE*m_pMem;//整个内存池的指针

CListm_listAllocate;//已经分配的块链表

CListm_listFree;//空闲的块链表

longm_nCount;//整个内存池的大小

3.接口函数

CMYNew(intnMB=50*1024*1024);//默认大小为50M

~CMYNew(void);

BYTE*MyAllocate(intnCount);//用来分配内存

voidMyFree(BYTE*pbuf);//通过指针来释入内存

voidDisplay();//显示分配链表和空闲链表的存储情况

4.构造函数的实现

m_nCount=nMB;

m_pMem=newBYTE(nMB);

m_nLastError=NOERROR;

if(!

m_pMem)

m_nLastError=NOMEMORY;

else

{

Nodeinfo*newNode=newNodeinfo;

newNode->nStart=0;

newNode->nEnd=nMB-1;

//整体是一个块,空闲链表中的指针值没有意义

m_listFree.AddTail(newNode);//加入空闲链表

}

5.析构函数的实现

if(m_pMem)

deletem_pMem;//删除内存

m_pMem=NULL;

//释放未用内存链表中的信息块

POSITIONpos=m_listFree.GetHeadPosition();

while(pos)

{

Nodeinfo*pNode=m_listFree.GetAt(pos);

if(pNode)

deletepNode;

m_listFree.GetNext(pos);

}

m_listFree.RemoveAll();

//释放已分配内存块的地址

pos=m_listAllocate.GetHeadPosition();

while(pos)

{

Nodeinfo*pNode=m_listAllocate.GetAt(pos);

if(pNode)

deletepNode;

m_listAllocate.GetNext(pos);

}

m_listAllocate.RemoveAll();

5.内存池的内存分配

BYTE*CMYNew:

:

MyAllocate(intnCount)

{

BYTE*pbuf=NULL;

Nodeinfo*nodeinfo=NULL;

POSITIONpos=m_listFree.GetHeadPosition();

POSITIONposEqual=0;

BOOLbEqual=FALSE;

while(pos)

{

Nodeinfo*pNode=m_listFree.GetAt(pos);

if(pNode)

{

if((pNode->nEnd-pNode->nStart)>nCount)

{

if(nodeinfo)

{

if(nodeinfo->nEnd-nodeinfo->nStart>pNode->nEnd-pNode->nStart)

{

nodeinfo=pNode;//空间更小者

}

}//ifnodeinfo

else//第一个匹配项

{

nodeinfo=pNode;

}

}

elseif((pNode->nEnd-pNode->nStart)==nCount)//最匹配

{

nodeinfo=pNode;

bEqual=TRUE;

posEqual=pos;

break;

}//==nCoun

}//如果有空间pNode

m_listFree.GetNext(pos);

}//whilepos

if(nodeinfo)//可以分配

{

pbuf=&m_pMem[nodeinfo->nStart];

if(bEqual)

{

nodeinfo->pBuf=pbuf;

m_listAllocate.AddTail(nodeinfo);//加到已分配中

m_listFree.RemoveAt(posEqual);//从空闲中移除

}

else

{

Nodeinfo*pnewAll=newNodeinfo;

pnewAll->nStart=nodeinfo->nStart;

pnewAll->nEnd=pnewAll->nStart+nCount-1;//结尾

m_listAllocate.AddTail(pnewAll);//加到已分配中

nodeinfo->nStart+=nCount;//改没分配

pnewAll->pBuf=pbuf;

}//是否全部分完

}

//Display();

returnpbuf;

}

6.内存池的释放

voidCMYNew:

:

MyFree(BYTE*pbuf)

{

Nodeinfo*pNodeInfoResult=NULL;

POSITIONpos=m_listAllocate.GetHeadPosition();

while(pos)

{

Nodeinfo*pNodeInfo=m_listAllocate.GetAt(pos);

if(pNodeInfo)

{

if(pNodeInfo->pBuf==pbuf)//如果是这块

{

pNodeInfoResult=pNodeInfo;

m_listAllocate.RemoveAt(pos);//移除

break;

}

}//ifpodeinfo

m_listAllocate.GetNext(pos);

}//while

//BOOLbTreatFree=FALSE;

if(pNodeInfoResult)//如果已经可以删除

{

pos=m_listFree.GetHeadPosition();

while(pos)

{

Nodeinfo*pNodeInfo=m_listFree.GetAt(pos);

if(pNodeInfo)

{

if(pNodeInfo->nEnd+1==pNodeInfoResult->nStart)//如果恰好是一空闲的尾部则合并

{

pNodeInfo->nEnd=pNodeInfoResult->nEnd;//合并

m_listFree.GetNext(pos);//看后面的

if(pos)

{

Nodeinfo*pNodeInfo1=m_listFree.GetAt(pos);

if(pNodeInfo1)

{

if(pNodeInfo1->nStart==pNodeInfo->nEnd+1)

{

pNodeInfo->nEnd=pNodeInfo1->nEnd;//再次扩大空闲区

m_listFree.RemoveAt(pos);//移除这个点

deletepNodeInfo1;

}//也恰好是别一个点的开始

}

}//后面的Pos

deletepNodeInfoResult;//删除

pNodeInfoResult=NULL;

//bTreatFree=TRUE;

break;

}//恰好是空闲尾

 

if(pNodeInfo->nStart==pNodeInfoResult->nEnd+1)//如果恰好是一空闲的头部则合并

{

pNodeInfo->nStart=pNodeInfoResult->nStart;//合并

m_listFree.GetPrev(pos);//看前面的

if(pos)

{

Nodeinfo*pNodeInfo1=m_listFree.GetAt(pos);

if(pNodeInfo1)

{

if(pNodeInfo1->nEnd+1==pNodeInfo->nStart)

{

pNodeInfo->nStart=pNodeInfo1->nStart;//再次扩大空闲区

m_listFree.RemoveAt(pos);//移除这个点

deletepNodeInfo1;

}//也恰好是别一个点的开始

}

}//后面的Pos

deletepNodeInfoResult;//删除

pNodeInfoResult=NULL;

//bTreatFree=TRUE;

break;

}//恰好是空闲尾

}//pNodeInfo

m_listFree.GetNext(pos);

}//while

 

if(pNodeInfoResult)//只是一块闲存

{

BOOLbIinsert=FALSE;

pos=m_listFree.GetHeadPosition();

while(pos)

{

Nodeinfo*pNodeInfo=m_listFree.GetAt(pos);

if(pNodeInfo)

{

if(pNodeInfo->nStart>pNodeInfoResult->nStart)//如果是这块

{

m_listFree.InsertBefore(pos,pNodeInfoResult);

bIinsert=TRUE;

break;

}

}//ifpodeinfo

m_listFree.GetNext(pos);

}//while

if(bIinsert==FALSE)

{

m_listFree.AddTail(pNodeInfoResult);

}

}

}//if可以删除

//Display();

}

7.显示函数

voidCMYNew:

:

Display()

{

POSITIONpos=m_listFree.GetHeadPosition();

while(pos)

{

Nodeinfo*pNode=m_listFree.GetAt(pos);

if(pNode)

{

TRACE(L"Free[%d]->[%d]\n",pNode->nStart,pNode->nEnd);

}

m_listFree.GetNext(pos);

}

inti=0;

pos=m_listAllocate.GetHeadPosition();

while(pos)

{

Nodeinfo*pNode=m_listAllocate.GetAt(pos);

if(pNode)

{

TRACE(L"Allocate:

[%d][%x][%d]->[%d]\n",i++,pNode->pBuf,pNode->nStart,pNode->nEnd);

}

m_listAllocate.GetNext(pos);

}

}

以上代码经本人测试通过。

并没有出现BUG,欢迎指定。

As_mhy@

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1