-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstack_allocator.c
More file actions
112 lines (100 loc) · 4.18 KB
/
Copy pathstack_allocator.c
File metadata and controls
112 lines (100 loc) · 4.18 KB
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
#include <stdint.h> // uintptr_t
#include <string.h> // memcpy - only needed for realloc
struct allocator {
void *buffer;
int capacity;
int cursor;
};
void *allocate(struct allocator *allocator, int size, int alignment) {
uintptr_t mask = (uintptr_t)alignment - 1; // Alignment must be a power of 2.
uintptr_t unaligned = (uintptr_t)allocator->buffer + allocator->cursor;
uintptr_t aligned = (unaligned + mask) & ~mask;
int new_cursor = allocator->cursor + size + (int)(aligned - unaligned);
if (new_cursor > allocator->capacity)
return 0;
allocator->cursor = new_cursor;
return (void *)aligned;
}
void deallocate(struct allocator *allocator, void *block, int size) {
if ((char *)block + size == (char *)allocator->buffer + allocator->cursor)
allocator->cursor -= size;
}
void *reallocate(struct allocator *allocator, void *block, int old_size, int new_size, int alignment) {
uintptr_t mask = (uintptr_t)alignment - 1;
if ((char *)block + old_size == (char *)allocator->buffer + allocator->cursor && ((uintptr_t)block & mask) == 0) {
int new_cursor = allocator->cursor + new_size - old_size;
if (new_cursor > allocator->capacity)
return 0;
allocator->cursor = new_cursor;
return block;
}
void *result = allocate(allocator, new_size, alignment);
if (result) {
int to_copy = new_size < old_size ? new_size : old_size;
memcpy(result, block, (size_t)to_copy);
}
return result;
}
#include <assert.h>
int main(void) {
struct allocator allocator = { 0 };
assert(!allocate(&allocator, 1, 1));
assert(!allocate(&allocator, 1, 1));
deallocate(&allocator, 0, 0);
assert(!reallocate(&allocator, 0, 0, 1, 1));
_Alignas(16) char buffer[16];
allocator = (struct allocator){ .buffer = buffer, .capacity = sizeof buffer };
char *c = allocate(&allocator, sizeof(char), _Alignof(char));
short *s = allocate(&allocator, sizeof(short), _Alignof(short));
int *i = allocate(&allocator, sizeof(int), _Alignof(int));
long long *l = allocate(&allocator, sizeof(long long), _Alignof(long long));
long long *null = allocate(&allocator, sizeof(long long), _Alignof(long long));
assert(c && (uintptr_t)c % _Alignof(char) == 0);
assert(s && (uintptr_t)s % _Alignof(short) == 0);
assert(i && (uintptr_t)i % _Alignof(int) == 0);
assert(l && (uintptr_t)l % _Alignof(long long) == 0);
assert(!null);
deallocate(&allocator, l, sizeof(long long));
l = allocate(&allocator, sizeof(long long), _Alignof(long long));
assert(l);
deallocate(&allocator, l, sizeof(long long));
deallocate(&allocator, i, sizeof(int));
int *ints = allocate(&allocator, 3 * sizeof(int), _Alignof(int));
assert(ints);
ints[0] = ints[1] = ints[2] = 42;
long long big_buffer[1024];
allocator = (struct allocator){ .buffer = big_buffer, .capacity = sizeof big_buffer };
assert(!allocate(&allocator, 1024 * sizeof(long long) + 1, 1));
l = allocate(&allocator, 1024 * sizeof(long long), _Alignof(long long));
assert(l);
deallocate(&allocator, l, 1024 * sizeof(long long));
l = allocate(&allocator, 1024 * sizeof(long long), _Alignof(long long));
assert(l);
i = reallocate(&allocator, l, 1024 * sizeof(long long), 0, 1);
assert(allocator.cursor == 0);
i = reallocate(&allocator, i, 0, sizeof(int), _Alignof(int));
*i = 42;
assert(allocator.cursor == sizeof(int));
i = reallocate(&allocator, i, sizeof(int), 10 * sizeof(int), _Alignof(int));
assert(allocator.cursor == 10 * sizeof(int));
i = reallocate(&allocator, i, 10 * sizeof(int), 2048 * sizeof(int), _Alignof(int));
assert(allocator.cursor == 2048 * sizeof(int));
i = reallocate(&allocator, i, 2048 * sizeof(int), 11 * sizeof(int), _Alignof(int));
assert(allocator.cursor == 11 * sizeof(int));
for (int j = 0; j < 11; ++j)
i[j] = j;
l = reallocate(&allocator, NULL, 0, 1, _Alignof(long long));
int *i1 = reallocate(&allocator, i, 11 * sizeof(int), 12 * sizeof(int), _Alignof(int));
assert(i1 != i);
for (int j = 0; j < 11; ++j)
assert(i1[j] == j);
allocate(&allocator, 2, _Alignof(char));
int *i2 = reallocate(&allocator, i1, 12 * sizeof(int), 3 * sizeof(int), _Alignof(int));
assert(i2 != i1);
for (int j = 0; j < 3; ++j)
assert(i2[j] == j);
int *i3 = reallocate(&allocator, i2, 3 * sizeof(int), 3 * sizeof(int), 64);
assert(i3 != i2);
for (int j = 0; j < 3; ++j)
assert(i2[j] == j);
}