1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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;
}
|