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