Plasma Engine  2.0
Loading...
Searching...
No Matches
AllocPolicyLinear.h
1#pragma once
2
3#include <Foundation/Containers/HybridArray.h>
4
10template <bool OverwriteMemoryOnReset = false>
12{
13public:
14 enum
15 {
16 Alignment = 16
17 };
18
19 PL_FORCE_INLINE plAllocPolicyLinear(plAllocator* pParent)
20 : m_pParent(pParent)
21 , m_uiNextBucketSize(4096)
22 {
23 }
24
25 PL_FORCE_INLINE ~plAllocPolicyLinear()
26 {
27 PL_ASSERT_DEV(m_uiCurrentBucketIndex == 0 && (m_Buckets.IsEmpty() || m_Buckets[m_uiCurrentBucketIndex].GetPtr() == m_pNextAllocation),
28 "There is still something allocated!");
29 for (auto& bucket : m_Buckets)
30 {
31 m_pParent->Deallocate(bucket.GetPtr());
32 }
33 }
34
35 PL_FORCE_INLINE void* Allocate(size_t uiSize, size_t uiAlign)
36 {
37 PL_ASSERT_DEV(uiAlign <= Alignment && Alignment % uiAlign == 0, "Unsupported alignment {0}", ((plUInt32)uiAlign));
38 uiSize = plMemoryUtils::AlignSize(uiSize, (size_t)Alignment);
39
40 bool bFoundBucket = !m_Buckets.IsEmpty() && m_pNextAllocation + uiSize <= m_Buckets[m_uiCurrentBucketIndex].GetEndPtr();
41
42 if (!bFoundBucket)
43 {
44 // Check if there is an empty bucket that fits the allocation
45 for (plUInt32 i = m_uiCurrentBucketIndex + 1; i < m_Buckets.GetCount(); ++i)
46 {
47 auto& testBucket = m_Buckets[i];
48 if (uiSize <= testBucket.GetCount())
49 {
50 m_uiCurrentBucketIndex = i;
51 m_pNextAllocation = testBucket.GetPtr();
52 bFoundBucket = true;
53 break;
54 }
55 }
56 }
57
58 if (!bFoundBucket)
59 {
60 while (uiSize > m_uiNextBucketSize)
61 {
62 PL_ASSERT_DEBUG(m_uiNextBucketSize > 0, "");
63
64 m_uiNextBucketSize *= 2;
65 }
66
67 m_uiCurrentBucketIndex = m_Buckets.GetCount();
68
69 auto newBucket = plArrayPtr<plUInt8>(static_cast<plUInt8*>(m_pParent->Allocate(m_uiNextBucketSize, Alignment)), m_uiNextBucketSize);
70 m_Buckets.PushBack(newBucket);
71
72 m_pNextAllocation = newBucket.GetPtr();
73
74 m_uiNextBucketSize *= 2;
75 }
76
77 PL_ASSERT_DEBUG(m_pNextAllocation + uiSize <= m_Buckets[m_uiCurrentBucketIndex].GetEndPtr(), "");
78
79 plUInt8* ptr = m_pNextAllocation;
80 m_pNextAllocation += uiSize;
81 return ptr;
82 }
83
84 PL_FORCE_INLINE void Deallocate(void* pPtr)
85 {
86 // Individual deallocation is not supported by this allocator
87 }
88
89 PL_FORCE_INLINE void Reset()
90 {
91 m_uiCurrentBucketIndex = 0;
92 m_pNextAllocation = !m_Buckets.IsEmpty() ? m_Buckets[0].GetPtr() : nullptr;
93
94 if constexpr (OverwriteMemoryOnReset)
95 {
96 for (auto& bucket : m_Buckets)
97 {
98 plMemoryUtils::PatternFill(bucket.GetPtr(), 0xCD, bucket.GetCount());
99 }
100 }
101 }
102
103 PL_FORCE_INLINE void FillStats(plAllocator::Stats& ref_stats)
104 {
105 ref_stats.m_uiNumAllocations = m_Buckets.GetCount();
106 for (auto& bucket : m_Buckets)
107 {
108 ref_stats.m_uiAllocationSize += bucket.GetCount();
109 }
110 }
111
112 PL_ALWAYS_INLINE plAllocator* GetParent() const { return m_pParent; }
113
114private:
115 plAllocator* m_pParent = nullptr;
116
117 plUInt32 m_uiCurrentBucketIndex = 0;
118 plUInt32 m_uiNextBucketSize = 0;
119
120 plUInt8* m_pNextAllocation = nullptr;
121
123};
This policy implements a linear allocator that can only grow and at some point all allocations gets r...
Definition AllocPolicyLinear.h:12
Base class for all memory allocators.
Definition Allocator.h:23
virtual void * Allocate(size_t uiSize, size_t uiAlign, plMemoryUtils::DestructorFunction destructorFunc=nullptr)=0
Interface, do not use this directly, always use the new/delete macros below.
void PushBack(const T &value)
Pushes value at the end of the array.
Definition ArrayBase_inl.h:333
bool IsEmpty() const
Returns true, if the array does not contain any elements.
Definition ArrayBase_inl.h:178
plUInt32 GetCount() const
Returns the number of active elements in the array.
Definition ArrayBase_inl.h:172
This class encapsulates an array and it's size. It is recommended to use this class instead of plain ...
Definition ArrayPtr.h:37
A hybrid array uses in-place storage to handle the first few elements without any allocation....
Definition HybridArray.h:12
static void PatternFill(T *pDestination, plUInt8 uiBytePattern, size_t uiCount=1)
Fills every byte of the provided buffer with the given value.
static T AlignSize(T uiSize, T uiAlignment)
Aligns the given size uiSize by rounding up to the next multiple of the size.
Definition Allocator.h:26
plUInt64 m_uiNumAllocations
total number of allocations
Definition Allocator.h:29
plUInt64 m_uiAllocationSize
total allocation size in bytes
Definition Allocator.h:31