Chinaunix首页 | 论坛 | 博客
  • 博客访问: 845972
  • 博文数量: 756
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 4980
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:40
文章分类

全部博文(756)

文章存档

2011年(1)

2008年(755)

我的朋友

分类:

2008-10-13 16:10:42

代码如下:

#ifndef  _MEMPOOL_H_
#define  _MEMPOOL_H_

/* 
本类封装了一个内存池,采用模板类,
模板参数就是内存池中分配的对象类型
本类主要用链表来实现,适用于固定大小的内存块分配
*/


#include 
<vector>
using  std::vector;

template
<typename T>
class CMemPool
{

 
struct _MemNode
 
{
  _MemNode
* pPrev;
  
char data[sizeof(T) - sizeof(_MemNode*)];
 }
;

 
struct _MemBlock
 
{
  _MemBlock
* pPrev;
  _MemNode
* pNode;
 }
;

 _MemBlock
* m_pBlockHeader ;    //大内存块链表头指针
 _MemNode*  m_FreeNodeHeader;   //空闲的小块头指针
 int m_BlockSize;              //当前小内存块数量

private:
 
void AllocBlocks();   //分配内存块
 void ReallocBlocks(); //扩大内存池大小

public:
 
//构造函数,nInitSize为初始内存块数
 CMemPool(int nInitSize = 128)
  : m_BlockSize(nInitSize), m_pBlockHeader(NULL), m_FreeNodeHeader(NULL)
 
{
  AllocBlocks();
 }


 
//析构函数,释放所有底层内存块
 ~CMemPool()
 
{
  
while(m_pBlockHeader != NULL)
  
{
   _MemBlock
* tmp = m_pBlockHeader;
   m_pBlockHeader 
= tmp->pPrev;
   free(tmp
->pNode);
   free(tmp);
  }

 }


 
/*  下面两个函数是主要的对外接口 */
 
void* AllocBlock(size_t size);                 //从内存池请求内存,size为分配的内存块大小
 void  FreeBlock(void* pobj , size_t size );    //把内存归还给内存池,pobj是内存块指针,size为内存块大小

 
//打印信息,用于调试程序
/* void PrintTestInfo()
 {
  printf("Handle pool: size = %d, free_index = %d, capacity = %d ", m_BlockSize, m_FreeIndex, m_Blocks.capacity());
 }
 
*/


}
;

template
<typename T>
void* CMemPool<T>::AllocBlock(size_t size)
{
 
if (size != sizeof(T)) //假如size不等于T类型大小,则使用全局分配符分配内存
 {
  
return malloc(size);
 }


 
if (m_FreeNodeHeader == NULL) //当前没有空闲的内存块,则扩大内存
 {
  ReallocBlocks();
 }


 
void* p = m_FreeNodeHeader;    //从空闲块中分配一块内存
 m_FreeNodeHeader = m_FreeNodeHeader->pPrev;

 
return p;
}


template
<typename T>
void  CMemPool<T>::FreeBlock(void* pobj , size_t size)
{
 
if( pobj == NULL )     //pobj不能为NULL
  return ;
 
if( size != sizeof(T) )   //假如size不等于T类型大小,则使用全局释放内存操作符释放内存      
 {
  free(pobj);
 }

 
else  //将内存归还给内存池
 {
  _MemNode
* p = (_MemNode*)pobj;
  p
->pPrev = m_FreeNodeHeader;
  m_FreeNodeHeader 
= p;
 }

}


template
<typename T>
void CMemPool<T>::AllocBlocks()
{
 
//分配m_BlockSize大小个内存块,放入内存池
 _MemBlock* newBlock = (_MemBlock*)malloc(sizeof(_MemBlock));

 
//分配大块内存
 newBlock->pNode = (_MemNode*)malloc(sizeof(_MemNode)* m_BlockSize);

 
//将分配的大块内存分成小块,串接在空闲块链表上
 newBlock->pNode->pPrev = NULL;
 
for(int i = 1; i < m_BlockSize; ++i)
 
{
  newBlock
->pNode[i].pPrev = &(newBlock->pNode[i - 1]);
 }

 m_FreeNodeHeader 
= &newBlock->pNode[m_BlockSize - 1];

 newBlock
->pPrev = m_pBlockHeader;
 m_pBlockHeader 
= newBlock;
}


template
<typename T>
void CMemPool<T>::ReallocBlocks()
{
 
//将内存池扩大2倍
 m_BlockSize *= 2;
    AllocBlocks();
}


#endif


本内存池只适合固定大小的内存块分配,避免频繁分配小块内存造成的内存碎片,同时也提高了分配内存的速度。特别适合服务器程序使用。下面有一个测试程序:


#include "MF_mempool.h"
#include "windows.h"

class Test
{
 int ss;
 char * p;
    static CMemPool mp;
public:
 static void* operator new(size_t size);
 static void operator delete(void* pobj, size_t size);
};

CMemPool Test::mp(512);

void* Test::operator new(size_t size)
{
 return mp.AllocBlock(size);
}

void Test::operator delete(void* pobj, size_t size)
{
 mp.FreeBlock(pobj, size);
}


#define Max_Blocks  1000000
int _tmain(int argc, _TCHAR* argv[])
{
 Test** ptrarry= new Test* [Max_Blocks];
 DWORD ss = GetTickCount();
 for(int i = 0; i < Max_Blocks; ++i)
 {
  ptrarry[i] = new Test;
 }
 
 for(int j = Max_Blocks - 1; j >= Max_Blocks; --j)
 {
  delete ptrarry[j];
 }
 
 DWORD end = GetTickCount();

 printf("take out time is %d\n", end - ss);
 return 0;
}

我的机器上(c2.4, 512内存): time take out is 370
不使用内存池的情况:      time take out is 731


--------------------next---------------------

阅读(510) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~