"L. Spiro Engine"

F:/My Projects/LSEngine/Modules/LSMemLib/Src/Allocators/LSAStdAllocator.h

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__
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator