|
经过一天的思考后,决定还是把变量k(也就是每一内存页中对象的数量)放在构造函数中,因为这个变量需要调整以取得最佳性能,而如果程序中定义了大量的TObjectPool<T,k>: tr后,调整k值,这些定义语句也要写改,所以把它从模版参数移入构造函数中,这样改动k值只需改写一句程序就可以了。
#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, //重复归还
};
const static char* TObjectPool_error_strings_A[] = {
"正常",
"内存分配错误",
"无效指针",
"重复归还"};
const static wchar_t* TObjectPool_error_strings_W[] = {
L"正常",
L"内存分配错误",
L"无效指针",
L"重复归还"};
#ifdef UNICODE
#define TObjectPool_error_strings TObjectPool_error_strings_W
#else
#define TObjectPool_error_strings TObjectPool_error_strings_A
#endif
template <typename T>
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;}
operator bool()const{return NULL!=m_p;}
private:
Ptr(T* p){}
Ptr(const Ptr& rhs){}
Ptr& operator=(const Ptr& rhs){}
T* m_p;
};
public:
TObjectPool(unsigned long per_page_object_count=16);
~TObjectPool();
//申请一个对象
bool operator >>(Ptr& ptr);
//归还一个对象(注意:归后ptr为NULL值)。
bool operator <<(Ptr& 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_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;
}
}
~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 Ptr& ptr){return ((ptr.m_p>=m_objects)&&(ptr.m_p<=&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;
}
private:
T* m_objects; //对象数组
T** m_objects_statck; //对象堆,堆中存储的是对象指针
bool* m_objects_idle_flag; //对象的空闲标志
unsigned long m_statck_top; //堆顶,当为0时说明对象已用完
unsigned long m_object_count; //对象数量
bool m_memory_error; //内存分配错误
};
std::list<page*> m_lspage;
std::list<page*>::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 <typename T>
TObjectPool<T>::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{
template<typename T>
void operator()(T* p)const{delete p;}
};
template <typename T>
TObjectPool<T>::~TObjectPool(){std::for_each(m_lspage.begin(), m_lspage.end(),DeleteObject());}
template <typename T>
bool TObjectPool<T>: perator >>(TObjectPool<T>::Ptr& ptr)
{
if(m_error!=TObjectPool_error_no)return false;
if(ptr){if(!operator <<(ptr))return false;}
std::list<TObjectPool<T>::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_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))>>(ptr);
return true;
}
template <typename T>
bool TObjectPool<T>::operator <<(TObjectPool<T>::Ptr& ptr)
{
if(m_error!=TObjectPool_error_no)return false;
if(!ptr)
{
m_error=TObjectPool_error_null_pointer;
return false;
}
bool ok=false;
std::list<TObjectPool<T>::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>=(m_per_page_object_count<<1))
{
//遍历页面链表,找出空闲页面并释放
for(std::list<TObjectPool<T>::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 -= m_per_page_object_count;
}
else ++i;
}
}
return true;
}
};
#endif
用例:
#include <iostream>
#include"TObjectPoolV12.h"
using namespace std;
using namespace Aura;
class CStudent
{
public:
long age;
long money;
long id;
};
void printa(const TObjectPool<CStudent>::Ptr& i)
{
if(i)cout<<"年龄:"<<i->age<<"岁"<<endl;
}
int main()
{
TObjectPool<CStudent> SOP(200);
TObjectPool<CStudent>::Ptr p[100];
for(int i=0; i<100;++i)SOP>>p;
cout<<TObjectPool_error_strings[SOP.error()]<<endl;
p[0]->age=10;
printa(p[0]);
for(i=0; i<100;++i)SOP<<p;
cout<<TObjectPool_error_strings[SOP.error()]<<endl;
return 0;
}
|
|