经过一天的思考后,决定还是把变量k(也就是每一内存页中对象的数量)放在构造函数中,因为这个变量需要调整以取得最佳性能,而如果程序中定义了大量的TObjectPoollt;T,kgt;:tr后,调整k值,这些定义语句也要写改,所以把它从模版参数移入构造函数中,这样改动k值只需改写一句程序就可以了。

#ifndef _TObjectPoolV12_H_
#define _TObjectPoolV12_H_


#includelt;iostreamgt;

#pragma warning(disable: 4786)//关闭4786错误(STL调试信息过长,超过255字符)
#includelt;listgt;
#includelt;algorithmgt;

namespace Aura
{
//TObjectPool1.2
//对象池模版,池里分配预算定数量的对象,用时从池申请,不用时归还池,采用页链表技术使池理论无上限

//错误信息
enum TObjectPool_error
{
TObjectPool_error_no,
TObjectPool_error_memory, //内存分配错误
TObjectPool_error_null_pointer, //无效指针
TObjectPool_error_multiple_return,//重复归还
};
const static char* TObjectPool_error_strings_A[] = {
quot;正常quot;,
quot;内存分配错误quot;,
quot;无效指针quot;,
quot;重复归还quot;};
const static wchar_t* TObjectPool_error_strings_W[] = {
Lquot;正常quot;,
Lquot;内存分配错误quot;,
Lquot;无效指针quot;,
Lquot;重复归还quot;};
#ifdef UNICODE
#define TObjectPool_error_strings TObjectPool_error_strings_W
#else
#define TObjectPool_error_strings TObjectPool_error_strings_A
#endif

template lt;typename Tgt;
class TObjectPool
{
private:
class page;
public:
//proxy classes
class Ptr
{
public:
friend class page;

Ptr():m_p(NULL){}
~Ptr(){}

T* operator-gt;()const{return m_p;}
Tamp; operator*()const{return *m_p;}

operator bool()const{return NULL!=m_p;}
private:
Ptr(T* p){}
Ptr(const Ptramp; rhs){}
Ptramp; operator=(const Ptramp; rhs){}

T* m_p;
};
public:
TObjectPool(unsigned long per_page_object_count=16);
~TObjectPool();

//申请一个对象
bool operator gt;gt;(Ptramp; ptr);
//归还一个对象(注意:归后ptr为NULL值)。
bool operator lt;lt;(Ptramp; ptr);
//获取错误代码
TObjectPool_error error()const{return m_error;}
private:
class page
{
public:
page(unsigned long k)
:m_object_count(k),m_objects(0),m_objects_statck(0),m_objects_idle_flag(0),m_memory_error(false)
{
if(NULL==(m_objects=new T[m_object_count])){set_memory_error();return;}
if(NULL==(m_objects_statck=new T*[m_object_count])){set_memory_error();return;}
if(NULL==(m_objects_idle_flag=new bool[m_object_count])){set_memory_error();return;}
for(m_statck_top=0; m_statck_toplt;m_object_count; ++m_statck_top)
{
m_objects_statck[m_statck_top]=amp;m_objects[m_statck_top];
m_objects_idle_flag[m_statck_top]=true;
}
}
~page(){release();}

void release()
{
if(NULL!=m_objects)delete[] m_objects;
if(NULL!=m_objects_statck)delete[] m_objects_statck;
if(NULL!=m_objects_idle_flag)delete[] m_objects_idle_flag;
}
void set_memory_error(){m_memory_error=true;release();}
bool memory_error()const{return m_memory_error;}
bool is_empty()const{return 0==m_statck_top;}
bool is_full()const{return m_statck_top==m_object_count;}
bool is_member(const Ptramp; ptr){return ((ptr.m_pgt;=m_objects)amp;amp;(ptr.m_plt;=amp;m_objects[m_object_count-1]));}

void operator gt;gt;(Ptramp; 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 lt;lt;(Ptramp; 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;
}

private:
T* m_objects; //对象数组
T** m_objects_statck; //对象堆,堆中存储的是对象指针
bool* m_objects_idle_flag;//对象的空闲标志
unsigned longm_statck_top; //堆顶,当为0时说明对象已用完
unsigned longm_object_count; //对象数量
bool m_memory_error; //内存分配错误
};

std::listlt;page*gt; m_lspage;
std::listlt;page*gt;::iterator m_current_page;
unsigned long m_per_page_object_count;
unsigned long m_idle_object_count;//空闲对象数量
TObjectPool_error m_error; //错误代码
};
//end

//////////////////////////////////
//TObjectPool Class template implement
//////////////////////////////////////
template lt;typename Tgt;
TObjectPoollt;Tgt;::TObjectPool(unsigned long per_page_object_count)
:m_per_page_object_count(per_page_object_count),m_idle_object_count(0),m_error(TObjectPool_error_no)
{
m_lspage.push_back(new page(m_per_page_object_count));
m_current_page=m_lspage.begin();
if((*(*m_current_page)).memory_error()){m_error=TObjectPool_error_memory;return;}
m_idle_object_count+=m_per_page_object_count;
}

//函数对象,用于销毁容器中new出来的对象
struct DeleteObject{
templatelt;typename Tgt;
void operator()(T* p)const{delete p;}
};
template lt;typename Tgt;
TObjectPoollt;Tgt;::~TObjectPool(){std::for_each(m_lspage.begin(), m_lspage.end(),DeleteObject());}

template lt;typename Tgt;
bool TObjectPoollt;Tgt;:perator gt;gt;(TObjectPoollt;Tgt;::Ptramp; ptr)
{
if(m_error!=TObjectPool_error_no)return false;
if(ptr){if(!operator lt;lt;(ptr))return false;}

std::listlt;TObjectPoollt;Tgt;::page*gt;::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))gt;gt;(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))gt;gt;(ptr);
return true;
}
}

