内存池创建以及使用

Author:阿冬哥

Created:2013-4-18 

Blog:http://blog.csdn.net/c359719435/

Copyright 2013 阿冬哥 http://blog.csdn.net/c359719435/

使用以及转载请注明出处


1 内存池

      内存池是一种内存分配方式。一般我们习惯用new\malloc在需要使用内存时分配内存,这样做的缺点是:调用new、malloc有一定的开销,由于每次调用的大小不确定所以频繁的调用会产生内存碎片从而降低性能。内存池则是在使用内存之前,预先分配一定量的、大小相等的内存块,当有需要时直接从内存池中取。这样做的一个显著优点是避免了内存碎片,提高了内存分配效率。


2 一个简单的内存池实现代码

      从内存中分配大片空间后,一般都会再分块进行管理,例如内存池大小是32M,可以以4K为单位分块。对内存池中的管理一般有两种方法:

      (1) 用带头结点的list表示空闲的内存块,list中头结点存储下一个空闲的内存块。例如类BufferPool。

      (2)用队列管理内存块。例如代码中类BufferQueueNode。


//myBufferPool.h

 //Author:Winter Chen 

//Created:2013-4-18
//此文件设计一个内存池
//
#ifndef MYBUFFERPOOL_H
#define MYBUFFERPOOL_H






class BufferPool{
public:
BufferPool():mPool(0),mPoolSize(0),
mPageSize(0),mTotalPagesAmount(0),
mFreePagesCount(0),mFreeListPtr(0){}
~BufferPool(){Destroy();}


int Creat(unsigned int poolSize, bool mmapMemory = 0, bool lockMemory = 0);
void Destroy();
char* Get();
char* Get(unsigned int size);
bool Reclaim(char *ptr);
bool Reclaim(char *ptr, unsigned int size);
bool IsEmpty(){ return mFreePagesCount <= 0 ? 1 : 0;}
bool IsFull(){ return mFreePagesCount ==  mTotalPagesAmount? 1 : 0;}
unsigned int GetFreePagesCount(){return mFreePagesCount;}
unsigned int GetPoolSize(){return mPoolSize;}


private:
void *mPool;
unsigned int mPoolSize;
unsigned int mPageSize;
unsigned int mTotalPagesAmount;
unsigned int mFreePagesCount;
int *mFreeListPtr;
bool mIsMmap;
};




class BufferQueueNode{
       public:
  BufferQueueNode():mBufferPtr(0), mNext(this), mPrev(this){}
~BufferQueueNode(){
if(mBufferPtr)
delete mBufferPtr;
mBufferPtr = 0;
mNext = 0;
mPrev = 0;
}
char *mBufferPtr;
BufferQueueNode *mNext;
BufferQueueNode *mPrev;
};


class BufferPoolQueue{
public:
BufferPoolQueue():mPoolSize(0),
mDatalet(0), mHead(0), mPool(0){}
~BufferPoolQueue(){Destroy();}


int Creat(unsigned int poolSize, bool mmapMemory = 0, bool lockMemory = 0);
void Destroy();
void Enqueue(BufferQueueNode *inNode);
BufferQueueNode *Dequeue();
BufferQueueNode *Allocate();
void Reclaim(BufferQueueNode *inNode);
bool IsEmpty(){ return ((mHead == NULL) || (mHead->mNext == mHead))  ? 1 : 0;}
unsigned int GetPoolSize(){return mPoolSize;}
//unsigned int GetFreepoolsize();


private:
void *mPool;
unsigned int mPoolSize;
unsigned int mDatalet;
BufferQueueNode *mHead;
bool mIsMmap;
};


#endif


//**************************************************************************************//


//myBufferPool.cc

//Author:Winter Chen

//Created:2013-4-18


#include "myBufferPool.h"
#include <errno.h>
#include <iostream>
#include <sys/mman.h>
using namespace std;








