OpenBarnyard
 
Loading...
Searching...
No Matches
TSharedBuffer.h
Go to the documentation of this file.
1#pragma once
2#include "Toshi/Typedefs.h"
3#include "Toshi/TArray.h"
4
6
7//-----------------------------------------------------------------------------
8// Use this to create shared buffer of type T.
9// Call TSharedBuffer<>::Create() specifying number of buffers to create.
10// Note: Max possible number of elements is BUFSIZE * m_iNumBuffers.
11//-----------------------------------------------------------------------------
12template <typename T, TINT BUFSIZE, TINT IDENTIFIER>
14{
15public:
16 class TNode
17 {
18 public:
19 T& GetElement( TINT a_iIndex )
20 {
21 TASSERT( a_iIndex < BUFSIZE );
22 return m_aElements[ a_iIndex ];
23 }
24
25 const T& GetElement( TINT a_iIndex ) const
26 {
27 return GetElement( a_iIndex );
28 }
29
30 T& operator[]( TINT a_iIndex )
31 {
32 return GetElement( a_iIndex );
33 }
34
35 const T& operator[]( TINT a_iIndex ) const
36 {
37 return GetElement( a_iIndex );
38 }
39
40 private:
41 union
42 {
43 TUINT8 m_aMemoryBuffer[ sizeof( T ) * BUFSIZE ];
44 T m_aElements[ BUFSIZE ];
45 };
46 };
47
48public:
49 //-----------------------------------------------------------------------------
50 // Static definitions
51 //-----------------------------------------------------------------------------
52
53 static void CreateSharedBuffers( TINT a_iNumBuffers )
54 {
55 TASSERT( m_iNumBuffers == 0 );
56 TASSERT( m_pNodeArray == TNULL );
57
58 m_iNumBuffers = a_iNumBuffers;
59
60 if ( a_iNumBuffers > m_oFreeList.SizeAllocated() )
61 {
62 m_oFreeList.Resize( a_iNumBuffers );
63 }
64
65 m_oFreeList.SetSize( a_iNumBuffers );
66 m_pNodeArray = TSTATICCAST( TNode, TMalloc( sizeof( TNode ) * m_iNumBuffers ) );
67
68 for ( TINT i = 0; i < m_iNumBuffers; i++ )
69 {
70 m_oFreeList[ i ] = &m_pNodeArray[ i ];
71 }
72
73 TASSERT( m_oFreeList.Size() <= m_iNumBuffers );
74 TASSERT( ( 1 << TMath::IntLog2( BUFSIZE ) ) == BUFSIZE );
75
76 m_iMainIndexShift = TMath::IntLog2( BUFSIZE );
77 m_iSubIndexMask = ( 1 << TMath::IntLog2( BUFSIZE ) ) - 1;
78 }
79
81 {
82 TASSERT( m_oFreeList.Size() <= m_iNumBuffers );
84
85 m_oFreeList.Clear();
86
87 TVALIDPTR( m_pNodeArray );
88 TFree( m_pNodeArray );
89
90 m_iNumBuffers = 0;
91 m_pNodeArray = TNULL;
92 }
93
95 {
96 return m_iNumBuffers != m_oFreeList.Size();
97 }
98
99private:
100 inline static TNode* m_pNodeArray;
101 inline static TINT m_iNumBuffers;
102 inline static TINT m_iMainIndexShift;
103 inline static TINT m_iSubIndexMask;
104 inline static TArray<TNode*> m_oFreeList;
105
106public:
107 //-----------------------------------------------------------------------------
108 // Member definitions
109 //-----------------------------------------------------------------------------
110
112 : m_oArray( 4, 10 )
113 {
114 TASSERT( ( 1 << TMath::IntLog2( BUFSIZE ) ) == BUFSIZE );
115 }
116
118 {
119 SetSize( 0 );
120 }
121
123 {
124 return m_oArray.Size() << m_iMainIndexShift;
125 }
126
127 TBOOL SetSize( TINT a_iSize )
128 {
129 TASSERT( a_iSize >= 0 );
130 TASSERT( m_oFreeList.Size() <= m_iNumBuffers );
131 TASSERT( TMath::IntLog2( BUFSIZE ) == m_iMainIndexShift );
132
133 TINT iDesiredNumNodes = a_iSize >> ( m_iMainIndexShift % BUFSIZE );
134
135 if ( 0 < ( m_iSubIndexMask & a_iSize ) )
136 {
137 iDesiredNumNodes += 1;
138 }
139
140 TASSERT( iDesiredNumNodes >= 0 );
141
142 if ( m_oArray.Size() != iDesiredNumNodes )
143 {
144 if ( 10 < iDesiredNumNodes ) return TFALSE;
145
146 if ( iDesiredNumNodes < m_oArray.Size() )
147 {
148 // Removing elements from m_oArray
149
150 while ( iDesiredNumNodes < m_oArray.Size() )
151 {
152 // Remove the last element from array and store in the freelist
153 m_oFreeList.Push( m_oArray.Pop() );
154 }
155
156 TASSERT( m_oArray.Size() == iDesiredNumNodes );
157 TASSERT( m_oFreeList.Size() <= m_iNumBuffers );
158 }
159 else
160 {
161 // Adding new elements to m_oArray
162
163 if ( m_oFreeList.Size() < 1 ) return TFALSE;
164
165 while ( m_oArray.Size() < iDesiredNumNodes )
166 {
167 if ( m_oFreeList.Size() < 1 ) return TFALSE;
168
169 TASSERT( m_oArray.Size() < m_oArray.SizeAllocated() );
170
171 m_oArray.Push( m_oFreeList.Pop() );
172 }
173
174 TASSERT( m_oArray.Size() == iDesiredNumNodes );
175 TASSERT( m_oFreeList.Size() <= m_iNumBuffers );
176 }
177 }
178
179 return TTRUE;
180 }
181
182 T& At( TINT a_iIndex )
183 {
184 TASSERT( TMath::IntLog2( BUFSIZE ) == m_iMainIndexShift );
185 TASSERT( m_oFreeList.Size() <= m_iNumBuffers );
186 TASSERT( a_iIndex < m_oArray.Size() * BUFSIZE );
187
188 TINT iSubIndex = m_iSubIndexMask & a_iIndex;
189 TINT iMainIndex = a_iIndex >> ( m_iMainIndexShift % BUFSIZE );
190
191 TASSERT( iMainIndex < m_oArray.Size() );
192 TASSERT( iSubIndex < BUFSIZE );
193
194 return m_oArray[ iMainIndex ]->GetElement( iSubIndex );
195 }
196
197 const T& At( TINT a_iIndex ) const
198 {
199 TASSERT( TMath::IntLog2( BUFSIZE ) == m_iMainIndexShift );
200 TASSERT( m_oFreeList.Size() <= m_iNumBuffers );
201 TASSERT( a_iIndex < m_oArray.Size() * BUFSIZE );
202
203 TINT iSubIndex = m_iSubIndexMask & a_iIndex;
204 TINT iMainIndex = a_iIndex >> ( m_iMainIndexShift % BUFSIZE );
205
206 TASSERT( iMainIndex < m_oArray.Size() );
207 TASSERT( iSubIndex < BUFSIZE );
208
209 return m_oArray[ iMainIndex ]->GetElement( iSubIndex );
210 }
211
212 T& operator[]( TINT a_iIndex )
213 {
214 return At( a_iIndex );
215 }
216
217 const T& operator[]( TINT a_iIndex ) const
218 {
219 return At( a_iIndex );
220 }
221
222private:
223 TArray<TNode*> m_oArray;
224};
225
void * TMalloc(TSIZE a_uiSize, Toshi::TMemory::MemBlock *a_pMemBlock, const TCHAR *a_szFileName, TINT a_iLineNum)
Allocates memory from a specific memory block.
Definition TMemory.cpp:973
void TFree(void *a_pMem)
Frees previously allocated memory.
Definition TMemory.cpp:1054
#define TASSERT(X,...)
Definition Defines.h:138
#define TSTATICCAST(POINTERTYPE, VALUE)
Definition Defines.h:69
#define TOSHI_NAMESPACE_START
Definition Defines.h:47
#define TOSHI_NAMESPACE_END
Definition Defines.h:50
#define TVALIDPTR(PTR)
Definition Defines.h:139
unsigned int TUINT
Definition Typedefs.h:8
uint8_t TUINT8
Definition Typedefs.h:17
#define TNULL
Definition Typedefs.h:23
int TINT
Definition Typedefs.h:7
#define TFALSE
Definition Typedefs.h:24
#define TTRUE
Definition Typedefs.h:25
bool TBOOL
Definition Typedefs.h:6
TFORCEINLINE constexpr TUINT IntLog2(TUINT32 a_uiValue)
Definition TMathInline.h:66
T & operator[](TINT a_iIndex)
TBOOL SetSize(TINT a_iSize)
static TBOOL IsAnyBuffersUsed()
static void CreateSharedBuffers(TINT a_iNumBuffers)
TUINT GetSize() const
static void DestroySharedBuffers()
const T & At(TINT a_iIndex) const
const T & operator[](TINT a_iIndex) const
T & At(TINT a_iIndex)
const T & operator[](TINT a_iIndex) const
const T & GetElement(TINT a_iIndex) const
T & operator[](TINT a_iIndex)
T & GetElement(TINT a_iIndex)
TUINT8 m_aMemoryBuffer[sizeof(T) *BUFSIZE]