1#pragma once
2
3#include <new>
4
5#include "basis/seadRawPrint.h"
6#include "basis/seadTypes.h"
7
8namespace sead
9{
10class FreeList
11{
12public:
13 void setWork(void* work, s32 elem_size, s32 num);
14 void reset();
15
16 void* alloc();
17 void free(void* ptr);
18
19 void* getFree() const { return mFree; }
20 void* work() const { return mWork; }
21
22 static const size_t cPtrSize = sizeof(void*);
23
24private:
25 struct Node
26 {
27 Node* nextFree;
28 };
29
30 Node* mFree = nullptr;
31 void* mWork = nullptr;
32};
33
34inline void FreeList::setWork(void* work, s32 elem_size, s32 num)
35{
36 SEAD_ASSERT(work);
37 SEAD_ASSERT(elem_size > 0 && elem_size % cPtrSize == 0);
38 SEAD_ASSERT(num > 0);
39
40 const s32 idx_multiplier = elem_size / cPtrSize;
41 void** const ptrs = new (work) void*[num * idx_multiplier];
42
43 mFree = new (work) Node;
44
45 // Create the linked list.
46 for (s32 i = 0; i < num - 1; ++i)
47 new (&ptrs[i * idx_multiplier]) Node{.nextFree: new (&ptrs[(i + 1) * idx_multiplier]) Node};
48
49 new (&ptrs[(num - 1) * idx_multiplier]) Node{.nextFree: nullptr};
50
51 mWork = work;
52}
53
54inline void FreeList::reset()
55{
56 mFree = nullptr;
57 mWork = nullptr;
58}
59
60inline void* FreeList::alloc()
61{
62 if (!mFree)
63 return nullptr;
64
65 void* ptr = mFree;
66 mFree = mFree->nextFree;
67 return ptr;
68}
69
70inline void FreeList::free(void* ptr)
71{
72 mFree = new (ptr) Node{.nextFree: mFree};
73}
74} // namespace sead
75