00001
00002
00003
00004
00005
00006
00007
00008 #ifndef moses_ObjectPool_h
00009 #define moses_ObjectPool_h
00010
00011 #include <vector>
00012 #include <deque>
00013 #include <string>
00014 #include <iostream>
00015 #include <iterator>
00016 #include "Util.h"
00017
00018
00019
00020
00021
00022
00023
00024
00025 template<typename T> class ObjectPool
00026 {
00027 public:
00028 typedef T Object;
00029 private:
00030 std::string name;
00031 size_t idx,dIdx,N;
00032 std::vector<Object*> data;
00033 std::vector<size_t> dataSize;
00034 std::deque<Object*> freeObj;
00035 int mode;
00036 public:
00037 static const int cleanUpOnDestruction=1;
00038 static const int hasTrivialDestructor=2;
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 ObjectPool(std::string name_="T",size_t N_=100000,int m=cleanUpOnDestruction)
00049 : name(name_),idx(0),dIdx(0),N(N_),mode(m) {
00050 allocate();
00051 }
00052
00053
00054
00055 Object* get() {
00056 return new (getPtr()) Object;
00057 }
00058 Object* get(const Object& x) {
00059 return new (getPtr()) Object(x);
00060 }
00061
00062
00063
00064
00065 Object* getPtr() {
00066 if(freeObj.size()) {
00067 Object* rv=freeObj.back();
00068 freeObj.pop_back();
00069 rv->~Object();
00070 return rv;
00071 }
00072 if(idx==dataSize[dIdx]) {
00073 idx=0;
00074 if(++dIdx==data.size()) allocate();
00075 }
00076 return data[dIdx]+idx++;
00077 }
00078
00079
00080
00081
00082
00083 void freeObject(Object* x) {
00084 freeObj.push_back(x);
00085 }
00086 template<class fwiter> void freeObjects(fwiter b,fwiter e) {
00087 for(; b!=e; ++b) this->free(*b);
00088 }
00089
00090
00091 void reset() {
00092 destroyObjects();
00093 idx=0;
00094 dIdx=0;
00095 freeObj.clear();
00096 }
00097
00098 void cleanUp() {
00099 reset();
00100 for(size_t i=0; i<data.size(); ++i) free(data[i]);
00101 data.clear();
00102 dataSize.clear();
00103 }
00104
00105 ~ObjectPool() {
00106 if(mode & cleanUpOnDestruction) cleanUp();
00107 }
00108
00109 void printInfo(std::ostream& out) const {
00110 out<<"OPOOL ("<<name<<") info: "<<data.size()<<" "<<dataSize.size()<<" "
00111 <<freeObj.size()<<"\n"<<idx<<" "<<dIdx<<" "<<N<<"\n";
00112 std::copy(dataSize.begin(),dataSize.end(),
00113 std::ostream_iterator<size_t>(out," "));
00114 out<<"\n\n";
00115 }
00116
00117
00118 private:
00119 void destroyObjects() {
00120 if(mode & hasTrivialDestructor) return;
00121 for(size_t i=0; i<=dIdx; ++i) {
00122 size_t lastJ= (i<dIdx ? dataSize[i] : idx);
00123 for(size_t j=0; j<lastJ; ++j) (data[i]+j)->~Object();
00124 }
00125 }
00126
00127
00128
00129 void allocate() {
00130 try {
00131 if(dataSize.empty()) dataSize.push_back(N);
00132 else dataSize.push_back(dataSize.back()*2);
00133 void *m=malloc(sizeof(Object)*dataSize.back());
00134 while(!m) {
00135 dataSize.back()=static_cast<size_t>(dataSize.back()*0.75);
00136 m=malloc(sizeof(Object)*dataSize.back());
00137 }
00138 data.push_back(static_cast<Object*>(m));
00139 } catch (const std::exception& e) {
00140 TRACE_ERR("caught std::exception: "<<e.what()
00141 <<" in ObjectPool::allocate(), name: "<<name<<", last size: "
00142 <<dataSize.back()<<"\n");
00143 TRACE_ERR("OPOOL info: "<<data.size()<<" "<<dataSize.size()<<" "
00144 <<freeObj.size()<<"\n"<<idx<<" "<<dIdx<<" "<<N<<"\n");
00145 std::copy(dataSize.begin(),dataSize.end(),
00146 std::ostream_iterator<size_t>(std::cerr," "));
00147 TRACE_ERR("\n");
00148 throw;
00149 }
00150 }
00151 };
00152
00153 #endif