Plasma Engine  2.0
Loading...
Searching...
No Matches
BlockStorage_inl.h
1
2template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
4 const plBlockStorage<T, BlockSize, StorageType>& storage, plUInt32 uiStartIndex, plUInt32 uiCount)
5 : m_Storage(storage)
6{
7 m_uiCurrentIndex = uiStartIndex;
8 m_uiEndIndex = plMath::Max(uiStartIndex + uiCount, uiCount);
9
10 if (StorageType == plBlockStorageType::FreeList)
11 {
12 plUInt32 uiEndIndex = plMath::Min(m_uiEndIndex, m_Storage.m_uiCount);
13 while (m_uiCurrentIndex < uiEndIndex && !m_Storage.m_UsedEntries.IsBitSet(m_uiCurrentIndex))
14 {
15 ++m_uiCurrentIndex;
16 }
17 }
18}
19
20template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
22{
23 const plUInt32 uiBlockIndex = m_uiCurrentIndex / plDataBlock<T, BlockSize>::CAPACITY;
24 const plUInt32 uiInnerIndex = m_uiCurrentIndex - uiBlockIndex * plDataBlock<T, BlockSize>::CAPACITY;
25 return m_Storage.m_Blocks[uiBlockIndex][uiInnerIndex];
26}
27
28template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
30{
31 return CurrentElement();
32}
33
34template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
36{
37 return &CurrentElement();
38}
39
40template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
42{
43 return &CurrentElement();
44}
45
46template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
48{
49 ++m_uiCurrentIndex;
50
51 if (StorageType == plBlockStorageType::FreeList)
52 {
53 plUInt32 uiEndIndex = plMath::Min(m_uiEndIndex, m_Storage.m_uiCount);
54 while (m_uiCurrentIndex < uiEndIndex && !m_Storage.m_UsedEntries.IsBitSet(m_uiCurrentIndex))
55 {
56 ++m_uiCurrentIndex;
57 }
58 }
59}
60
61template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
63{
64 return m_uiCurrentIndex < plMath::Min(m_uiEndIndex, m_Storage.m_uiCount);
65}
66
67template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
69{
70 Next();
71}
72
74
75template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
77 const plBlockStorage<T, BlockSize, StorageType>& storage, plUInt32 uiStartIndex, plUInt32 uiCount)
78 : ConstIterator(storage, uiStartIndex, uiCount)
79{
80}
81
82template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
84{
85 return this->CurrentElement();
86}
87
88template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
90{
91 return &(this->CurrentElement());
92}
93
94template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
96{
97 return &(this->CurrentElement());
98}
99
101
102template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
104 plLargeBlockAllocator<BlockSize>* pBlockAllocator, plAllocator* pAllocator)
105 : m_pBlockAllocator(pBlockAllocator)
106 , m_Blocks(pAllocator)
107
108{
109}
110
111template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
113{
114 Clear();
115}
116
117template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
119{
120 for (plUInt32 uiBlockIndex = 0; uiBlockIndex < m_Blocks.GetCount(); ++uiBlockIndex)
121 {
122 plDataBlock<T, BlockSize>& block = m_Blocks[uiBlockIndex];
123
124 if (StorageType == plBlockStorageType::Compact)
125 {
126 plMemoryUtils::Destruct(block.m_pData, block.m_uiCount);
127 }
128 else
129 {
130 for (plUInt32 uiInnerIndex = 0; uiInnerIndex < block.m_uiCount; ++uiInnerIndex)
131 {
132 plUInt32 uiIndex = uiBlockIndex * plDataBlock<T, BlockSize>::CAPACITY + uiInnerIndex;
133 if (m_UsedEntries.IsBitSet(uiIndex))
134 {
135 plMemoryUtils::Destruct(&block.m_pData[uiInnerIndex], 1);
136 }
137 }
138 }
139
140 m_pBlockAllocator->DeallocateBlock(block);
141 }
142
143 m_Blocks.Clear();
144}
145
146template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
148{
149 T* pNewObject = nullptr;
150 plUInt32 uiNewIndex = plInvalidIndex;
151
152 if (StorageType == plBlockStorageType::FreeList && m_uiFreelistStart != plInvalidIndex)
153 {
154 uiNewIndex = m_uiFreelistStart;
155
156 const plUInt32 uiBlockIndex = uiNewIndex / plDataBlock<T, BlockSize>::CAPACITY;
157 const plUInt32 uiInnerIndex = uiNewIndex - uiBlockIndex * plDataBlock<T, BlockSize>::CAPACITY;
158
159 pNewObject = &(m_Blocks[uiBlockIndex][uiInnerIndex]);
160
161 m_uiFreelistStart = *reinterpret_cast<plUInt32*>(pNewObject);
162 }
163 else
164 {
165 plDataBlock<T, BlockSize>* pBlock = nullptr;
166
167 if (m_Blocks.GetCount() > 0)
168 {
169 pBlock = &m_Blocks.PeekBack();
170 }
171
172 if (pBlock == nullptr || pBlock->IsFull())
173 {
174 m_Blocks.PushBack(m_pBlockAllocator->template AllocateBlock<T>());
175 pBlock = &m_Blocks.PeekBack();
176 }
177
178 pNewObject = pBlock->ReserveBack();
179 uiNewIndex = m_uiCount;
180
181 ++m_uiCount;
182 }
183
185
186 if (StorageType == plBlockStorageType::FreeList)
187 {
188 m_UsedEntries.SetCount(m_uiCount);
189 m_UsedEntries.SetBit(uiNewIndex);
190 }
191
192 return pNewObject;
193}
194
195template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
196PL_FORCE_INLINE void plBlockStorage<T, BlockSize, StorageType>::Delete(T* pObject)
197{
198 T* pDummy;
199 Delete(pObject, pDummy);
200}
201
202template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
203void plBlockStorage<T, BlockSize, StorageType>::Delete(T* pObject, T*& out_pMovedObject)
204{
205 Delete(pObject, out_pMovedObject, plTraitInt<StorageType>());
206}
207
208template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
209PL_ALWAYS_INLINE plUInt32 plBlockStorage<T, BlockSize, StorageType>::GetCount() const
210{
211 return m_uiCount;
212}
213
214template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
216 plUInt32 uiStartIndex /*= 0*/, plUInt32 uiCount /*= plInvalidIndex*/)
217{
218 return Iterator(*this, uiStartIndex, uiCount);
219}
220
221template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
223 plUInt32 uiStartIndex /*= 0*/, plUInt32 uiCount /*= plInvalidIndex*/) const
224{
225 return ConstIterator(*this, uiStartIndex, uiCount);
226}
227
228template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
229PL_FORCE_INLINE void plBlockStorage<T, BlockSize, StorageType>::Delete(T* pObject, T*& out_pMovedObject, plTraitInt<plBlockStorageType::Compact>)
230{
231 plDataBlock<T, BlockSize>& lastBlock = m_Blocks.PeekBack();
232 T* pLast = lastBlock.PopBack();
233
234 --m_uiCount;
235 if (pObject != pLast)
236 {
237 plMemoryUtils::Relocate(pObject, pLast, 1);
238 }
239 else
240 {
241 plMemoryUtils::Destruct(pLast, 1);
242 }
243
244 out_pMovedObject = pLast;
245
246 if (lastBlock.IsEmpty())
247 {
248 m_pBlockAllocator->DeallocateBlock(lastBlock);
249 m_Blocks.PopBack();
250 }
251}
252
253template <typename T, plUInt32 BlockSize, plBlockStorageType::Enum StorageType>
254PL_FORCE_INLINE void plBlockStorage<T, BlockSize, StorageType>::Delete(T* pObject, T*& out_pMovedObject, plTraitInt<plBlockStorageType::FreeList>)
255{
256 plUInt32 uiIndex = plInvalidIndex;
257 for (plUInt32 uiBlockIndex = 0; uiBlockIndex < m_Blocks.GetCount(); ++uiBlockIndex)
258 {
259 std::ptrdiff_t diff = pObject - m_Blocks[uiBlockIndex].m_pData;
260 if (diff >= 0 && diff < plDataBlock<T, BlockSize>::CAPACITY)
261 {
262 uiIndex = uiBlockIndex * plDataBlock<T, BlockSize>::CAPACITY + (plInt32)diff;
263 break;
264 }
265 }
266
267 PL_ASSERT_DEV(uiIndex != plInvalidIndex, "Invalid object {0} was not found in block storage.", plArgP(pObject));
268
269 m_UsedEntries.ClearBit(uiIndex);
270
271 out_pMovedObject = pObject;
272 plMemoryUtils::Destruct(pObject, 1);
273
274 *reinterpret_cast<plUInt32*>(pObject) = m_uiFreelistStart;
275 m_uiFreelistStart = uiIndex;
276}
Base class for all memory allocators.
Definition Allocator.h:23
Definition BlockStorage.h:20
Definition BlockStorage.h:45
Definition BlockStorage.h:17
A block allocator which can only allocates blocks of memory at once.
Definition LargeBlockAllocator.h:40
static void Construct(T *pDestination, size_t uiCount=1)
Constructs uiCount objects of type T in a raw buffer at pDestination.
static void Relocate(T *pDestination, T *pSource, size_t uiCount=1)
Moves objects of type T from pSource to pDestination.
static void Destruct(T *pDestination, size_t uiCount=1)
Destructs uiCount objects of type T at pDestination.
constexpr PL_ALWAYS_INLINE T Min(T f1, T f2)
Returns the smaller value, f1 or f2.
Definition Math_inl.h:27
constexpr PL_ALWAYS_INLINE T Max(T f1, T f2)
Returns the greater value, f1 or f2.
Definition Math_inl.h:39
Definition FormatStringArgs.h:76
This struct represents a block of type T, typically 4kb.
Definition LargeBlockAllocator.h:14
Type traits.
Definition TypeTraits.h:12