头文件
#ifndef MY_MEMPOOL_H
#define MY_MEMPOOL_H
#define MY_MPN_B namespace my_mempool{
#define MY_MPN_E }
#define DECLARE_MY_MEMPOOL using namespace ::my_mempool;
#include <string>
#include <map>
#include <vector>
using namespace ::std;
MY_MPN_B
/**
* /ingroup my_memorypool
* CMPBase,base class ,non copyable.
*
* /par requirements
* win98 or later/n
* win2k or later/n
* MFC/n
*
* /version 1.0
* first version
*
* /date 2009-06-03
*
* /author Jason
*
* /par license
* This code is absolutely free to use and modify. The code is provided "as is" with
* no expressed or implied warranty. The author accepts no liability if it causes
* any damage to your computer, causes your pet to fall ill, increases baldness
* or makes your car start emitting strange noises when you start it up.
* This code has no bugs, just undocumented features!
*
* /todo
*
* /bug
*
*/
class CMPBase
{
private:
CMPBase(const CMPBase &){}
CMPBase & operator = (const CMPBase &){return *this;}
public:
CMPBase(){}
virtual ~CMPBase() = 0;
protected:
int round_up(int size);
public:
/**
* 追加一块内存
* /param size
* 追加内存的大小
* /return
* 返回追加的内存实际大小
*/
virtual int append(int size) = 0;
virtual void reap(void) = 0;
/**
* 计算总空间
* /param void
* /return
*/
virtual int space_(void) = 0;
/**
* 计算分配了多少空间
* /param void
* /return
*/
virtual int malloced(void) = 0;
/**
* 计算剩余空间
* /param void
* /return
*/
virtual int freememory(void) = 0;
/**
* malloc memory,same to stardard c malloc function
* /param size
*/
virtual void * malloc(int size) = 0;
/**
* free memory
* /param mp
*/
virtual void free(void * mp) = 0;
virtual void dump(const string & file) {};
};
/**
* /ingroup my_memorypool
* class CMapMemoryPool
* 简单实现
* /par requirements
* win98 or later/n
* win2k or later/n
* MFC/n
*
* /version 1.0
* first version
*
* /date 2009-06-04
*
* /author Jason
*
* /par license
* This code is absolutely free to use and modify. The code is provided "as is" with
* no expressed or implied warranty. The author accepts no liability if it causes
* any damage to your computer, causes your pet to fall ill, increases baldness
* or makes your car start emitting strange noises when you start it up.
* This code has no bugs, just undocumented features!
*
* /todo
*
* /bug
*
*/
class CMapMemoryPool : public CMPBase
{
enum{DEFAULTSIZE = 2 * 1024 * 1024};
bool initialized;
public:
CMapMemoryPool();
CMapMemoryPool(const int & size);
virtual ~CMapMemoryPool();
//尽量大些
virtual int append(int size);
virtual void reap(void);
virtual int space_(void){ return malloced() + freememory();}
virtual int malloced(void);
virtual int freememory(void);
virtual void * malloc(int size);
virtual void free(void * mp);
virtual void dump(const string & file);
private:
enum { mbMed = 0x00, mbHeader = 0x01, mbTail = 0x02};
struct mem_control_block
{
int is_available;
int flag;//mbHeader,mbMed,mbTail
int size;
int blockcounter;
};
// pointer , memory control block pointer
map<unsigned int,unsigned int> free_memory;
map<unsigned int,unsigned int> malloced_memory;
typedef map<unsigned int,unsigned int> map_type;
typedef pair<const unsigned int, unsigned int> map_it;
int count_space(const map_type & m);
//void realign_right(const unsigned int & pointer);
//void realign_left(const unsigned int & pointer);
class CSimpleCount
{
public:
CSimpleCount()
:count(0)
{}
void operator()(const map_it & t)
{
mem_control_block * p = (mem_control_block *)(t.second);
if(p)
count += p->size;
}
int Count(void)
{
return count;
}
private:
int count;
};
struct temZone
{
void * buf;
int size;
temZone()
:buf(0),size(0)
{
;
}
temZone(void * b,int s)
:buf(b),size(s)
{
;
}
temZone(const temZone& t)
:buf(t.buf),size(t.size)
{
;
}
temZone & operator = (const temZone &t)
{
buf = t.buf;
size = t.size;
return *this;
}
};
vector<temZone> _blocks;
int blockcounter;
};
/**
* /ingroup my_memorypool
* CGeneralMemoryPool,提供线程安全的实现
*
* /par requirements
* win98 or later/n
* win2k or later/n
* MFC/n
*
* /version 1.0
* first version
*
* /date 2009-06-03
*
* /author Jason
*
* /par license
* This code is absolutely free to use and modify. The code is provided "as is" with
* no expressed or implied warranty. The author accepts no liability if it causes
* any damage to your computer, causes your pet to fall ill, increases baldness
* or makes your car start emitting strange noises when you start it up.
* This code has no bugs, just undocumented features!
*
* /todo
*
* /bug
*
*/
template<class MUTEX__,class MPINSTANCE>
class CGeneralMemoryPool : public CMPBase
{
class CSimGuard
{
public:
CSimGuard(MUTEX__ & l)
:lk(l)
{
lk.acquire();
}
~CSimGuard(void)
{
lk.release();
}
private:
MUTEX__ & lk;
};
public:
CGeneralMemoryPool()
{
mp_ins = new MPINSTANCE;
}
CGeneralMemoryPool(int size)
{
mp_ins = new MPINSTANCE(size);
}
virtual ~CGeneralMemoryPool(void)
{
delete mp_ins;
}
virtual int append(int size)
{
CSimGuard b(lock__);
return mp_ins->append(size);
}
virtual void reap(void)
{
CSimGuard b(lock__);
mp_ins->reap();
}
virtual int space_(void)
{
CSimGuard b(lock__);
return mp_ins->space_();
}
virtual int malloced(void)
{
CSimGuard b(lock__);
return mp_ins->malloced();
}
virtual int freememory(void)
{
CSimGuard b(lock__);
return mp_ins->freememory();
}
virtual void * malloc(int size)
{
CSimGuard b(lock__);
return mp_ins->malloc(size);
}
virtual void free(void * mp)
{
CSimGuard b(lock__);
mp_ins->free(mp);
}
virtual void dump(const string & file)
{
CSimGuard b(lock__);
mp_ins->dump(file);
}
private:
CGeneralMemoryPool(const CGeneralMemoryPool &){}
CGeneralMemoryPool & operator = (const CGeneralMemoryPool & t){return *this;}
MUTEX__ lock__;
MPINSTANCE * mp_ins;
};
/**
* /ingroup my_memorypool
* CObjectPool 提供基于内存池的对象级别的内存管理接口
*
* /par requirements
* win98 or later/n
* win2k or later/n
* MFC/n
*
* /version 1.0
* first version
*
* /date 2009-06-05
*
* /author Jason
*
* /par license
* This code is absolutely free to use and modify. The code is provided "as is" with
* no expressed or implied warranty. The author accepts no liability if it causes
* any damage to your computer, causes your pet to fall ill, increases baldness
* or makes your car start emitting strange noises when you start it up.
* This code has no bugs, just undocumented features!
*
* /todo
*
* /bug
*
*/
template<class _ACEMutex,class MPINSTANCE>
class CObjectPool : public CGeneralMemoryPool<_ACEMutex,MPINSTANCE>
{
typedef CGeneralMemoryPool<_ACEMutex,MPINSTANCE> supper;
public:
//这个定义应该会屏蔽超类的定义
template<class T>
T* malloc(/*int size*/T*& p)
{
void* obj = supper::malloc(sizeof(T)/*size*/);
::new (obj) T(/* not args */); // 进行默认构造
p = (T*)obj;
return /*(T*)obj*/p;
}
// 释放对象
template<class T>
void free(T* obj)
{
if (obj != 0)
{
obj->~T();
supper::free(obj);
}
}
};
MY_MPN_E // namespace my_mempool
#endif /*MY_MEMBLOCK_H*/
cpp文件
#include <stdlib.h>
#include <algorithm>
#include <fstream>
#include "MemPool.h"
MY_MPN_B
CMPBase::~CMPBase()
{
;
}
int CMPBase::round_up(int size)
{
return (( size + 7) &~ 7);// 按8字节对齐
}
CMapMemoryPool::CMapMemoryPool()
:blockcounter(1),initialized(false)
{
append(DEFAULTSIZE);
}
CMapMemoryPool::CMapMemoryPool(const int & size)
:blockcounter(1),initialized(false)
{
append(size);
}
CMapMemoryPool::~CMapMemoryPool()
{
reap();
}
int CMapMemoryPool::append(int size)
{
if(size < 1024 * 10)
{
size = 1024 * 10;
}
size = round_up(size);
char * p = (char*)::malloc(size);
if(!p)
return -1;
::memset(p,0,size);
_blocks.push_back(temZone(p,size));
mem_control_block * pMCB = (mem_control_block *)p;
pMCB->flag = mbHeader | mbTail;
pMCB->is_available = 1;
pMCB->blockcounter = 0;
pMCB->size = size;
pMCB->blockcounter = blockcounter++;
unsigned int v2,v1;
v2 = (unsigned int)pMCB;
v1 = (unsigned int)++pMCB;
pair<map_type::iterator, bool> r ;
r = free_memory.insert(make_pair(v1,v2));
if(r.second)
{
initialized = true;
return 0;
}
::free(p);
return -1;
}
void CMapMemoryPool::reap(void)
{
initialized = false;
for(vector<temZone>::iterator i = _blocks.begin(); i != _blocks.end() ; ++i)
{
if(i->buf)
::free(i->buf);
}
_blocks.clear();
}
int CMapMemoryPool::count_space(const map_type & m)
{
if(!initialized)
return -1;
CSimpleCount counter__;
for_each(m.begin(),m.end(),counter__);
return counter__.Count();
}
int CMapMemoryPool::malloced(void)
{
if(!initialized)
return -1;
return count_space(malloced_memory);
}
int CMapMemoryPool::freememory(void)
{
if(!initialized)
return -1;
return count_space(free_memory);
}
void * CMapMemoryPool::malloc(int size)
{
if(!initialized)
return NULL;
size = round_up(size);
mem_control_block * p = NULL, * p1 = NULL;
map_type::iterator i,i1 = free_memory.end();
//修改实际内存
for( i = free_memory.begin(); i != free_memory.end(); ++i)
{
p = (mem_control_block *)(i->second);
if( p && p->size > size )
{
if( p->size < size * 2 )
{
p->is_available = 0;
break;
}
else// larger ,blocking partition, Jason
{
int old_size = p->size;
p->is_available = 0;
if(old_size - size < sizeof(mem_control_block))
{
break;
}
p->size = size + sizeof(mem_control_block);
p1 = (mem_control_block*)((char*)p + p->size);
p1->is_available = 1;
p1->size = old_size - p->size;
p1->blockcounter = p->blockcounter;
if( ( p->flag & mbHeader ) == mbHeader && ( p->flag & mbTail ) == mbTail )
{
p->flag = mbHeader;
p1->flag = mbTail;
}
else if( ( p->flag & mbTail ) == mbTail ) //尾巴
{
p1->flag = mbTail;
}
else //if( ( p->flag | mbHeader ) == 0 ) //头和中间的处理一样
{
p1->flag = mbMed;
i1 = ++i;
--i;
mem_control_block * p3 = (mem_control_block *)(i1->second);
if((unsigned int )p1 + p1->size != i1->second ) //不连续
break;
if(p3->blockcounter == p->blockcounter)// same memory block
{
p1->size += p3->size;
p1->flag = p3->flag;
}
}
break;
}
}//if( p && p->size > size )
}//for
//修改表
if( i != free_memory.end() )
{
malloced_memory.insert(*i);
if(i1 != free_memory.end())
free_memory.erase(i,i1);
else
free_memory.erase(i);
if(p1)//新块,加入进来了
{
char * _p = (char*)(p1+1);
free_memory.insert(make_pair((unsigned int)_p,(unsigned int)p1));
}
return (void*)(++p);
}
return NULL;
}
void CMapMemoryPool::free(void * mp)
{
if(!initialized)
return ;
mem_control_block * p = NULL, * p1 = NULL;
map_type::iterator i;
unsigned int k = (unsigned int)mp;
i = malloced_memory.find(k);
if(i != malloced_memory.end())
{
p = (mem_control_block *)i->second;
malloced_memory.erase(i); // i 无效了
p->is_available = 1;
map_type::iterator previ,nexti;
unsigned int _pos,pos_;
map_type::iterator _i = free_memory.end(), i_ = free_memory.end(), it;
pos_ = (unsigned int)p + p->size + sizeof(mem_control_block);
_pos = 0;
for( it = free_memory.begin(); it != free_memory.end() ; ++it)
{
p1 = (mem_control_block *)it->second;
if(p1->blockcounter != p->blockcounter)
continue;
if( (unsigned) p1 + p1->size == (unsigned)p )//正好是前面的
{
_i = it;
}
else if( (unsigned) p1 == (unsigned)p + p->size )//正好是后面的
{
i_ = it;
break;
}
else if((unsigned) p1 /*+ p1->size*/ > (unsigned)p + p->size )
break;
}
if( _i == free_memory.end() && i_ == free_memory.end() )//没有找到邻接点
{
free_memory.insert( make_pair( (unsigned int) p + sizeof(mem_control_block) ,(unsigned int)p ) );
}
else if( _i != free_memory.end() && i_ != free_memory.end() ) //前驱后继都有
{
mem_control_block * _p, *p_;
_p = (mem_control_block *)_i->second;
p_ = (mem_control_block *)i_->second;
_p->size += p->size + p_->size;
if(p_->flag == mbTail)
_p->flag |= p_->flag;
free_memory.erase(_i,i_);
free_memory.insert( make_pair( (unsigned int) _p + sizeof(mem_control_block) ,(unsigned int)_p ) );
}
else if( _i != free_memory.end() )//有前驱点
{
p1 = (mem_control_block *)_i->second;
if(p->flag == mbTail)
p1->flag |= p->flag;
p1->size += p->size;
free_memory.erase(_i);
free_memory.insert( make_pair( (unsigned int) p1 + sizeof(mem_control_block) ,(unsigned int)p1 ) );
}
else if( i_ != free_memory.end() )//有后继点
{
p1 = (mem_control_block *)i_->second;
if(p1->flag == mbTail)
p->flag |= p1->flag;
p->size += p1->size;
free_memory.erase(i_);
free_memory.insert( make_pair( (unsigned int) p + sizeof(mem_control_block) ,(unsigned int)p ) );
}
}
}
void CMapMemoryPool::dump(const string & file)
{
if(!initialized)
return ;
fstream fs;
fs.open(file.c_str(),/*ios::oct |*/ ios_base::out | ios::binary | ios::ate | ios::app);
if(!fs.bad())
{
for( vector<temZone>::iterator i = _blocks.begin(); i != _blocks.end() ; ++i )
{
fs.write((const char *)i->buf,i->size);
}
fs.close();
}
}
MY_MPN_E