A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
Heap.hh
1#pragma once
2
3#include "egg/core/Disposer.hh"
4
5#include <abstract/memory/HeapCommon.hh>
6
7#include <list>
8#include <new>
9
10namespace Kinoko {
11
12namespace Host {
13
14class Context;
15
16} // namespace Host
17
18namespace EGG {
19
20class ExpHeap;
21class FrmHeap;
22
25class Heap : Disposer {
26 friend class Host::Context;
27
28public:
29 enum class Kind {
30 None,
31 Expanded,
32 Frame,
33 Unit,
34 Assert,
35 };
36
38 ~Heap() override;
39
40 virtual void destroy() = 0;
41 virtual Kind getHeapKind() const = 0;
42 virtual void *alloc(size_t size, s32 align) = 0;
43 virtual void free(void *block) = 0;
44 virtual u32 getAllocatableSize(s32 align = 4) const = 0;
45
46 void dispose();
47
48 void disableAllocation() {
49 m_flags.setBit(eFlags::Lock);
50 }
51
52 void enableAllocation() {
53 m_flags.resetBit(eFlags::Lock);
54 }
55
56 [[nodiscard]] bool tstDisableAllocation() const {
57 return m_flags.onBit(eFlags::Lock);
58 }
59
60 void appendDisposer(Disposer *disposer) {
61 m_children.append(disposer);
62 }
63
64 void removeDisposer(Disposer *disposer) {
65 m_children.remove(disposer);
66 }
67
68 Heap *becomeAllocatableHeap();
69 Heap *becomeCurrentHeap();
70
71 void registerHeapBuffer(void *buffer) {
72 m_block = buffer;
73 }
74
75 [[nodiscard]] void *getStartAddress() {
76 return this;
77 }
78
79 [[nodiscard]] void *getEndAddress() {
80 return m_handle->getHeapEnd();
81 }
82
83 [[nodiscard]] const char *getName() const {
84 return m_name;
85 }
86
88 [[nodiscard]] Heap *getParentHeap() const {
89 return m_parentHeap;
90 }
91
92 void setName(const char *name) {
93 m_name = name;
94 }
95
96 void setParentHeap(Heap *heap) {
97 m_parentHeap = heap;
98 }
99
100 static void initialize();
101 [[nodiscard]] static void *alloc(size_t size, int align, Heap *pHeap);
102 static void free(void *block, Heap *pHeap);
103
104 [[nodiscard]] static Heap *findHeap(Abstract::Memory::MEMiHeapHead *handle);
105 [[nodiscard]] static Heap *findContainHeap(const void *block);
106
107 [[nodiscard]] static ExpHeap *dynamicCastToExp(Heap *heap) {
108 return heap->getHeapKind() == Kind::Expanded ? reinterpret_cast<ExpHeap *>(heap) : nullptr;
109 }
110
111 [[nodiscard]] static FrmHeap *dynamicCastToFrm(Heap *heap) {
112 return heap->getHeapKind() == Kind::Frame ? reinterpret_cast<FrmHeap *>(heap) : nullptr;
113 }
114
115 [[nodiscard]] static Heap *getCurrentHeap() {
116 return s_currentHeap;
117 }
118
119 [[nodiscard]] static constexpr uintptr_t getOffset() {
120 // offsetof doesn't work, so instead of hardcoding an offset, we derive it ourselves
121 return reinterpret_cast<uintptr_t>(&reinterpret_cast<Heap *>(NULL)->m_link);
122 }
123
124protected:
125 enum class eFlags {
126 Lock = 0,
127 };
128 typedef TBitFlag<u16, eFlags> Flags;
129
131 void *m_block;
132 Heap *m_parentHeap;
133 Flags m_flags;
135 Abstract::Memory::MEMList m_children;
136 const char *m_name;
137
138 static Abstract::Memory::MEMList s_heapList;
139
140 static Heap *s_currentHeap;
141 static Heap *s_allocatableHeap;
142};
143
144[[nodiscard]] void *egg_alloc(size_t size, s32 align = 4, Heap *pHeap = nullptr);
145void egg_free(void *block, Heap *pHeap = nullptr);
146
147template <typename T, typename... Args>
148[[nodiscard]] T *egg_new(Args &&...args) {
149 return ::new (egg_alloc(sizeof(T), static_cast<s32>(alignof(T))))
150 T(std::forward<Args>(args)...);
151}
152
153template <typename T>
154void egg_delete(const T *ptr) {
155 if (ptr) {
156 ptr->~T();
157 egg_free(const_cast<T *>(ptr));
158 }
159}
160
161template <typename T>
162[[nodiscard]] T *egg_new_array(size_t count) {
163 T *p = static_cast<T *>(egg_alloc(sizeof(T) * count, static_cast<s32>(alignof(T))));
164 for (size_t i = 0; i < count; ++i) {
165 ::new (p + i) T();
166 }
167 return p;
168}
169
170template <typename T>
171void egg_delete_array(T *ptr, size_t count) {
172 if (ptr) {
173 for (size_t i = count; i-- > 0;) {
174 ptr[i].~T();
175 }
176 egg_free(ptr);
177 }
178}
179
180} // namespace EGG
181
182} // namespace Kinoko
183
186#define EGG_NEW_DELETE_FRIEND \
187 template <typename T, typename... Args> \
188 friend T *Kinoko::EGG::egg_new(Args &&...args); \
189 template <typename T> \
190 friend void Kinoko::EGG::egg_delete(const T *ptr);
A low-level representation of a memory heap for managing dynamic memory allocation....
Definition HeapCommon.hh:21
High-level implementation of a memory heap for managing dynamic memory allocation....
Definition ExpHeap.hh:15
A high-level representation of a memory heap for managing dynamic memory allocation....
Definition Heap.hh:25
Contexts can be used to restore a previous memory state for the current session.
Definition Context.hh:71
EGG core library.
Definition Allocator.hh:5
Represents the host application.
Definition HeapCommon.hh:11
Intrusive doubly-linked list. Links are placed within the corresponding object.
Definition List.hh:14
Wrapper around an integral type with an enum corresponding to its bits.
Definition BitFlag.hh:23