Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
5.7 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: A fast stack memory allocator that uses virtual memory if available
  4. //
  5. //=============================================================================//
  6. #ifndef MEMSTACK_H
  7. #define MEMSTACK_H
  8. #if defined( _WIN32 )
  9. #pragma once
  10. #endif
  11. //-----------------------------------------------------------------------------
  12. typedef unsigned MemoryStackMark_t;
  13. class CMemoryStack
  14. {
  15. public:
  16. CMemoryStack();
  17. ~CMemoryStack();
  18. bool Init( unsigned maxSize = 0, unsigned commitSize = 0, unsigned initialCommit = 0, unsigned alignment = 16 );
  19. #ifdef _X360
  20. bool InitPhysical( unsigned size = 0, unsigned alignment = 16 );
  21. #endif
  22. void Term();
  23. int GetSize();
  24. int GetMaxSize();
  25. int GetUsed();
  26. void *Alloc( unsigned bytes, bool bClear = false ) RESTRICT;
  27. MemoryStackMark_t GetCurrentAllocPoint();
  28. void FreeToAllocPoint( MemoryStackMark_t mark, bool bDecommit = true );
  29. void FreeAll( bool bDecommit = true );
  30. void Access( void **ppRegion, unsigned *pBytes );
  31. void PrintContents();
  32. void *GetBase();
  33. const void *GetBase() const { return const_cast<CMemoryStack *>(this)->GetBase(); }
  34. private:
  35. bool CommitTo( byte * ) RESTRICT;
  36. byte *m_pNextAlloc;
  37. byte *m_pCommitLimit;
  38. byte *m_pAllocLimit;
  39. byte *m_pBase;
  40. unsigned m_maxSize;
  41. unsigned m_alignment;
  42. #ifdef _WIN32
  43. unsigned m_commitSize;
  44. unsigned m_minCommit;
  45. #endif
  46. #ifdef _X360
  47. bool m_bPhysical;
  48. #endif
  49. };
  50. //-------------------------------------
  51. FORCEINLINE void *CMemoryStack::Alloc( unsigned bytes, bool bClear ) RESTRICT
  52. {
  53. Assert( m_pBase );
  54. int alignment = m_alignment;
  55. if ( bytes )
  56. {
  57. bytes = AlignValue( bytes, alignment );
  58. }
  59. else
  60. {
  61. bytes = alignment;
  62. }
  63. void *pResult = m_pNextAlloc;
  64. byte *pNextAlloc = m_pNextAlloc + bytes;
  65. if ( pNextAlloc > m_pCommitLimit )
  66. {
  67. if ( !CommitTo( pNextAlloc ) )
  68. {
  69. return NULL;
  70. }
  71. }
  72. if ( bClear )
  73. {
  74. memset( pResult, 0, bytes );
  75. }
  76. m_pNextAlloc = pNextAlloc;
  77. return pResult;
  78. }
  79. //-------------------------------------
  80. inline int CMemoryStack::GetMaxSize()
  81. {
  82. return m_maxSize;
  83. }
  84. //-------------------------------------
  85. inline int CMemoryStack::GetUsed()
  86. {
  87. return ( m_pNextAlloc - m_pBase );
  88. }
  89. //-------------------------------------
  90. inline void *CMemoryStack::GetBase()
  91. {
  92. return m_pBase;
  93. }
  94. //-------------------------------------
  95. inline MemoryStackMark_t CMemoryStack::GetCurrentAllocPoint()
  96. {
  97. return ( m_pNextAlloc - m_pBase );
  98. }
  99. //-----------------------------------------------------------------------------
  100. // The CUtlMemoryStack class:
  101. // A fixed memory class
  102. //-----------------------------------------------------------------------------
  103. template< typename T, typename I, size_t MAX_SIZE, size_t COMMIT_SIZE = 0, size_t INITIAL_COMMIT = 0 >
  104. class CUtlMemoryStack
  105. {
  106. public:
  107. // constructor, destructor
  108. CUtlMemoryStack( int nGrowSize = 0, int nInitSize = 0 ) { m_MemoryStack.Init( MAX_SIZE * sizeof(T), COMMIT_SIZE * sizeof(T), INITIAL_COMMIT * sizeof(T), 4 ); COMPILE_TIME_ASSERT( sizeof(T) % 4 == 0 ); }
  109. CUtlMemoryStack( T* pMemory, int numElements ) { Assert( 0 ); }
  110. // Can we use this index?
  111. bool IsIdxValid( I i ) const { return (i >= 0) && (i < m_nAllocated); }
  112. // Specify the invalid ('null') index that we'll only return on failure
  113. static const I INVALID_INDEX = ( I )-1; // For use with COMPILE_TIME_ASSERT
  114. static I InvalidIndex() { return INVALID_INDEX; }
  115. class Iterator_t
  116. {
  117. Iterator_t( I i ) : index( i ) {}
  118. I index;
  119. friend class CUtlMemoryStack<T,I,MAX_SIZE, COMMIT_SIZE, INITIAL_COMMIT>;
  120. public:
  121. bool operator==( const Iterator_t it ) const { return index == it.index; }
  122. bool operator!=( const Iterator_t it ) const { return index != it.index; }
  123. };
  124. Iterator_t First() const { return Iterator_t( m_nAllocated ? 0 : InvalidIndex() ); }
  125. Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( it.index < m_nAllocated ? it.index + 1 : InvalidIndex() ); }
  126. I GetIndex( const Iterator_t &it ) const { return it.index; }
  127. bool IsIdxAfter( I i, const Iterator_t &it ) const { return i > it.index; }
  128. bool IsValidIterator( const Iterator_t &it ) const { return it.index >= 0 && it.index < m_nAllocated; }
  129. Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); }
  130. // Gets the base address
  131. T* Base() { return (T*)m_MemoryStack.GetBase(); }
  132. const T* Base() const { return (const T*)m_MemoryStack.GetBase(); }
  133. // element access
  134. T& operator[]( I i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
  135. const T& operator[]( I i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
  136. T& Element( I i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
  137. const T& Element( I i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
  138. // Attaches the buffer to external memory....
  139. void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); }
  140. // Size
  141. int NumAllocated() const { return m_nAllocated; }
  142. int Count() const { return m_nAllocated; }
  143. // Grows the memory, so that at least allocated + num elements are allocated
  144. void Grow( int num = 1 ) { Assert( num > 0 ); m_nAllocated += num; m_MemoryStack.Alloc( num * sizeof(T) ); }
  145. // Makes sure we've got at least this much memory
  146. void EnsureCapacity( int num ) { Assert( num <= MAX_SIZE ); if ( m_nAllocated < num ) Grow( num - m_nAllocated ); }
  147. // Memory deallocation
  148. void Purge() { m_MemoryStack.FreeAll(); m_nAllocated = 0; }
  149. // is the memory externally allocated?
  150. bool IsExternallyAllocated() const { return false; }
  151. // Set the size by which the memory grows
  152. void SetGrowSize( int size ) {}
  153. private:
  154. CMemoryStack m_MemoryStack;
  155. int m_nAllocated;
  156. };
  157. //-----------------------------------------------------------------------------
  158. #endif // MEMSTACK_H