9 #include "Core/Macro/Macro.h" 22 using DataPointer = uint8_t*;
30 uintptr_t AlignAddress(uintptr_t address,
size_t align)
32 const size_t mask = align - 1;
33 MX_ASSERT((align & mask) == 0);
34 return (address + align - 1) & ~mask;
43 uintptr_t AlignAddressWithPadding(uintptr_t address,
size_t align)
45 const size_t mask = align - 1;
46 MX_ASSERT((align & mask) == 0);
47 return (address + align) & ~mask;
56 uint8_t* AlignPointerWithPadding(uint8_t* ptr,
size_t align)
58 return reinterpret_cast<uint8_t*
>(AlignAddressWithPadding((uintptr_t)ptr, align));
67 uint8_t* AlignPointer(uint8_t* ptr,
size_t align)
69 return reinterpret_cast<uint8_t*
>(AlignAddress((uintptr_t)ptr, align));
88 return (Header*)(next & ~1);
97 return (uint8_t*)GetNext() - (uint8_t*)
this -
sizeof(Header);
131 return (uint8_t*)
this +
sizeof(Header);
138 Header* first =
nullptr;
142 Header* last =
nullptr;
151 void Split(Header* header,
size_t bytes,
size_t align)
153 if (header->GetSize() < bytes + 2 *
sizeof(Header))
156 align = (align <
sizeof(uintptr_t)) ?
sizeof(uintptr_t) : align;
158 Header* next = (Header*)AlignPointer(header->GetData() + bytes, align);
159 next->next = (uintptr_t)header->GetNext();
161 header->next = (uintptr_t)next;
169 bool Collapse(Header* header)
171 Header* next = header->GetNext();
172 if (next != last && next->IsFree())
174 header->next = (uintptr_t)next->GetNext();
175 #if !defined(MXENGINE_DEBUG) // remove pointer entry in block to make allocator easier to debug 194 void Init(DataPointer data,
size_t bytes)
196 MX_ASSERT(bytes >
sizeof(Header));
197 first = (Header*)data;
198 last = (Header*)(data + bytes);
200 first->next = (uintptr_t)last;
211 this->
Init(data, bytes);
220 return (DataPointer)first;
229 [[nodiscard]] DataPointer
RawAlloc(
size_t bytes,
size_t align = 1)
231 MX_ASSERT(this->first !=
nullptr);
233 Header* current = first;
234 while (current != last)
236 if (current->IsFree())
238 while (this->Collapse(current));
239 uint8_t* data = current->GetData();
240 size_t available = current->GetSize();
241 if (available >= bytes)
243 this->Split(current, bytes, align);
248 current = current->GetNext();
259 MX_ASSERT(ptr > (uint8_t*)first && ptr < (uint8_t*)last);
260 Header* current = (Header*)(ptr -
sizeof(Header));
261 while (this->Collapse(current));
270 template<
typename T,
typename... Args>
271 [[nodiscard]] T*
Alloc(Args&&... args)
273 DataPointer ptr =
RawAlloc(
sizeof(T),
alignof(T));
274 return new (ptr) T(std::forward<Args>(args)...);
282 template<
typename T,
typename... Args>
285 auto deleter = [
this](T* ptr) { this->
Free(ptr); };
286 using SmartPtr = std::unique_ptr<T, decltype(deleter)>;
287 return SmartPtr(this->Alloc<T>(std::forward<Args>(args)...), std::move(deleter));
298 RawFree(reinterpret_cast<uint8_t*>(ptr));
305 void Dump(std::ostream& out)
const 307 uint8_t* base = (uint8_t*)first;
308 size_t size = (uint8_t*)last - base;
309 for (
size_t i = 0; i < size; i++)
311 if (i %
sizeof(uintptr_t) == 0) out <<
' ';
312 out << std::setfill(
'0') << std::setw(2);
313 out << std::hex << (int)base[i];
315 out << std::dec <<
"\n --- dumped " << size <<
" bytes --- \n";
DataPointer GetBase()
Definition: RandomAllocator.h:218
T * Alloc(Args &&... args)
Definition: RandomAllocator.h:271
void Free(T *ptr)
Definition: RandomAllocator.h:295
RandomAllocator()
Definition: RandomAllocator.h:187
void Init(DataPointer data, size_t bytes)
Definition: RandomAllocator.h:194
void Dump(std::ostream &out) const
Definition: RandomAllocator.h:305
void RawFree(uint8_t *ptr)
Definition: RandomAllocator.h:257
DataPointer RawAlloc(size_t bytes, size_t align=1)
Definition: RandomAllocator.h:229
RandomAllocator(DataPointer data, size_t bytes)
Definition: RandomAllocator.h:209
Definition: Application.cpp:49
auto StackAlloc(Args &&... args)
Definition: RandomAllocator.h:283
Definition: RandomAllocator.h:19