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
|
#include "../../include/std/scoped_allocator.h"
#include "../../include/std/alloc.h"
#include <assert.h>
#define ALLOC_NODE_SIZE 4096
int scoped_allocator_node_init(ScopedAllocatorNode *self) {
self->data = NULL;
self->size = 0;
self->next = NULL;
return am_malloc(ALLOC_NODE_SIZE, (void**)&self->data);
}
void scoped_allocator_node_deinit(ScopedAllocatorNode *self) {
am_free(self->data);
self->data = NULL;
self->size = 0;
if(self->next) {
scoped_allocator_node_deinit(self->next);
am_free(self->next);
self->next = NULL;
}
}
int scoped_allocator_init(ScopedAllocator *self) {
return_if_error(scoped_allocator_node_init(&self->head));
self->current = &self->head;
return buffer_init(&self->buffers, NULL);
}
static void buffer_deinit(Buffer *self) {
am_free(self->data);
self->data = NULL;
self->size = 0;
self->capacity = 0;
}
void scoped_allocator_deinit(ScopedAllocator *self) {
Buffer *buffer;
Buffer *buffer_end;
scoped_allocator_node_deinit(&self->head);
self->current = NULL;
buffer = (Buffer*)self->buffers.data;
buffer_end = buffer + self->buffers.size / sizeof(Buffer);
while(buffer != buffer_end) {
buffer_deinit(buffer);
++buffer;
}
buffer_deinit(&self->buffers);
}
static CHECK_RESULT int scoped_allocator_ensure_capacity_for(ScopedAllocator *self, usize size) {
void *new_node;
new_node = NULL;
if(self->current->size + size > ALLOC_NODE_SIZE) {
return_if_error(am_malloc(sizeof(ScopedAllocatorNode), &new_node));
cleanup_if_error(scoped_allocator_node_init(new_node));
self->current->next = new_node;
self->current = new_node;
}
return ALLOC_OK;
cleanup:
if(new_node)
am_free(new_node);
return ALLOC_FAIL;
}
static void* align_ptr_ceil(void *ptr, uintptr_t alignment) {
uintptr_t ptrval;
ptrval = (uintptr_t)ptr;
return (void*)((ptrval + alignment + 1) & ~(alignment - 1));
}
static usize align_ptr_ceil_offset(void *ptr, uintptr_t alignment) {
return (uintptr_t)align_ptr_ceil(ptr, alignment) - (uintptr_t)ptr;
}
int scoped_allocator_alloc(ScopedAllocator *self, usize size, void **mem) {
ScopedAllocatorNode *current;
usize alloc_size;
assert(self->current);
assert(size <= ALLOC_NODE_SIZE);
current = self->current;
alloc_size = size + align_ptr_ceil_offset(self->current->data + self->current->size, 16);
return_if_error(scoped_allocator_ensure_capacity_for(self, alloc_size));
/* Reallocated (new node created) */
if(self->current != current) {
*mem = self->current->data;
self->current->size += size;
} else {
*mem = align_ptr_ceil(self->current->data + self->current->size, 16);
self->current->size += alloc_size;
}
return 0;
}
int scoped_allocator_add_buffer(ScopedAllocator *self, Buffer *buffer) {
return buffer_append(&self->buffers, buffer, sizeof(Buffer));
}
|