对象池
/* ---------------------------------------------------------------- */
/* Copyright 2005 (c) by RWTH Aachen - Lehrstuhl fuer Informatik VI */
/* Richard Zens */
/* ---------------------------------------------------------------- */
#include <vector>
#include <deque>
#include <string>
#include <iostream>
#include <iterator>
#include <stdio.h>
#include "CTimeUtil.h"
using namespace std;
/***
* template class for pool of objects
* - useful if many small objects are frequently created and destroyed
* - allocates memory for N objects at a time
* - separates memory allocation from constructor/destructor calls
* - prevents memory leaks
*/
template<typename T> class ObjectPool {
public:
typedef T Object;
private:
std::string name; /*对象的名字*/
size_t idx,dIdx,N; /*N初始分配对象的大小*/
std::vector<Object*> data; /*装载分配的对象*/
std::vector<size_t> dataSize;/*记录分配对象的大小*/
std::deque<Object*> freeObj; /*双端对列,放入不再使用的对象*/
int mode; /*模式*/
public:
static const int cleanUpOnDestruction=1; /*用来对对象进行清除的标志*/
static const int hasTrivialDestructor=2; /*是否有无意义的构建函数*/
// constructor arguments:
// N: initial number of objects to allocate memory at a time
// m & cleanUpOnDestruction = clean up objects in destructor
// m & hasTrivialDestructor = the object type has a trivial destructor,
// i.e. no sub-object uses dynamically allocated memory
// note: not equivalent to empty destructor
// -> more efficient (destructor calls can be omitted),
// note: looks like memory leak, but is not
ObjectPool(std::string name_="T",size_t N_=100000,int m=cleanUpOnDestruction)
: name(name_),idx(0),dIdx(0),N(N_),mode(m)
{
CTimeUtil ut;
ut.Begin();
allocate();
cout<<"allocate :" << ut.End()<<endl;
}
// main accesss functions:
// get pointer to object via default or copy constructor
Object* get()
{
return new (getPtr()) Object; /*在getPtr返回的地址上建立Object*/
}
Object* get(const Object& x)
{
return new (getPtr()) Object(x);
}
// get pointer to uninitialized memory,
// WARNING: use only if you know what you are doing !
// useful for non-default constructors, you have to use placement new
Object* getPtr()
{
/*若有空余的对象,则将这个对象析构,返回其地址,分配新的对象*/
if (freeObj.size())
{
Object* rv = freeObj.back();
freeObj.pop_back();
rv->~Object();
return rv;
}
if (idx == dataSize[dIdx])
{
idx=0;
if (++dIdx == data.size())
{
allocate();
}
}
return data[dIdx]+idx++;/*返回分配地址*/
}
// return object(s) to pool for reuse
// note: objects are not destroyed here, but in 'getPtr'/'destroyObjects',
// otherwise 'destroyObjects' would have to check the freeObj-stack
// before each destructor call
void freeObject(Object* x)
{
freeObj.push_back(x); /*并不删除对象,将其放入freeObj中,以重复利用*/
}
template<class fwiter>
void freeObjects(fwiter b, fwiter e)
{
for(;b!=e;++b)
{
this->free(*b);
}
}
// destroy all objects, but do not free memory
void reset()
{
destroyObjects();
idx=0;
dIdx=0;
freeObj.clear();
}
// destroy all objects and free memory
void cleanUp()
{
reset();
for(size_t i=0;i<data.size();++i)
{
free(data[i]);
}
data.clear();
dataSize.clear();
}
~ObjectPool()
{
if(mode & cleanUpOnDestruction)
{
cleanUp();
}
}
void printInfo(std::ostream& out) const
{
out<<"OPOOL ("<<name<<") info: "<<data.size()<<" "<<dataSize.size()<<" "
<<freeObj.size()<<"\n"<<idx<<" "<<dIdx<<" "<<N<<"\n";
std::copy(dataSize.begin(),dataSize.end(),
std::ostream_iterator<size_t>(out," "));
out<<"\n\n";
}
private:
void destroyObjects()
{
if(mode & hasTrivialDestructor)
return;
for(size_t i=0;i<=dIdx;++i)
{
size_t lastJ= (i<dIdx ? dataSize[i] : idx);
for(size_t j=0;j<lastJ;++j)
{
(data[i]+j)->~Object();
}
}
}
// allocate memory for a N objects, for follow-up allocations,
// the block size is doubled every time
// if allocation fails, block size is reduced by 1/4
void allocate()
{
try
{
if(dataSize.empty())
{
dataSize.push_back(N);
}
else
{
dataSize.push_back( dataSize.back() * 2 );
}
void *m = malloc(sizeof(Object)*dataSize.back());
while(!m)
{
/*分配不成功,一次减小1/4*/
dataSize.back() = static_cast<size_t>(dataSize.back() * 0.75);
m = malloc(sizeof(Object)*dataSize.back());
}
data.push_back(static_cast<Object*>(m));
}
catch (const std::exception& e)
{
cerr<<"caught std::exception: "<<e.what()
<<" in ObjectPool::allocate(), name: "<<name<<", last size: "
<<dataSize.back()<<"\n";
cerr<<"OPOOL info: "<<data.size()<<" "<<dataSize.size()<<" "
<<freeObj.size()<<"\n"<<idx<<" "<<dIdx<<" "<<N<<"\n";
std::copy(dataSize.begin(),dataSize.end(),
std::ostream_iterator<size_t>(std::cerr," "));
cerr<<"\n";
throw;
}
}
};
class TestObject;
static ObjectPool<TestObject> s_objectPool("T", 10000000);
class TestObject
{
public:
#ifdef USE_OBJ_POOL
static ObjectPool<TestObject>* GetPool()
{
return &s_objectPool;
}
#endif
public:
TestObject():name("TestObject"),id(0),sum1(0.0f),sum2(0.0),sum3(0.0){};
~TestObject(){};
#ifdef USE_OBJ_POOL
void *operator new(size_t num_bytes)
{
void *ptr = s_objectPool.getPtr();
return ptr;
}
static void Delete(TestObject *obj)
{
s_objectPool.freeObject(obj);
}
#else
static void Delete(TestObject *obj)
{
delete obj;
}
#endif
private:
string name;
int id;
double sum1;
double sum2;
double sum3;
};
//for test
#define TEST_MAX_OBJ_COUNT 10000000
int main(int argc, char *argv)
{
CTimeUtil ut1;
CTimeUtil ut;
#ifdef USE_OBJ_POOL
s_objectPool.printInfo(cout);
#endif
//*
vector<TestObject*> vec;
vec.reserve(TEST_MAX_OBJ_COUNT);
ut1.Begin();
ut.Begin();
for ( int i = 0; i < TEST_MAX_OBJ_COUNT; i++)
{
vec.push_back(new TestObject());
}
#ifdef USE_OBJ_POOL
cout<<"Used Object Pool : new time :" << ut.End()<<endl;
s_objectPool.printInfo(cout);
#else
cout<<"NoUsed Object Pool : new time :" << ut.End()<<endl;
#endif
ut.Begin();
for ( vector<TestObject*>::iterator it = vec.begin(); it != vec.end(); ++it )
{
TestObject::Delete(*it);
}
#ifdef USE_OBJ_POOL
cout<<"Used Object Pool : delete time :" << ut.End()<<endl;
s_objectPool.printInfo(cout);
#else
cout<<"NoUsed Object Pool : delete time :" << ut.End()<<endl;
#endif
// */
/*
for (int i = 0; i < TEST_MAX_OBJ_COUNT; i++)
{
TestObject* pObj = new TestObject();
TestObject::Delete(pObj);
}
*/
#ifdef USE_OBJ_POOL
cout<<"Used Object Pool : time :" << ut1.End()<<endl;
#else
cout<<"NoUsed Object Pool : time :" << ut1.End()<<endl;
#endif
return 0;
}
对象池
最新推荐文章于 2023-12-23 16:31:45 发布