00001 #ifndef BlockWipedAllocator_H 00002 #define BlockWipedAllocator_H 00003 00004 #include<vector> 00005 #include<list> 00006 #include<map> 00007 #include <algorithm> 00008 00009 #include<boost/bind.hpp> 00010 00011 // #include<iostream> 00012 00013 /* Allocator that never removes single allocations 00014 * it "wipes" or "clears" the whole allocation when not needed anymore 00015 * if not wiped it may easily run out of memory 00016 */ 00017 class BlockWipedAllocator { 00018 public: 00019 BlockWipedAllocator( std::size_t typeSize, 00020 std::size_t blockSize); 00021 00022 00023 /* copy constructor clone the allocator and the memory it manages 00024 * it needs to be reinitialized to avoid pointing to "rh" 00025 * 00026 */ 00027 BlockWipedAllocator(BlockWipedAllocator const & rh); 00028 00029 BlockWipedAllocator& operator=(BlockWipedAllocator const & rh); 00030 00031 00032 void * alloc(); 00033 00034 void dealloc(void *); 00035 00036 // redime memory to the system heap 00037 void clear() const; 00038 00039 // reset allocator status. does not redime memory 00040 void wipe() const; 00041 00042 00043 // longliving (static) local caches: to be reset at wipe 00044 struct LocalCache { 00045 virtual ~LocalCache(){} 00046 virtual void reset()=0; 00047 }; 00048 00049 void registerCache(LocalCache * c) { 00050 localCaches.push_back(c); 00051 } 00052 00053 private: 00054 std::vector<LocalCache*> localCaches; 00055 00056 00057 protected: 00058 00059 BlockWipedAllocator & me() const; 00060 00061 public: 00062 00063 struct Stat { 00064 size_t typeSize; 00065 size_t blockSize; 00066 size_t currentOccupancy; 00067 size_t currentAvailable; 00068 size_t totalAvailable; 00069 size_t nBlocks; 00070 int alive; 00071 }; 00072 00073 Stat stat() const; 00074 00075 private: 00076 void nextBlock(bool advance); 00077 00078 00079 struct Block { 00080 std::size_t m_allocated; 00081 std::vector<unsigned char> m_data; 00082 }; 00083 00084 typedef unsigned char * pointer; 00085 typedef std::list<Block> Blocks; 00086 typedef Blocks::iterator iterator; 00087 typedef Blocks::const_iterator const_iterator; 00088 00089 00090 std::size_t m_typeSize; 00091 std::size_t m_blockSize; 00092 pointer m_next; 00093 iterator m_current; 00094 Blocks m_blocks; 00095 00096 int m_alive; // for stat purposes 00097 00098 }; 00099 00100 00101 class BlockWipedPool { 00102 public: 00103 typedef BlockWipedAllocator Allocator; 00104 typedef std::map<std::size_t, Allocator> Pool; 00105 00106 BlockWipedPool(std::size_t blockSize); 00107 00108 Allocator & allocator( std::size_t typeSize); 00109 00110 void wipe(); 00111 00112 void clear(); 00113 00114 template<typename Visitor> 00115 void visit(Visitor& visitor) const { 00116 std::for_each(m_pool.begin(),m_pool.end(),boost::bind(&Visitor::visit,visitor, 00117 boost::bind(&Pool::value_type::second,_1) 00118 )); 00119 } 00120 00121 00122 private: 00123 std::size_t m_blockSize; 00124 Pool m_pool; 00125 }; 00126 00127 00128 // singleton 00129 BlockWipedPool & blockWipedPool(); 00130 00131 template<size_t S> 00132 BlockWipedAllocator & blockWipedAllocator() { 00133 static BlockWipedAllocator & local = blockWipedPool().allocator(S); 00134 return local; 00135 } 00136 00137 template<typename T> 00138 struct LocalCache : public BlockWipedAllocator::LocalCache { 00139 std::auto_ptr<T> ptr; 00140 LocalCache(){ 00141 blockWipedAllocator<sizeof(T)>().registerCache(this); 00142 } 00143 ~LocalCache(){} 00144 void reset(){ ptr.reset();} 00145 }; 00146 00147 00148 /* generaric Basic class 00149 * 00150 */ 00151 class BlockWipedPoolAllocated { 00152 public: 00153 virtual ~BlockWipedPoolAllocated(){} 00154 // instance counter... 00155 static int s_alive; 00156 static void * operator new(size_t s, void * p); 00157 static void * operator new(size_t s); 00158 00159 static void operator delete(void * p, size_t s); 00160 00161 static BlockWipedAllocator & allocator(size_t s); 00162 00163 00164 static BlockWipedAllocator::Stat stat(size_t s); 00165 00166 // throw id s_alive!=0??? 00167 static void usePool(); 00168 00169 00170 private: 00171 static bool s_usePool; 00172 // static BlockAllocator * s_allocator; 00173 }; 00174 00175 // below: not used 00176 00177 /* Allocator by type 00178 * 00179 */ 00180 template<typename T> 00181 class BlockWipedAllocated { 00182 public: 00183 static void * operator new(size_t) { 00184 return allocator().alloc(); 00185 } 00186 00187 static void operator delete(void * p) { 00188 allocator().dealloc(p); 00189 } 00190 00191 static BlockWipedAllocator & allocator() { 00192 static BlockWipedAllocator & local = blockWipedPool().allocator(sizeof(T)); 00193 return local; 00194 } 00195 00196 00197 static BlockWipedAllocator::Stat stat() { 00198 return allocator().stat(); 00199 } 00200 00201 00202 private: 00203 00204 // static BlockAllocator * s_allocator; 00205 }; 00206 00207 00208 /* Allocator by size 00209 * 00210 */ 00211 template<typename T> 00212 class SizeBlockWipedAllocated { 00213 public: 00214 static void * operator new(size_t) { 00215 return allocator().alloc(); 00216 } 00217 00218 static void operator delete(void * p) { 00219 allocator().dealloc(p); 00220 } 00221 00222 static BlockWipedAllocator & allocator() { 00223 static BlockWipedAllocator & local = blockWipedAllocator<sizeof(T)>(); 00224 return local; 00225 } 00226 00227 00228 static BlockWipedAllocator::Stat stat() { 00229 return allocator().stat(); 00230 } 00231 00232 private: 00233 00234 // static BlockAllocator * s_allocator; 00235 }; 00236 00237 00238 #endif // BlockAllocator_H