1ef1e77260eecd2e49ebbb4f069b6167a241352a
[vg.git] / src / vg / vg_mem.h
1 #ifndef VG_MEM_H
2 #define VG_MEM_H
3
4 #include "vg_stdint.h"
5 #include "vg_platform.h"
6
7 #include <stdlib.h>
8
9 typedef struct vg_linear_allocator vg_linear_allocator;
10
11 struct
12 {
13 void *rtmemory,
14 *scratch;
15 }
16 static vg_mem;
17
18 #pragma pack(push,1)
19 struct vg_linear_allocator
20 {
21 u32 size, cur;
22
23 /* allows temporarily extendable buffers */
24 void *last_alloc;
25 u32 last_alloc_size;
26 };
27 #pragma pack(pop)
28
29 /*
30 * TODO: Fallback on libc
31 * TODO: 8 byte alignment
32 */
33
34 VG_STATIC void vg_error(const char *fmt, ...);
35
36 /* allocate something from a linear allocator */
37 __attribute__((warn_unused_result))
38 VG_STATIC void *vg_linear_alloc( void *allocator, u32 size )
39 {
40 if( allocator == NULL )
41 vg_fatal_exit_loop( "Null allocator" );
42
43 vg_linear_allocator *allocptr = allocator;
44 allocptr --;
45
46 if( allocptr->cur + size > allocptr->size )
47 {
48 vg_error( "%u(current) + %u(alloc) > %u(max)\n",
49 allocptr->cur, size, allocptr->size );
50
51 vg_fatal_exit_loop( "Linear allocator out of memory" );
52 }
53
54 void *data = allocator + allocptr->cur;
55 allocptr->cur += size;
56 allocptr->last_alloc = data;
57 allocptr->last_alloc_size = size;
58
59 return data;
60 }
61
62 /* resize latest block of memory from linear */
63 __attribute__((warn_unused_result))
64 VG_STATIC void *vg_linear_resize( void *allocator, void *data, u32 newsize )
65 {
66 vg_linear_allocator *allocptr = allocator;
67 allocptr --;
68
69 if( allocptr->last_alloc == data )
70 {
71 allocptr->cur -= allocptr->last_alloc_size;
72 return vg_linear_alloc( allocator, newsize );
73 }
74 else
75 {
76 vg_fatal_exit_loop( "Cannot resize this buffer anymore" );
77 }
78
79 return NULL;
80 }
81
82 VG_STATIC void vg_linear_del( void *allocator, void *data )
83 {
84 void *ignore = vg_linear_resize( allocator, data, 0 );
85
86 vg_linear_allocator *allocptr = allocator;
87 allocptr --;
88
89 allocptr->last_alloc = NULL;
90 allocptr->last_alloc_size = 0;
91 }
92
93 /* extend latest block of memory from linear */
94 __attribute__((warn_unused_result))
95 VG_STATIC void *vg_linear_extend( void *allocator, void *data, u32 extra )
96 {
97 vg_linear_allocator *allocptr = allocator;
98 allocptr --;
99
100 return vg_linear_resize( allocator, data, allocptr->last_alloc_size+extra );
101 }
102
103 /* get the current usage of allocator */
104 VG_STATIC u32 vg_linear_get_cur( void *allocator )
105 {
106 vg_linear_allocator *allocptr = allocator;
107 allocptr --;
108
109 return allocptr->cur;
110 }
111
112 /* get the capacity of allocator */
113 VG_STATIC u32 vg_linear_get_capacity( void *allocator )
114 {
115 vg_linear_allocator *allocptr = allocator;
116 allocptr --;
117
118 return allocptr->size;
119 }
120
121 /* get the size of the last allocated thing */
122 VG_STATIC u32 vg_linear_last_size( void *allocator )
123 {
124 vg_linear_allocator *allocptr = allocator;
125 allocptr --;
126
127 return allocptr->last_alloc_size;
128 }
129
130 /* yeet all memory from linear allocator */
131 VG_STATIC void vg_linear_clear( void *allocator )
132 {
133 vg_linear_allocator *allocptr = allocator;
134 allocptr --;
135
136 allocptr->last_alloc = NULL;
137 allocptr->last_alloc_size = 0;
138 allocptr->cur = 0;
139 }
140
141 /* allocate a FIXED SIZE linear allocator */
142 VG_STATIC void *vg_create_linear_allocator( void *lin_alloc, u32 size )
143 {
144 u32 total = size + sizeof(vg_linear_allocator);
145 vg_linear_allocator *allocptr;
146
147 if( lin_alloc == NULL )
148 {
149 static int allow_once = 1;
150
151 if( allow_once )
152 {
153 allocptr = malloc( total );
154
155 if( allocptr == NULL )
156 vg_fatal_exit_loop( "Create linear: Malloc failed" );
157
158 allow_once = 0;
159 }
160 else
161 vg_fatal_exit_loop( "Shouldnt call this twice!" );
162 }
163 else
164 {
165 vg_linear_allocator *parent = lin_alloc;
166 parent --;
167
168 allocptr = vg_linear_alloc( lin_alloc, total );
169
170 #if 0
171 parent->last_alloc = allocptr+1;
172 parent->last_alloc_size = total;
173 #else
174 parent->last_alloc = NULL;
175 parent->last_alloc_size = total;
176 #endif
177 }
178
179 allocptr->size = size;
180 allocptr->cur = 0;
181 allocptr->last_alloc = NULL;
182 allocptr->last_alloc_size = 0;
183
184 void *data = allocptr+1;
185 return data;
186 }
187
188 /* request all the memory we need in advance */
189 VG_STATIC void vg_prealloc_quota( u32 size )
190 {
191 size = VG_MAX( size, 20*1024*1024 );
192 vg_mem.rtmemory = vg_create_linear_allocator( NULL, size );
193 vg_mem.scratch = vg_create_linear_allocator( vg_mem.rtmemory, 10*1024*1024 );
194 }
195
196 #endif /* VG_MEM_H */