-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhgl_arena_alloc.h
184 lines (157 loc) · 5.09 KB
/
hgl_arena_alloc.h
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/**
* LICENSE:
*
* MIT License
*
* Copyright (c) 2023 Henrik A. Glass
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* MIT License
*
*
* ABOUT:
*
* hgl_arena_alloc.h implements a simple to use arena (a.k.a. linear) allocator.
*
*
* USAGE:
*
* Include hgl_arena_alloc.h file like this:
*
* #define HGL_ARENA_ALLOC_IMPLEMENTATION
* #include "hgl_arena_alloc.h"
*
* This will create the implementation of hgl_arena_alloc in the current compilation unit. To
* include hgl_arena_alloc.h without creating the implementation, simply ommit the #define
* of HGL_ARENA_ALLOC_IMPLEMENTATION.
*
* Below is a complet listing of the API:
*
* HglArena hgl_arena_make(size_t arena_size)
* void *hgl_arena_alloc(HglArena *arena, size_t alloc_size)
* void hgl_arena_free_all(HglArena *arena)
* void hgl_arena_destroy(HglArena *arena)
*
* hgl_arena_alloc allows the user to define the alignment of allocations from an arena by
* redefining HGL_ARENA_ALIGNMENT, as such:
*
* #define HGL_ARENA_ALIGNMENT 64
*
* The default alignment is 16.
*
*
* AUTHOR: Henrik A. Glass
*
*/
#ifndef HGL_ARENA_ALLOC_H
#define HGL_ARENA_ALLOC_H
/*--- Arena alloc-specific macros -------------------------------------------------------*/
//#define HGL_ARENA_ALLOC_DEBUG_PRINTS
#ifndef HGL_ARENA_ALIGNMENT
#define HGL_ARENA_ALIGNMENT 16
#endif
/*--- Include files ---------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <stdint.h>
#include <string.h> // memset
/*--- Public type definitions -----------------------------------------------------------*/
typedef struct
{
uint8_t *memory;
size_t head;
size_t size;
} HglArena;
/**
* Create an arena of size `arena_size`.
*/
HglArena hgl_arena_make(size_t arena_size);
/**
* Create an arena of `buf_size` from a preallocated buffer `buf`.
*/
HglArena hgl_arena_make_from_buffer(void *buf, size_t buf_size);
/**
* Allocate a chunk of `alloc_size` bytes from `arena`.
*/
void *hgl_arena_alloc(HglArena *arena, size_t alloc_size);
/**
* Free all allocations in `arena`.
*/
void hgl_arena_free_all(HglArena *arena);
/**
* Destroy the arena (Free the arena itself).
*/
void hgl_arena_destroy(HglArena *arena);
#endif /* HGL_ARENA_ALLOC_H */
/*--- Public variables ------------------------------------------------------------------*/
/*--- Arena Alloc functions -------------------------------------------------------------*/
#ifdef HGL_ARENA_ALLOC_IMPLEMENTATION
HglArena hgl_arena_make(size_t arena_size)
{
static_assert(HGL_ARENA_ALIGNMENT % 2 == 0);
void *mem = aligned_alloc(HGL_ARENA_ALIGNMENT, arena_size);
memset(mem, 0, arena_size); // why not
return (HglArena) {
.memory = mem,
.head = 0,
.size = (mem == NULL) ? 0 : arena_size,
};
}
HglArena hgl_arena_make_from_buffer(void *buf, size_t buf_size)
{
return (HglArena) {
.memory = (uint8_t *) buf,
.head = 0,
.size = buf_size,
};
}
void *hgl_arena_alloc(HglArena *arena, size_t alloc_size)
{
void *ptr = arena->memory + arena->head;
/* Allocation too small: Return NULL */
if (alloc_size == 0) {
return NULL;
}
/* Allocation too big: Return NULL */
if (arena->head + alloc_size > arena->size) {
#ifdef HGL_ARENA_ALLOC_DEBUG_PRINTS
printf("Arena alloc failed. Requested %lu bytes, but only %lu remain in arena.\n",
alloc_size, arena->size - arena->head);
#endif /* HGL_ARENA_ALLOC_DEBUG_PRINTS */
return NULL;
}
/* Move head to nearest multiple of alignment after `head` + `alloc_size` */
arena->head += (alloc_size + HGL_ARENA_ALIGNMENT - 1) &
~(HGL_ARENA_ALIGNMENT - 1);
#ifdef HGL_ARENA_ALLOC_DEBUG_PRINTS
printf("Arena usage: %f%% of %lu KiB\n",
100.f * ((float) arena->head / (float) arena->size),
(arena->size / 1024));
#endif /* HGL_ARENA_ALLOC_DEBUG_PRINTS */
return ptr;
}
void hgl_arena_free_all(HglArena *arena)
{
arena->head = 0;
}
void hgl_arena_destroy(HglArena *arena)
{
(free)(arena->memory);
}
#endif /* HGL_ARENA_ALLOC_IMPLEMENTATION */