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