int 
BufferPool::Creat(unsigned int poolSize, bool mmapMemory, bool lockMemory){
mPageSize = sysconf(_SC_PAGESIZE);
mIsMmap = mmapMemory;
mTotalPagesAmount = poolSize/mPageSize + 1;
mPoolSize = mTotalPagesAmount*mPageSize;
cout << "mPageSize = " << mPageSize << " mTotalPagesAmount = " << mTotalPagesAmount <<" mPoolSize = "<< mPoolSize << endl;
if(mIsMmap){
mPool = mmap(0, mPoolSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
   if (mPool == MAP_FAILED) {
mPool = 0;
return errno;
}
}
else 
mPool = new char[mPoolSize];
//mlock:通过mlock可以将进程使用的部分
//或者全部的地址空间锁定在物理内存中,防止其被交换到swap空间
if(lockMemory && mlock(mPool, mPoolSize) != 0){
Destroy();
return errno;


}
mFreeListPtr = new int[mTotalPagesAmount+ 1];
mFreePagesCount = 0;
while(mFreePagesCount < mTotalPagesAmount){
mFreeListPtr[mFreePagesCount] = mFreePagesCount+1;
mFreePagesCount++;
}
mFreeListPtr[mTotalPagesAmount] = 0;
return 0;
}


bool
BufferPool::Reclaim(char *ptr){
if(IsFull())
return 0;
int pageNum = (ptr - (char*)mPool)/mPageSize + 1;
if(pageNum >= mTotalPagesAmount)
return 0;
mFreeListPtr[pageNum] = mFreeListPtr[0];
mFreeListPtr[0] = pageNum;
mFreePagesCount++;
return 1;
}


char*
BufferPool::Get(){
if(IsEmpty()){
cout << "empty!!!" << endl;
return NULL;


}
char *res;
res = (char*)mPool + (mFreeListPtr[0]-1) * mPageSize;
mFreeListPtr[0] = mFreeListPtr[mFreeListPtr[0]];
mFreePagesCount--;
cout << "get a buffer, address is :" << (void*)res << endl;
return res;
}


void
BufferPool::Destroy(){
delete [] mFreeListPtr;
mFreeListPtr = 0;
if(mIsMmap){
if (mPool && munmap(mPool, mPoolSize) != 0) {
cout <<"munmap error: " << errno <<endl;
}
}
else 
delete [] mPool;
mPool = 0;
mPoolSize = 0;
mTotalPagesAmount  = 0;
mFreePagesCount = 0;
}








int 
BufferPoolQueue::Creat(unsigned int poolSize, unsigned int datalet, bool mmapMemory, bool lockMemory){
unsigned int pageSize = sysconf(_SC_PAGESIZE);
mPoolSize = (poolSize/pageSize + 1)*pageSize;
if(datalet <= 0)
return 0;
mDatalet = datalet;
//cout << "mPageSize = " << mPageSize << " mTotalPagesAmount = " << mTotalPagesAmount <<" mPoolSize = "<< mPoolSize << endl;
if(mmapMemory){
mPool = mmap(0, mPoolSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
   if (mPool == MAP_FAILED) {
mPool = 0;
return errno;
}
}
else 
mPool = new char[mPoolSize];
//mlock:通过mlock可以将进程使用的部分
//或者全部的地址空间锁定在物理内存中,防止其被交换到swap空间
if(lockMemory && mlock(mPool, mPoolSize) != 0){
Destroy();
return errno;


}
//create the head node of queue
mHead = new BufferQueueNode();
char pos = 0;
char *ptr = (char*) mPool;
while(pos < (mPoolSize - datalet)){
BufferQueueNode *p = new BufferQueueNode();
ptr += pos;
p->mBufferPtr = ptr;
Enqueue(p);
pos += datalet;


}
return 1;
}


void
BufferPoolQueue::Reclaim(BufferQueueNode *inNode){
Enqueue(inNode);
}




BufferQueueNode *
BufferPoolQueue::Allocate(){
return Dequeue();
}


void
BufferPoolQueue::Enqueue(BufferQueueNode *inNode){
inNode->mPrev = mHead->mPrev;
inNode->mNext = mHead;
mHead->mPrev->mNext = inNode;
mHead->mPrev = inNode;
}


BufferQueueNode *
BufferPoolQueue::Dequeue(){
if(IsEmpty())
return NULL;
BufferQueueNode *p = mHead->mNext;
p->mPrev->mNext = p->mNext;
p->mNext->mPrev= p->mPrev;
p->mPrev = p->mNext = 0;
return p;
}


void
BufferPoolQueue::Destroy(){
while(!IsEmpty()){
delete Dequeue();
}
delete mHead;
mHead = NULL;
if(mIsMmap){
if (mPool && munmap(mPool, mPoolSize) != 0) {
cout <<"munmap error: " << errno <<endl;
}
}
else 
delete [] mPool;
mPool = 0;
mPoolSize = 0;
}


/*unsigned int 
BufferPoolQueue::GetFreepoolsize(){

}
*/


注:以上代码没有考虑多线程情况,如果考虑多线程,需要在适当的地方加锁






参考资料:

        http://baike.baidu.com/view/2659852.htm

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值