|
查看以前写的一个对象池,感觉代码凌乱,今天重构了一下。
#ifndef _TObjectPoolV12_H_
#define _TObjectPoolV12_H_
#include<iostream>
#pragma warning(disable: 4786)//关闭4786错误(STL调试信息过长,超过255字符)
#include<list>
#include<algorithm>
namespace Aura
{
//TObjectPool1.2
//对象池模版,池里分配预算定数量的对象,用时从池申请,不用时归还池,采用页链表技术使池理论无上限
enum TObjectPool_error
{
TObjectPool_error_no,
TObjectPool_error_memory, //内存分配错误
TObjectPool_error_null_pointer, //无效对象指针
TObjectPool_error_multiple_return, //多重归还对象
};
template <typename T,int k=16>
class TObjectPool
{
private:
class page;
public:
//proxy classes
class Ptr
{
public:
friend class page;
Ptr():m_p(NULL){}
~Ptr(){}
T* operator->()const{return m_p;}
T& operator*()const{return *m_p;}
bool is_null()const{return NULL==m_p;}
private:
Ptr(T* p){}
Ptr(const Ptr& rhs){}
Ptr& operator=(const Ptr& rhs){}
T* m_p;
};
public:
TObjectPool();
~TObjectPool();
//申请一个对象
bool operator >>(Ptr& ptr);
//归还一个对象(注意:归后ptr为NULL值)。
bool operator <<(Ptr& ptr);
//获取错误代码
TObjectPool_error error()const{return m_error;}
private:
class page
{
public:
T m_objects[k]; //对象数组
T* m_objects_statck[k]; //对象堆,堆中存储的是对象指针
bool m_objects_idle_flag[k];//对象的空闲标志
unsigned long m_statck_top; //堆顶,当为0时说明对象已用完
unsigned long m_object_count; //对象数量
page():m_object_count(k)
{
for(m_statck_top=0; m_statck_top<m_object_count; ++m_statck_top)
{
m_objects_statck[m_statck_top]=&m_objects[m_statck_top];
m_objects_idle_flag[m_statck_top]=true;
}
}
bool is_empty(){return 0==m_statck_top;}
bool is_full(){return m_statck_top==m_object_count;}
bool is_member(const Ptr& ptr){return ((&(*ptr)>=m_objects)&&(&(*ptr)<=&m_objects[m_object_count-1]));}
void operator >>(Ptr& ptr)
{
--m_statck_top;
m_objects_idle_flag[m_objects_statck[m_statck_top]-m_objects]=false;
ptr.m_p=m_objects_statck[m_statck_top];
}
TObjectPool_error operator <<(Ptr& ptr)
{
T* p=ptr.m_p;
long a=p-m_objects;
long b=(long)p-(long)m_objects;
if((b%sizeof(T))!=0)return TObjectPool_error_null_pointer;
if(is_full()||m_objects_idle_flag[a])return TObjectPool_error_multiple_return;
m_objects_idle_flag[a]=true;
m_objects_statck[m_statck_top]=p;
++m_statck_top;
ptr.m_p=NULL;
return TObjectPool_error_no;
}
};
std::list<page*> m_lspage;
std::list<page*>::iterator m_current_page;
unsigned long m_idle_object_count; //空闲对象数量
TObjectPool_error m_error; //错误代码
};
//end
//////////////////////////////////
//TObjectPool Class template implement
//////////////////////////////////////
template <typename T,int k>
TObjectPool<T,k>::TObjectPool():m_idle_object_count(0),m_error(TObjectPool_error_no)
{
m_lspage.push_back(new page);
m_current_page=m_lspage.begin();
m_idle_object_count+=k;
}
//函数对象,用于销毁容器中new出来的对象
struct DeleteObject{
template<typename T>
void operator()(T* p)const{delete p;}
};
template <typename T,int k>
TObjectPool<T,k>::~TObjectPool(){std::for_each(m_lspage.begin(), m_lspage.end(),DeleteObject());}
template <typename T,int k>
bool TObjectPool<T,k>: perator >>(TObjectPool<T,k>: tr& ptr)
{
if(m_error!=TObjectPool_error_no)return false;
if(!ptr.is_null()){if(!operator <<(ptr))return false;}
std::list<TObjectPool<T,k>::page*>::iterator end=m_current_page;
for(; m_current_page!=m_lspage.end(); ++m_current_page)
{
if(!(*(*m_current_page)).is_empty()) //如果不为空就申请一个对象
{
--m_idle_object_count; //一个对象成功分配,空闲对象数量减1
(*(*m_current_page))>>(ptr);
return true;
}
}
for(m_current_page=m_lspage.begin(); m_current_page!=end; ++m_current_page)
{
if(!(*(*m_current_page)).is_empty()) //如果不为空就申请一个对象
{
--m_idle_object_count; //一个对象成功分配,空闲对象数量减1
(*(*m_current_page))>>(ptr);
return true;
}
}
//如果循环结束还没找到空闲对象,说明页面已经用完,需要分配新页面
m_lspage.push_back(new page);
m_current_page=m_lspage.end();
--m_current_page;
m_idle_object_count+=k-1; //空闲对象数量增加一个页面的数量-1
(*(*m_current_page))>>(ptr);
return true;
}
template <typename T,int k>
bool TObjectPool<T,k>::operator <<(TObjectPool<T,k>::Ptr& ptr)
{
if(m_error!=TObjectPool_error_no)return false;
if(ptr.is_null())
{
m_error=TObjectPool_error_null_pointer;
return false;
}
bool ok=false;
std::list<TObjectPool<T,k>::page*>::iterator end=m_current_page;
for(; m_current_page!=m_lspage.end(); ++m_current_page)
{
if((*(*m_current_page)).is_member(ptr))//对象是否属于此页
{
TObjectPool_error Ret=(*(*m_current_page))<<(ptr);
if(TObjectPool_error_no!=Ret)
{
m_error=Ret;
return false;
}
++m_idle_object_count; //一个对象成功归还,空闲对象数量加1
ok=true;
break;
}
}
if(!ok)
{
for(m_current_page=m_lspage.begin(); m_current_page!=end; ++m_current_page)
{
if((*(*m_current_page)).is_member(ptr))//对象是否属于此页
{
TObjectPool_error Ret=(*(*m_current_page))<<(ptr);
if(TObjectPool_error_no!=Ret)
{
m_error=Ret;
return false;
}
++m_idle_object_count; //一个对象成功归还,空闲对象数量加1
ok=true;
break;
}
}
}
//如果空闲对象数量大于2倍页面数量,说明空闲对象太多了,需要释放一些以减少内存占用
if(m_idle_object_count>=(k<<1))
{
//遍历页面链表,找出空闲页面并释放
for(std::list<TObjectPool<T,k>::page*>::iterator i=m_lspage.begin(); i!=m_lspage.end();)
{
if((*(*i)).is_full())
{
delete *i;
i=m_lspage.erase(i);
m_idle_object_count -= k;
}
else ++i;
}
}
return true;
}
};
#endif
|
|