summaryrefslogtreecommitdiff
path: root/code/amr_memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'code/amr_memory.c')
-rw-r--r--code/amr_memory.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/code/amr_memory.c b/code/amr_memory.c
new file mode 100644
index 0000000..f92f14a
--- /dev/null
+++ b/code/amr_memory.c
@@ -0,0 +1,113 @@
+#include "amr_memory.h"
+
+bool amr_IsPowerOfTwo(uintptr_t x)
+{
+ return (x & (x-1)) == 0;
+}
+
+uintptr_t amr_AlignForward(uintptr_t ptr, size_t align)
+{
+ uintptr_t p, a, modulo;
+
+ assert(amr_IsPowerOfTwo(align));
+
+ p = ptr;
+ a = (uintptr_t)align;
+ modulo = p & (a-1);
+
+ if (modulo != 0)
+ {
+ p += a - modulo;
+ }
+ return p;
+}
+
+void *amr_ArenaAllocAlign(amr_DebugArena *Alloc, size_t Size, size_t Align)
+{
+ uintptr_t CurrOffset = (uintptr_t)Alloc->Buffer + (uintptr_t)Alloc->CurrOffset;
+ uintptr_t AlignedOffset = amr_AlignForward(CurrOffset, Align);
+ AlignedOffset -= (uintptr_t)(Alloc->Buffer);
+
+ if (AlignedOffset + Size < Alloc->Size)
+ {
+ void *Ptr = &Alloc->Buffer[AlignedOffset];
+ Alloc->PrevOffset = AlignedOffset;
+ Alloc->CurrOffset = AlignedOffset + Size;
+
+ PlatformZeroMemory(Ptr, Size);
+ return Ptr;
+ }
+ return NULL;
+}
+
+void amr_ArenaInit(amr_DebugArena *Alloc, void* BackingBuffer, size_t Size)
+{
+ Alloc->Buffer = (u8 *)BackingBuffer;
+ Alloc->Size = Size;
+ Alloc->CurrOffset = 0;
+ Alloc->PrevOffset = 0;
+}
+
+void *amr_ArenaAlloc(amr_DebugArena *Alloc, size_t Size)
+{
+ return amr_ArenaAllocAlign(Alloc, Size, DEFAULT_ALIGNMENT);
+}
+
+void amr_ArenaFree(amr_DebugArena *Alloc, void *Ptr)
+{
+ // @note: Arenas do not support freeing memory
+ // this is here to let me know I have not forgotten to implement it
+ return;
+}
+
+void *amr_ArenaResizeAlign(amr_DebugArena *Alloc, void *OldMem, size_t OldSize,
+ size_t NewSize, size_t Align)
+{
+ assert(amr_IsPowerOfTwo(Align));
+ if (OldMem == NULL || OldSize == 0)
+ {
+ return amr_ArenaAllocAlign(Alloc, NewSize, Align);
+ }
+ else if (Alloc->Buffer < OldMem && OldMem < Alloc->Buffer + Alloc->Size)
+ {
+ // check if old_memory falls on prev_offset
+ if (Alloc->Buffer + Alloc->PrevOffset == OldMem)
+ {
+ // re-use prev_offset and resize from there
+ size_t _CurrOffset = Alloc->CurrOffset;
+ Alloc->CurrOffset = Alloc->PrevOffset + NewSize;
+ if (NewSize > OldSize)
+ {
+ PlatformZeroMemory(&Alloc->Buffer[_CurrOffset], NewSize - OldSize);
+ }
+ return OldMem;
+ }
+ else
+ {
+ // generate new memory
+ // will have some fragmentation
+ void *NewMem = amr_ArenaAllocAlign(Alloc, NewSize, Align);
+ size_t CopySize = OldSize < NewSize ? OldSize : NewSize;
+
+ // copy old memory to new memory location
+ PlatformCopyMemory(NewMem, OldMem, CopySize);
+ return NewMem;
+ }
+ }
+ else
+ {
+ assert(0 && "Memory is out of bounds of the buffer in this arena");
+ return NULL;
+ }
+}
+
+void *amr_ArenaResize(amr_DebugArena *Alloc, void *OldMem, size_t OldSize, size_t NewSize)
+{
+ return amr_ArenaResizeAlign(Alloc, OldMem, OldSize, NewSize, DEFAULT_ALIGNMENT);
+}
+
+void amr_ArenaFreeAll(amr_DebugArena *Alloc)
+{
+ Alloc->CurrOffset = 0;
+ Alloc->PrevOffset = 0;
+}