"L. Spiro Engine"
|
00001 00020 #ifndef __LSA_STDALLOCATOR_H__ 00021 #define __LSA_STDALLOCATOR_H__ 00022 00023 #include "../OSHeap/LSAOsHeap.h" 00024 #ifndef LSA_DEBUG 00025 #include "LSASmallAllocator.h" 00026 #endif // #ifndef LSA_DEBUG 00027 #include "LSAStdAllocatorHeap.h" 00028 #include <new> 00029 00030 #pragma warning( push ) 00031 00032 // warning C4127: conditional expression is constant 00033 #pragma warning( disable : 4127 ) 00034 00035 00036 namespace lsa { 00037 00044 class CStdAllocator { 00045 protected : 00046 friend class CMemLib; 00047 // == Various constructors. 00048 LSE_CALL CStdAllocator(); 00049 LSE_CALL ~CStdAllocator(); 00050 00051 00052 public : 00053 // == Functions. 00061 LSVOID * LSE_CALL Alloc( LSA_SIZE _sSize, LSUINT32 _ui32Align = 16UL LSA_DEBUGPARMSDECL ); 00062 00070 LSVOID * LSE_CALL CAlloc( LSA_SIZE _sSize, LSUINT32 _ui32Align = 16UL LSA_DEBUGPARMSDECL ); 00071 00078 LSE_INLINE LSBOOL LSE_CALL Free( LSVOID * _pvAddr ); 00079 00087 LSVOID * LSE_CALL ReAlloc( LSVOID * _pvAddr, LSA_SIZE _sSize LSA_DEBUGPARMSDECL ); 00088 00094 LSBOOL LSE_CALL Clear(); 00095 00101 LSE_INLINE LSVOID LSE_CALL Trash(); 00102 00107 LSVOID LSE_CALL ReleaseEmptyHeaps(); 00108 00118 LSA_SIZE LSE_CALL PrintAllocations( LSUINT32 _ui32Count = 0UL, LSUINT32 _ui32End = 0xFFFFFFFFUL ) const; 00119 00127 LSA_SIZE LSE_CALL GetTotalAllocatedSize(); 00128 00129 #ifdef LSA_DEBUG 00130 00134 LSVOID LSE_CALL VerifyBlocks() const; 00135 #endif // #ifdef LSA_DEBUG 00136 00137 protected : 00145 LSBOOL LSE_CALL SetSize( LSA_SIZE _sSize, LSBOOL _bGrowable ); 00146 00153 LSBOOL LSE_CALL AddBlock( LSA_SIZE _sSize ); 00154 00155 #ifndef LSA_DEBUG 00156 00160 LSBOOL LSE_CALL AddSmallAllocator(); 00161 #endif // #ifndef LSA_DEBUG 00162 00169 LSE_INLINE static LSVOID * LSE_CALL GetStartAddress( const CStdAllocatorHeap * _psahBlock ); 00170 00177 LSE_INLINE static LSA_SIZE LSE_CALL GetMinSizeOfBlock( const CStdAllocatorHeap * _psahBlock ); 00178 00186 LSE_INLINE LSVOID * LSE_CALL AllocInternal( LSA_SIZE _sSize, LSUINT32 _ui32Align LSA_DEBUGPARMSDECL ); 00187 00188 #ifndef LSA_DEBUG 00189 00196 LSE_INLINE LSVOID * LSE_CALL AllocInternalSmall( LSA_SIZE _sSize, LSUINT32 _ui32Align ); 00197 #endif // #ifndef LSA_DEBUG 00198 00209 LSVOID * LSE_CALL ReAllocInternal( CStdAllocatorHeap::LPLSA_ALLOCATIONHEADER &_lpahBlock, LSVOID * _pvAddr, LSA_SIZE _sSize LSA_DEBUGPARMSDECL ); 00210 00211 // == Members. 00212 // Thread safety. 00213 mutable CCriticalSection m_csCrit; 00214 00215 // Linked list of blocks. 00216 CStdAllocatorHeap * m_psahHead; 00217 00218 #ifndef LSA_DEBUG 00219 // Linked list of small blocks. 00220 CSmallAllocator * m_psaSmallHead; 00221 #endif // #ifndef LSA_DEBUG 00222 00223 // Total size of the heap. 00224 LSA_SIZE m_sSize; 00225 // Can the heap grow? 00226 LSBOOL m_bGrowable; 00227 00228 // Range of addresses covered by this object. 00229 LSA_SIZE m_sLow, 00230 m_sHi; 00231 }; 00232 00233 00234 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00235 // DEFINITIONS 00236 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00237 // == Functions. 00244 LSE_INLINE LSBOOL LSE_CALL CStdAllocator::Free( LSVOID * _pvAddr ) { 00245 if ( !_pvAddr ) { return true; } 00246 CCriticalSection::CLocker lLock( m_csCrit ); 00247 // Quick range check. 00248 LSA_SIZE sThis = reinterpret_cast<LSA_SIZE>(_pvAddr); 00249 if ( sThis < m_sLow || sThis >= m_sHi ) { return false; } 00250 #ifndef LSA_DEBUG 00251 // Check small heaps. 00252 for ( CSmallAllocator * psaThis = m_psaSmallHead; psaThis; psaThis = psaThis->m_psaNext ) { 00253 if ( psaThis->HaveAddress( _pvAddr ) ) { 00254 return psaThis->Free( _pvAddr ); 00255 } 00256 } 00257 #endif // #ifndef LSA_DEBUG 00258 00259 for ( CStdAllocatorHeap * psahThis = m_psahHead; psahThis; psahThis = psahThis->m_psahNext ) { 00260 if ( psahThis->Free( _pvAddr ) ) { return true; } 00261 } 00262 return false; 00263 } 00264 00270 LSE_INLINE LSVOID LSE_CALL CStdAllocator::Trash() { 00271 CCriticalSection::CLocker lLock( m_csCrit ); 00272 for ( CStdAllocatorHeap * psahThis = m_psahHead; psahThis; psahThis = psahThis->m_psahNext ) { 00273 psahThis->Trash(); 00274 } 00275 #ifndef LSA_DEBUG 00276 for ( CSmallAllocator * psaThis = m_psaSmallHead; psaThis; psaThis = psaThis->m_psaNext ) { 00277 psaThis->Trash(); 00278 } 00279 #endif // #ifndef LSA_DEBUG 00280 } 00281 00288 LSE_INLINE LSVOID * LSE_CALL CStdAllocator::GetStartAddress( const CStdAllocatorHeap * _psahBlock ) { 00289 LSA_SIZE sStart = reinterpret_cast<LSA_SIZE>(_psahBlock); 00290 sStart += sizeof( CStdAllocatorHeap ); 00291 sStart = CStdAllocatorHeap::RoundUp( sStart ); 00292 return reinterpret_cast<LSVOID *>(sStart); 00293 } 00294 00301 LSE_INLINE LSA_SIZE LSE_CALL CStdAllocator::GetMinSizeOfBlock( const CStdAllocatorHeap * _psahBlock ) { 00302 LSA_SIZE sStart = reinterpret_cast<LSA_SIZE>(_psahBlock); 00303 LSA_SIZE sEnd = reinterpret_cast<LSA_SIZE>(GetStartAddress( _psahBlock )); 00304 // Must have enough space for an allocation-block header and 4 allocation units. 00305 sEnd += LSA_MIN_ALIGN * 4 + sizeof( CStdAllocatorHeap::LSA_ALLOCATIONHEADER ); 00306 return CStdAllocatorHeap::RoundUp( sEnd ) - sStart; 00307 } 00308 00316 LSE_INLINE LSVOID * LSE_CALL CStdAllocator::AllocInternal( LSA_SIZE _sSize, LSUINT32 _ui32Align LSA_DEBUGPARMSDEF ) { 00317 // Find a block that manages to allocate it. 00318 for ( CStdAllocatorHeap * psahThis = m_psahHead; psahThis; psahThis = psahThis->m_psahNext ) { 00319 LSVOID * pvRet = psahThis->Alloc( _sSize, _ui32Align LSA_DEBUGPARMSPASS ); 00320 if ( pvRet ) { return pvRet; } 00321 } 00322 // No blocks could allocate it. Fail. 00323 return NULL; 00324 } 00325 00326 #ifndef LSA_DEBUG 00327 00334 LSE_INLINE LSVOID * LSE_CALL CStdAllocator::AllocInternalSmall( LSA_SIZE _sSize, LSUINT32 _ui32Align ) { 00335 // Find a block that manages to allocate it. 00336 for ( CSmallAllocator * psaThis = m_psaSmallHead; psaThis; psaThis = psaThis->m_psaNext ) { 00337 LSVOID * pvRet = psaThis->Alloc( _sSize, _ui32Align ); 00338 if ( pvRet ) { return pvRet; } 00339 } 00340 // No blocks could allocate it. Fail. 00341 return NULL; 00342 } 00343 #endif // #ifndef LSA_DEBUG 00344 00345 } // namespace lsa 00346 00347 #pragma warning( pop ) 00348 00349 #endif // __LSA_STDALLOCATOR_H__