Skip to content

Commit 288a097

Browse files
committed
Documented all TLSF allocator classes
1 parent a719be5 commit 288a097

File tree

2 files changed

+263
-17
lines changed

2 files changed

+263
-17
lines changed

engine/utils/allocators/Tlsf.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,6 @@ template<typename T>
240240
typename TlsfAllocator<T>::FreeBlockNode* TlsfAllocator<T>::FindFreeBlock(const T& size)
241241
{
242242
T fl, sl, index;
243-
// 1000 0000 0000 1000
244243
index = CalculateFreeBlockIndices(size, fl, sl);
245244

246245
if (!IsFree(fl, sl)) index = GetNextFreeSlotIndex(fl, sl);

engine/utils/allocators/Tlsf.h

Lines changed: 263 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
#include "../Macros.h"
1616

17+
/**
18+
* A shorthand macro for making deallocations easier to manage.
19+
*/
1720
#define FREE(ptr) Deallocate((void**) &ptr)
1821

1922
namespace Siege
@@ -23,32 +26,55 @@ class TlsfAllocator
2326
{
2427
public:
2528

29+
/**
30+
* @brief Flags for determining the state of a memory block. Every header has a flag where the
31+
* first three bits are dedicated to keeping track of the block's state
32+
*/
2633
enum HeaderFlags
2734
{
2835
FULL = 0,
2936
FREE = 1,
3037
PREV_IS_FREE = 2
3138
};
3239

40+
/**
41+
* @brief linked list nodes for representing free memory blocks
42+
*/
3343
struct FreeBlockNode
3444
{
3545
FreeBlockNode* next {nullptr};
3646
FreeBlockNode* prev {nullptr};
3747
};
3848

49+
/**
50+
* @brief A struct representing the header for each memory block in the allocator. This struct
51+
* stores the size of the entire block alongside the state of the block
52+
*/
3953
struct BlockHeader
4054
{
4155
T sizeAndFlags {0};
4256
};
4357

58+
/**
59+
* @brief a struct which stores the size of the the entire memory block. Used to navigate the
60+
* allocator and find the block's header
61+
*/
4462
struct BlockFooter
4563
{
4664
T totalBlockSize {0};
4765
};
4866

4967
// S'tructors
5068

69+
/**
70+
* @brief Empty constructor Initialises the constructor and size to 0 (null)
71+
*/
5172
TlsfAllocator();
73+
/**
74+
* @brief Size initialiser. Accepts a number representing the number of bytes to allocate to
75+
* the allocator's memory buffer
76+
* @param size the number of bytes to allocate, cannot be less than 16
77+
*/
5278
TlsfAllocator(const T size);
5379

5480
// Deleted copy and move constructors
@@ -58,69 +84,279 @@ class TlsfAllocator
5884

5985
// Other functions
6086

61-
void CreateHeader(uint8_t* ptr, const T size, HeaderFlags flags);
62-
void CreateFooter(uint8_t* ptr, const T size);
63-
FreeBlockNode* CreateFreeBlock(uint8_t* ptr, FreeBlockNode* prev, FreeBlockNode* next);
64-
FreeBlockNode* FindFreeBlock(const T& size);
87+
/**
88+
* @brief Checks if a block's preceding neighbour is free (the block that comes before it)
89+
* @param header the current header
90+
* @return true if the previous block is free, otherwise false
91+
*/
92+
bool PrevBlockIsFree(BlockHeader* header);
6593

66-
const T GetNextFreeSlotIndex(T& fl, T& sl);
94+
/**
95+
* @brief Checks if a block is free for allocation
96+
* @param header the header to check for free space
97+
* @return true if the free flag is set, otherwise false
98+
*/
6799
bool IsFree(BlockHeader* header);
100+
101+
/**
102+
* @brief Checks if an entry exists in the FreeList for a specific combination of first and
103+
* second level indices
104+
* @param fl the index to search the first level bitmask with
105+
* @param sl the index to search the second level bitmask with
106+
* @return true if a free block exists, false otherwise
107+
*/
68108
bool IsFree(T fl, T sl);
109+
110+
/**
111+
* @brief Checks if the allocator is full
112+
* @return true if there are no bytes left in the allocator, otherwise false
113+
*/
69114
bool IsFull();
70-
bool PrevBlockIsFree(BlockHeader* header);
71-
T CalculateFreeBlockIndices(T size, OUT T& fl, OUT T& sl);
72115

73116
// Buffer manipulation Functions
74117

118+
/**
119+
* @brief Retrieves a free block from a header if possible
120+
* @param header the header from which to get a FreeBlock
121+
* @return a FreeBlock if applicable, otherwise a nullptr
122+
*/
75123
FreeBlockNode* GetFreeBlock(BlockHeader* header);
124+
125+
/**
126+
* @brief Retrieves a free block using first and second level indices
127+
* @param fl the first level index to be calculated
128+
* @param sl the second level index to be calculated
129+
* @return the FreeBlock at the specified first and second level indices
130+
*/
76131
FreeBlockNode* GetFreeBlock(const T fl, const T sl);
132+
133+
/**
134+
* @brief Retrieves the raw allocated data stored within the memory block
135+
* @param header the header to extrapolate the data from
136+
* @return a pointer to the data stored by the memory block
137+
*/
77138
uint8_t* GetBlockData(BlockHeader* header);
139+
140+
/**
141+
* @brief Gets the footer for a memory block
142+
* @param header the header of the memory block
143+
* @return the footer associated with the memory block or nullptr if out of bounds
144+
*/
78145
BlockFooter* GetFooter(BlockHeader* header);
146+
147+
/**
148+
* @brief Returns the footer of the previous memory block
149+
* @param header the current header
150+
* @return the previous footer or nullptr if it doesnt exist
151+
*/
79152
BlockFooter* GetPrevFooter(BlockHeader* header);
153+
154+
/**
155+
* @brief Returns the header associated with a FreeBlock
156+
* @param node the FreeBlock to search
157+
* @return the BlockHeader associated with the free block
158+
*/
80159
BlockHeader* GetHeader(FreeBlockNode* node);
160+
161+
/**
162+
* @brief Returns the header of a data pointer. Assumes that the data is pointing to the start
163+
* of the data pointer
164+
* @param ptr the raw data pointer
165+
* @return a BlockHeader if one exists
166+
*/
81167
BlockHeader* GetHeader(uint8_t* ptr);
168+
169+
/**
170+
* @brief Returns the header of the previous data block if within the allocator's range
171+
* @param header the current header
172+
* @return the header of the previous block or nullptr if none exist
173+
*/
82174
BlockHeader* GetPrevHeader(BlockHeader* header);
175+
176+
/**
177+
* @brief Returns the header of the next memory block if within the allocator's range
178+
* @param header the current header
179+
* @return the header of the next memory block or nullptr if out of bounds
180+
*/
83181
BlockHeader* GetNextHeader(BlockHeader* header);
84182

85183
// Allocate/Deallocate
86184

185+
/**
186+
* @brief Allocates a memory block and returns a pointer to the allocator's buffer
187+
* @param size the size in bytes to allocate. The minimum allocatable chunk of memory is 16
188+
* bytes
189+
* @return a pointer to the memory block
190+
*/
87191
void* Allocate(const T& size);
88-
void Deallocate(void** ptr);
89192

90-
BlockHeader* TrySplitBlock(FreeBlockNode* node, T& allocatedSize);
91-
bool RemoveFreeBlock(FreeBlockNode* node);
92-
void AddNewBlock(const T size, BlockHeader* currentNode);
93-
BlockHeader* TryCoalesce(BlockHeader* header, OUT T& size);
193+
/**
194+
* @brief Deallocates a memory block and returns the memory to the allocator's pool
195+
* @param ptr the pointer to deallocate
196+
*/
197+
void Deallocate(void** ptr);
94198

95199
// Getters
96200

97-
bool IsValid(uint8_t* ptr);
201+
/**
202+
* @brief Returns the size of a memory block from its header
203+
* @param header the header of the memory block
204+
* @return the fully padded size of the memory block
205+
*/
98206
const T GetHeaderSize(BlockHeader* header);
207+
208+
/**
209+
* Returns the maximum capacity of the allocator
210+
* @return the allocator's capacity in bytes
211+
*/
99212
const T Capacity();
213+
214+
/**
215+
* Returns the number of unpadded bytes remaining
216+
* @return the number of bytes remaining in the allocator
217+
*/
100218
const T BytesRemaining();
219+
220+
/**
221+
* Returns the total bytes remaining with padding
222+
* @return the total bytes remaining with padding
223+
*/
101224
const T TotalBytesRemaining()
102225
{
103226
return totalBytesRemaining;
104227
}
228+
229+
/**
230+
* Returns the total size of allocated memory by the allocator with padding
231+
* @return the total size of allocated memory by the allocator with padding
232+
*/
105233
const T TotalSize()
106234
{
107235
return totalSize;
108236
}
237+
238+
/**
239+
* Returns the data buffer held by the allocator
240+
* @return the data buffer held by the allocator
241+
*/
109242
const uint8_t* Data()
110243
{
111244
return data;
112245
}
246+
247+
/**
248+
* Returns the bitmask representing the first level of size classes
249+
* @return the bitmask representing the first level of size classes
250+
*/
113251
const T FlBitmask()
114252
{
115253
return flBitmask;
116254
}
255+
256+
/**
257+
* Returns the second level bitmask stored by the allocator
258+
* @param fl the first level index to search over
259+
* @return the value of the second level bitmask
260+
*/
117261
const uint16_t& SlBitmask(const T fl)
118262
{
119263
return slBitmasks[fl];
120264
}
121265

122266
private:
123267

268+
/**
269+
* @brief Calculates the FreeList, first level, and second level indices for a given size
270+
* @param size the size class to search for in the allocator
271+
* @param fl the first level index to be calculated
272+
* @param sl the second level index to be calculated
273+
* @return the FreeList index
274+
*/
275+
T CalculateFreeBlockIndices(T size, OUT T& fl, OUT T& sl);
276+
277+
/**
278+
* @brief Creates and initialises a header at a specified memory location
279+
* @param ptr the memory location, represented as a pointer to a set of bytes
280+
* @param size the size to allocate to the memory block. Size must have metadata sizes factored
281+
* into its calculation
282+
* @param flags The state flags for header (see HeaderFlags)
283+
*/
284+
void CreateHeader(uint8_t* ptr, const T size, HeaderFlags flags);
285+
286+
/**
287+
* @brief Creates a footer at a specified memory location. Footers store the size of the entire
288+
* memory block (including metadata padding)
289+
* @param ptr the memory location to allocate the footer to (represented as a byte pointer)
290+
* @param size the size to assign the footer (should be the full block size)
291+
*/
292+
void CreateFooter(uint8_t* ptr, const T size);
293+
294+
/**
295+
* @brief Creates a FreeBlockNode at a specified memory location and positions it within the
296+
* FreeList
297+
* @param ptr the memory location to initialise the block to
298+
* @param prev the FreeBlock that precedes this block
299+
* @param next the FreeBlock that follows this block
300+
* @return a pointer to the new FreeBlock
301+
*/
302+
FreeBlockNode* CreateFreeBlock(uint8_t* ptr, FreeBlockNode* prev, FreeBlockNode* next);
303+
304+
/**
305+
* @brief Finds a free block for a specified size. If none exist, will attempt to find the next
306+
* available block
307+
* @param size the minimum size of the free block
308+
* @return a pointer to a FreeBlockNode if one exists, otherwise nullptr
309+
*/
310+
FreeBlockNode* FindFreeBlock(const T& size);
311+
312+
/**
313+
* @brief Returns the next available free block (if any exist)
314+
* @param fl the index to search the first level bitmask with
315+
* @param sl the index to search the second level bitmask with
316+
* @return the index to the FreeList where the block exists
317+
*/
318+
const T GetNextFreeSlotIndex(T& fl, T& sl);
319+
320+
/**
321+
* Attempts to split a block in two, prioritising splitting the block into the requested size
322+
* first and allocating the remainder to a second block. If an attempted split results in too
323+
* few bytes remaining, the block will allocate the full free block
324+
* @param node the node to try and split
325+
* @param allocatedSize the size to allocate to the first split block
326+
* @return a BlockHeader representing the split block
327+
*/
328+
BlockHeader* TrySplitBlock(FreeBlockNode* node, T& allocatedSize);
329+
330+
/**
331+
* Removes a free block from the FreeList, unlinking it from its class linked list
332+
* @param node the node to remove
333+
* @return true if successfully removed, otherwise false
334+
*/
335+
bool RemoveFreeBlock(FreeBlockNode* node);
336+
337+
/**
338+
* Adds a new free block to the allocator
339+
* @param size the size in bytes of the new FreeBlock
340+
* @param currentNode the header of the FreeNode you wish to add
341+
*/
342+
void AddNewBlock(const T size, BlockHeader* currentNode);
343+
344+
/**
345+
* Attempts to combine a FreeBlock with its neighbours and updates the size of the header if
346+
* memory blocks were successfully combined
347+
* @param header the header to attempt to coalesce
348+
* @param size the size in bytes of the combined new memory block
349+
* @return the BlockHeader of the combined memory block (if combined)
350+
*/
351+
BlockHeader* TryCoalesce(BlockHeader* header, OUT T& size);
352+
353+
/**
354+
* Tests if a pointer is valid within the allocator
355+
* @param ptr the pointer to test
356+
* @return true if the pointer is valid, otherwise false
357+
*/
358+
bool IsValid(uint8_t* ptr);
359+
124360
static uint8_t MIN_SIZE_INDEX;
125361

126362
T totalSize {0};
@@ -137,11 +373,22 @@ class TlsfAllocator
137373
uint16_t* slBitmasks {nullptr};
138374
};
139375

140-
// Maximum buffer possible here is around 8KB.
376+
/**
377+
* @brief A TLSF allocator capable of storing up to 8KB of memory. Each allocation has a overhead of
378+
* 4 bytes and can only allocate a minimum of 16 bytes
379+
*/
141380
typedef TlsfAllocator<uint16_t> SmallTlsfAllocator;
142-
// Maximum buffer possible here is around 512MB.
381+
382+
/**
383+
* A TLSF allocator capable of storing up to 512MB of memory. Each allocation has a overhead of
384+
* 8 bytes and can only allocate a minimum of 16 bytes
385+
*/
143386
typedef TlsfAllocator<uint32_t> MediumTlsfAllocator;
144-
// Maximum buffer possible here is around 2,147,483.6GB.
387+
388+
/**
389+
* A TLSF allocator capable of storing up to 8GB of memory. Each allocation has a overhead of
390+
* 16 bytes and can only allocate a minimum of 16 bytes
391+
*/
145392
typedef TlsfAllocator<uint64_t> LargeTlsfAllocator;
146393
} // namespace Siege
147394

0 commit comments

Comments
 (0)