//如果循环结束还没找到空闲对象,说明页面已经用完,需要分配新页面
m_lspage.push_back(new page(m_per_page_object_count));
m_current_page=m_lspage.end();
--m_current_page;
if((*(*m_current_page)).memory_error()){m_error=TObjectPool_error_memory;return false;}
m_idle_object_count+=m_per_page_object_count-1;//空闲对象数量增加一个页面的数量-1
(*(*m_current_page))gt;gt;(ptr);
return true;
}

template lt;typename Tgt;
bool TObjectPoollt;Tgt;::operator lt;lt;(TObjectPoollt;Tgt;::Ptramp; ptr)
{
if(m_error!=TObjectPool_error_no)return false;
if(!ptr)
{
m_error=TObjectPool_error_null_pointer;
return false;
}
bool ok=false;
std::listlt;TObjectPoollt;Tgt;::page*gt;::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))lt;lt;(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))lt;lt;(ptr);
if(TObjectPool_error_no!=Ret)
{
m_error=Ret;
return false;
}
++m_idle_object_count;//一个对象成功归还,空闲对象数量加1
ok=true;
break;
}
}
}

//如果空闲对象数量大于2倍页面数量,说明空闲对象太多了,需要释放一些以减少内存占用
if(m_idle_object_countgt;=(m_per_page_object_countlt;lt;1))
{
//遍历页面链表,找出空闲页面并释放
for(std::listlt;TObjectPoollt;Tgt;::page*gt;::iterator i=m_lspage.begin(); i!=m_lspage.end();)
{
if((*(*i)).is_full())
{
delete *i;
i=m_lspage.erase(i);
m_idle_object_count -= m_per_page_object_count;
}
else ++i;
}
}
return true;
}

};

#endif







用例:
#include lt;iostreamgt;
#includequot;TObjectPoolV12.hquot;
using namespace std;
using namespace Aura;

class CStudent
{
public:
long age;
long money;
long id;
};

void printa(const TObjectPoollt;CStudentgt;::Ptramp; i)
{
if(i)coutlt;lt;quot;年龄:quot;lt;lt;i-gt;agelt;lt;quot;岁quot;lt;lt;endl;
}

int main()
{

TObjectPoollt;CStudentgt; SOP(200);
TObjectPoollt;CStudentgt;::Ptr p[100];
for(int i=0; ilt;100;++i)SOPgt;gt;p;
coutlt;lt;TObjectPool_error_strings[SOP.error()]lt;lt;endl;
p[0]-gt;age=10;
printa(p[0]);
for(i=0; ilt;100;++i)SOPlt;lt;p;
coutlt;lt;TObjectPool_error_strings[SOP.error()]lt;lt;endl;
return 0;
}

锐亚教育

锐亚教育,游戏开发论坛|游戏制作人|游戏策划|游戏开发|独立游戏|游戏产业|游戏研发|游戏运营| unity|unity3d|unity3d官网|unity3d 教程|金融帝国3|8k8k8k|mcafee8.5i|游戏蛮牛|蛮牛 unity|蛮牛