Home | nevrax.com |
|
block_memory.hGo to the documentation of this file.00001 00007 /* Copyright, 2001 Nevrax Ltd. 00008 * 00009 * This file is part of NEVRAX NEL. 00010 * NEVRAX NEL is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2, or (at your option) 00013 * any later version. 00014 00015 * NEVRAX NEL is distributed in the hope that it will be useful, but 00016 * WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 * General Public License for more details. 00019 00020 * You should have received a copy of the GNU General Public License 00021 * along with NEVRAX NEL; see the file COPYING. If not, write to the 00022 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, 00023 * MA 02111-1307, USA. 00024 */ 00025 00026 #ifndef NL_BLOCK_MEMORY_H 00027 #define NL_BLOCK_MEMORY_H 00028 00029 #include "nel/misc/types_nl.h" 00030 #include <list> 00031 #include <vector> 00032 #include "nel/misc/debug.h" 00033 00034 00035 namespace NLMISC 00036 { 00037 00038 00039 // *************************************************************************** 00041 extern bool NL3D_BlockMemoryAssertOnPurge; // =true. 00042 00043 00044 // *************************************************************************** 00063 template<class T, bool __ctor_dtor__= true > 00064 class CBlockMemory 00065 { 00066 public: 00067 00069 CBlockMemory(uint blockSize= 16) 00070 { 00071 nlassert(blockSize); 00072 _BlockSize= blockSize; 00073 _EltSize= std::max(sizeof(T), sizeof(void*)); 00074 _NextFreeElt= NULL; 00075 _NAllocatedElts= 0; 00076 } 00077 // just copy setup from other blockMemory, don't copy data! 00078 CBlockMemory(const CBlockMemory<T, __ctor_dtor__> &other) 00079 { 00080 _BlockSize= other._BlockSize; 00081 // if other block is rebinded, don't copy its rebinded size. 00082 _EltSize= std::max(sizeof(T), sizeof(void*)); 00083 // No elts allocated 00084 _NextFreeElt= NULL; 00085 _NAllocatedElts= 0; 00086 } 00089 ~CBlockMemory() 00090 { 00091 purge(); 00092 } 00093 00094 00096 T* allocate() 00097 { 00098 // if not enough memory, aloc a block. 00099 if(!_NextFreeElt) 00100 { 00101 _Blocks.push_front(CBlock()); 00102 buildBlock(*_Blocks.begin()); 00103 // new free elt points to the beginning of this block. 00104 _NextFreeElt= (*_Blocks.begin()).Data; 00105 #ifdef NL_DEBUG 00106 // if debug, must decal for begin check. 00107 _NextFreeElt= (uint32*)_NextFreeElt + 1; 00108 #endif 00109 } 00110 00111 // choose next free elt. 00112 nlassert(_NextFreeElt); 00113 T* ret= (T*)_NextFreeElt; 00114 00115 // update _NextFreeElt, so it points to the next free element. 00116 _NextFreeElt= *(void**)_NextFreeElt; 00117 00118 // construct the allocated element. 00119 if( __ctor_dtor__ ) 00120 #undef new 00121 new (ret) T; 00122 #define new NL_NEW 00123 00124 00125 // some simple Check. 00126 #ifdef NL_DEBUG 00127 uint32 *checkStart= (uint32*)(void*)ret-1; 00128 uint32 *checkEnd = (uint32*)((uint8*)(void*)ret+_EltSize); 00129 nlassert( *checkStart == CheckDeletedIdent); 00130 nlassert( *checkEnd == CheckDeletedIdent); 00131 // if ok, mark this element as allocated. 00132 *checkStart= CheckAllocatedIdent; 00133 *checkEnd = CheckAllocatedIdent; 00134 #endif 00135 00136 _NAllocatedElts++; 00137 return ret; 00138 } 00139 00141 void free(T* ptr) 00142 { 00143 if(!ptr) 00144 return; 00145 // some simple Check. 00146 nlassert(_NAllocatedElts>0); 00147 #ifdef NL_DEBUG 00148 uint32 *checkStart= (uint32*)(void*)ptr-1; 00149 uint32 *checkEnd = (uint32*)((uint8*)(void*)ptr+_EltSize); 00150 nlassert( *checkStart == CheckAllocatedIdent); 00151 nlassert( *checkEnd == CheckAllocatedIdent); 00152 // if ok, mark this element as deleted. 00153 *checkStart= CheckDeletedIdent; 00154 *checkEnd = CheckDeletedIdent; 00155 #endif 00156 00157 // destruct the element. 00158 if( __ctor_dtor__ ) 00159 ptr->~T(); 00160 00161 // just append this freed element to the list. 00162 *(void**)ptr= _NextFreeElt; 00163 _NextFreeElt= (void*) ptr; 00164 00165 _NAllocatedElts--; 00166 } 00167 00168 00174 void purge () 00175 { 00176 if(NL3D_BlockMemoryAssertOnPurge) 00177 nlassert(_NAllocatedElts==0); 00178 00179 while(_Blocks.begin()!=_Blocks.end()) 00180 { 00181 releaseBlock(*_Blocks.begin()); 00182 _Blocks.erase(_Blocks.begin()); 00183 } 00184 00185 _NextFreeElt= NULL; 00186 _NAllocatedElts= 0; 00187 } 00188 00189 00190 // ******************** 00191 public: 00192 00193 // This is to be used with CSTLBlockAllocator only!!! It change the size of an element!! 00194 void __stl_alloc_changeEltSize(uint eltSize) 00195 { 00196 // must not be used with object ctor/dtor behavior. 00197 nlassert(__ctor_dtor__ == false); 00198 // format size. 00199 eltSize= std::max(eltSize, sizeof(void*)); 00200 // if not the same size as before 00201 if(_EltSize!= eltSize) 00202 { 00203 // verify that rebind is made before any allocation!! 00204 nlassert(_Blocks.empty()); 00205 // change the size. 00206 _EltSize= eltSize; 00207 } 00208 }; 00209 // This is to be used with CSTLBlockAllocator only!!! 00210 uint __stl_alloc_getEltSize() const 00211 { 00212 return _EltSize; 00213 } 00214 00215 00216 private: 00218 uint _BlockSize; 00220 uint _EltSize; 00222 sint _NAllocatedElts; 00224 void *_NextFreeElt; 00225 00226 00228 struct CBlock 00229 { 00231 void *Data; 00232 }; 00233 00235 std::list<CBlock> _Blocks; 00236 00237 00239 enum TCheckIdent { CheckAllocatedIdent= 0x01234567, CheckDeletedIdent= 0x89ABCDEF }; 00240 00241 00242 private: 00243 void buildBlock(CBlock &block) 00244 { 00245 uint i; 00246 uint32 nodeSize= _EltSize; 00247 #ifdef NL_DEBUG 00248 // must allocate more size for mem checks in debug. 00249 nodeSize+= 2*sizeof(uint32); 00250 #endif 00251 00252 // allocate. 00253 block.Data = (void*)new uint8 [_BlockSize * nodeSize]; 00254 00255 // by default, all elements are not allocated, build the list of free elements. 00256 void *ptr= block.Data; 00257 #ifdef NL_DEBUG 00258 // if debug, must decal for begin check. 00259 ptr= (uint32*)ptr + 1; 00260 #endif 00261 for(i=0; i<_BlockSize-1; i++) 00262 { 00263 // next elt. 00264 void *next= (uint8*)ptr + nodeSize; 00265 // points to the next element in this array. 00266 *(void**)ptr= next; 00267 // next. 00268 ptr= next; 00269 } 00270 // last element points to NULL. 00271 *(void**)ptr= NULL; 00272 00273 00274 // If debug, must init all check values to CheckDeletedIdent. 00275 #ifdef NL_DEBUG 00276 ptr= block.Data; 00277 // must decal for begin check. 00278 ptr= (uint32*)ptr + 1; 00279 // fill all nodes. 00280 for(i=0; i<_BlockSize; i++) 00281 { 00282 uint32 *checkStart= (uint32*)ptr-1; 00283 uint32 *checkEnd = (uint32*)((uint8*)ptr+_EltSize); 00284 // mark this element as deleted. 00285 *checkStart= CheckDeletedIdent; 00286 *checkEnd = CheckDeletedIdent; 00287 00288 // next elt. 00289 ptr= (uint8*)ptr + nodeSize; 00290 } 00291 #endif 00292 00293 } 00294 void releaseBlock(CBlock &block) 00295 { 00296 delete [] ((uint8*)block.Data); 00297 } 00298 00299 }; 00300 00301 00302 } // NLMISC 00303 00304 00305 #endif // NL_BLOCK_MEMORY_H 00306 00307 /* End of block_memory.h */ |