Derive-C
Loading...
Searching...
No Matches
template.h
Go to the documentation of this file.
1
2
4#if !defined(SKIP_INCLUDES)
5 #include "includes.h"
6#endif
7
9
10#if !defined CAPACITY
11 #if !defined PLACEHOLDERS
12TEMPLATE_ERROR("No CAPACITY")
13 #endif
14 #define CAPACITY 32
15#endif
16
17#if !defined KEY
18 #if !defined PLACEHOLDERS
19TEMPLATE_ERROR("No KEY")
20 #endif
21 #define KEY map_key_t
22typedef int KEY;
23#endif
24
25#if !defined KEY_EQ
26 #define KEY_EQ DC_MEM_EQ
27#endif
28
29#if !defined KEY_DELETE
30 #define KEY_DELETE DC_NO_DELETE
31#endif
32
33#if !defined KEY_CLONE
34 #define KEY_CLONE DC_COPY_CLONE
35#endif
36
37#if !defined KEY_DEBUG
38 #define KEY_DEBUG DC_DEFAULT_DEBUG
39#endif
40
41#if !defined VALUE
42 #if !defined PLACEHOLDERS
43TEMPLATE_ERROR("No VALUE")
44 #endif
45typedef struct {
46 int x;
47} value_t;
48 #define VALUE value_t
49#endif
50
51#if !defined VALUE_DELETE
52 #define VALUE_DELETE DC_NO_DELETE
53#endif
54
55#if !defined VALUE_CLONE
56 #define VALUE_CLONE DC_COPY_CLONE
57#endif
58
59#if !defined VALUE_DEBUG
60 #define VALUE_DEBUG DC_DEFAULT_DEBUG
61#endif
62
63typedef KEY NS(SELF, key_t);
64typedef VALUE NS(SELF, value_t);
65
66static size_t NS(SELF, capacity)() { return CAPACITY; };
67
68#define BITSET NS(NAME, bitset)
69
70#define EXCLUSIVE_END_INDEX CAPACITY // [DERIVE-C] for template
71#define INTERNAL_NAME BITSET // [DERIVE-C] for template
73
74#define INDEX_TYPE NS(BITSET, index_t)
75
76typedef struct {
80
83} SELF;
84
85#define INVARIANT_CHECK(self) DC_ASSUME(self);
86
87static SELF NS(SELF, new)() {
88 return (SELF){
89 .presence = NS(BITSET, new)(),
90 .keys = {},
91 .values = {},
92 .derive_c_map_staticlinear = dc_gdb_marker_new(),
93 .iterator_invalidation_tracker = mutation_tracker_new(),
94 };
95}
96
97static VALUE const* NS(SELF, try_read)(SELF const* self, KEY key) {
98 INVARIANT_CHECK(self);
99 for (INDEX_TYPE index = 0; index < CAPACITY; index++) {
100 if (NS(BITSET, get)(&self->presence, index) && KEY_EQ(&self->keys[index], &key)) {
101 return &self->values[index];
102 }
103 }
104 return NULL;
105}
106
107static VALUE const* NS(SELF, read)(SELF const* self, KEY key) {
108 VALUE const* value = NS(SELF, try_read)(self, key);
109 DC_ASSERT(value);
110 return value;
111}
112
113static VALUE* NS(SELF, try_write)(SELF* self, KEY key) {
114 return (VALUE*)(NS(SELF, try_read)(self, key));
115}
116
117static VALUE* NS(SELF, write)(SELF* self, KEY key) {
118 VALUE* value = NS(SELF, try_write)(self, key);
119 DC_ASSERT(value);
120 return value;
121}
122
123static VALUE* NS(SELF, try_insert)(SELF* self, KEY key, VALUE value) {
124 INVARIANT_CHECK(self);
125 mutation_tracker_mutate(&self->iterator_invalidation_tracker);
126
127 if (NS(BITSET, size)(&self->presence) + 1 > CAPACITY) {
128 return NULL;
129 }
130
131 VALUE const* existing_value = NS(SELF, try_read)(self, key);
132 if (existing_value) {
133 return NULL;
134 }
135
136 for (INDEX_TYPE index = 0; index < CAPACITY; index++) {
137 if (!NS(BITSET, get)(&self->presence, index)) {
138 NS(BITSET, set)(&self->presence, index, true);
139 self->keys[index] = key;
140 self->values[index] = value;
141 return &self->values[index];
142 }
143 }
144
145 DC_UNREACHABLE("A space must exist for insert");
146}
147
148static VALUE* NS(SELF, insert)(SELF* self, KEY key, VALUE value) {
149 VALUE* placed = NS(SELF, try_insert)(self, key, value);
150 DC_ASSERT(placed);
151 return placed;
152}
153
154static bool NS(SELF, try_remove)(SELF* self, KEY key, VALUE* dest) {
155 INVARIANT_CHECK(self);
156 mutation_tracker_mutate(&self->iterator_invalidation_tracker);
157
158 for (INDEX_TYPE index = 0; index < CAPACITY; index++) {
159 if (NS(BITSET, get)(&self->presence, index) && KEY_EQ(&self->keys[index], &key)) {
160 NS(BITSET, set)(&self->presence, index, false);
161 KEY_DELETE(&self->keys[index]);
162 *dest = self->values[index];
163 return true;
164 }
165 }
166 return false;
167}
168
169static VALUE NS(SELF, remove)(SELF* self, KEY key) {
170 VALUE dest;
171 DC_ASSERT(NS(SELF, try_remove)(self, key, &dest));
172 return dest;
173}
174
175static void NS(SELF, delete_entry)(SELF* self, KEY key) {
176 VALUE val = NS(SELF, remove)(self, key);
177 VALUE_DELETE(&val);
178}
179
180static size_t NS(SELF, size)(SELF const* self) { return (size_t)NS(BITSET, size)(&self->presence); }
181
182static SELF NS(SELF, clone)(SELF const* self) {
183 INVARIANT_CHECK(self);
184
185 SELF new_self = (SELF){
186 .presence = NS(BITSET, clone)(&self->presence),
187 .derive_c_map_staticlinear = dc_gdb_marker_new(),
188 .iterator_invalidation_tracker = mutation_tracker_new(),
189 };
190 for (INDEX_TYPE index = 0; index < CAPACITY; index++) {
191 if (NS(BITSET, get)(&self->presence, index)) {
192 new_self.keys[index] = KEY_CLONE(&self->keys[index]);
193 new_self.values[index] = VALUE_CLONE(&self->values[index]);
194 }
195 }
196 return new_self;
197}
198
199static void NS(SELF, delete)(SELF* self) {
200 INVARIANT_CHECK(self);
201
202 for (INDEX_TYPE index = 0; index < CAPACITY; index++) {
203 if (NS(BITSET, get)(&self->presence, index)) {
204 KEY_DELETE(&self->keys[index]);
205 VALUE_DELETE(&self->values[index]);
206 }
207 }
208 NS(BITSET, delete)(&self->presence);
209}
210
211static void NS(SELF, debug)(SELF const* self, dc_debug_fmt fmt, FILE* stream) {
212 fprintf(stream, EXPAND_STRING(SELF) "@%p {\n", self);
213 fmt = dc_debug_fmt_scope_begin(fmt);
214
215 dc_debug_fmt_print(fmt, stream, "entries: [");
216 fmt = dc_debug_fmt_scope_begin(fmt);
217 for (INDEX_TYPE index = 0; index < CAPACITY; index++) {
218 if (NS(BITSET, get)(&self->presence, index)) {
219 dc_debug_fmt_print(fmt, stream, "(index: %lu, key: ", (size_t)index);
220 KEY_DEBUG(&self->keys[index], fmt, stream);
221 dc_debug_fmt_print(fmt, stream, ", value: ");
222 VALUE_DEBUG(&self->values[index], fmt, stream);
223 dc_debug_fmt_print(fmt, stream, "), ");
224 }
225 }
226 fmt = dc_debug_fmt_scope_end(fmt);
227 dc_debug_fmt_print(fmt, stream, "],\n");
228
229 fmt = dc_debug_fmt_scope_end(fmt);
230 dc_debug_fmt_print(fmt, stream, "}");
231}
232
233#define ITER_CONST NS(SELF, iter_const)
234#define KV_PAIR_CONST NS(ITER_CONST, item)
235
236typedef struct {
237 SELF const* map;
238 INDEX_TYPE next_index;
239 mutation_version version;
240} ITER_CONST;
241
242typedef struct {
243 KEY const* key;
244 VALUE const* value;
246
248 return item->key == NULL && item->value == NULL;
249}
250
252 mutation_version_check(&iter->version);
253 INDEX_TYPE const next_index = iter->next_index;
254
255 if (next_index == CAPACITY) {
256 return (KV_PAIR_CONST){.key = NULL, .value = NULL};
257 }
258
259 iter->next_index++;
260 while (iter->next_index < CAPACITY &&
261 !NS(BITSET, get)(&iter->map->presence, iter->next_index)) {
262 iter->next_index++;
263 }
264
265 if (next_index == CAPACITY) {
266 return (KV_PAIR_CONST){.key = NULL, .value = NULL};
267 }
268 return (KV_PAIR_CONST){
269 .key = &iter->map->keys[next_index],
270 .value = &iter->map->values[next_index],
271 };
272}
273
274static ITER_CONST NS(SELF, get_iter_const)(SELF const* self) {
275 INVARIANT_CHECK(self);
276
277 INDEX_TYPE next_index = 0;
278 while (next_index < CAPACITY && !NS(BITSET, get)(&self->presence, next_index)) {
279 next_index++;
280 }
281
282 return (ITER_CONST){
283 .map = self,
284 .next_index = next_index,
285 .version = mutation_tracker_get(&self->iterator_invalidation_tracker),
286 };
287}
288
289#undef KV_PAIR_CONST
290#undef ITER_CONST
291
292#define ITER NS(SELF, iter)
293#define KV_PAIR NS(ITER, item)
294
295typedef struct {
296 SELF* map;
297 INDEX_TYPE next_index;
298 mutation_version version;
299} ITER;
300
301typedef struct {
302 KEY const* key;
303 VALUE const* value;
304} KV_PAIR;
305
306static bool NS(ITER, empty_item)(KV_PAIR const* item) {
307 return item->key == NULL && item->value == NULL;
308}
309
310static KV_PAIR NS(ITER, next)(ITER* iter) {
311 mutation_version_check(&iter->version);
312 INDEX_TYPE const next_index = iter->next_index;
313
314 if (next_index == CAPACITY) {
315 return (KV_PAIR){.key = NULL, .value = NULL};
316 }
317
318 iter->next_index++;
319 while (iter->next_index < CAPACITY &&
320 !NS(BITSET, get)(&iter->map->presence, iter->next_index)) {
321 iter->next_index++;
322 }
323
324 if (next_index == CAPACITY) {
325 return (KV_PAIR){.key = NULL, .value = NULL};
326 }
327 return (KV_PAIR){
328 .key = &iter->map->keys[next_index],
329 .value = &iter->map->values[next_index],
330 };
331}
332
333static ITER NS(SELF, get_iter)(SELF* self) {
334 INVARIANT_CHECK(self);
335
336 INDEX_TYPE next_index = 0;
337 while (next_index < CAPACITY && !NS(BITSET, get)(&self->presence, next_index)) {
338 next_index++;
339 }
340
341 return (ITER){
342 .map = self,
343 .next_index = next_index,
344 .version = mutation_tracker_get(&self->iterator_invalidation_tracker),
345 };
346}
347
348#undef KV_PAIR
349#undef ITER
350
351#undef INVARIANT_CHECK
352#undef INDEX_TYPE
353#undef BITSET
354
355#undef VALUE_DEBUG
356#undef VALUE_CLONE
357#undef VALUE_DELETE
358#undef VALUE
359
360#undef KEY_DEBUG
361#undef KEY_CLONE
362#undef KEY_DELETE
363#undef KEY_EQ
364#undef KEY
365
366#undef CAPACITY
367
369
static void debug(SELF const *self, dc_debug_fmt fmt, FILE *stream)
Definition template.h:62
#define CAPACITY
A very simple bump allocator making use of a provided fixed size buffer (e.g. statically allocated).
Definition template.h:17
static INDEX insert(SELF *self, VALUE value)
Definition template.h:127
static ITER_CONST get_iter_const(SELF const *self)
Definition template.h:449
static ITER get_iter(SELF *self)
Definition template.h:370
#define VALUE_DEBUG
Definition template.h:39
static IV_PAIR next(ITER *iter)
Definition template.h:352
static INDEX_TYPE size(SELF const *self)
Definition template.h:252
#define INVARIANT_CHECK(self)
Definition template.h:88
static VALUE remove(SELF *self, INDEX index)
Definition template.h:292
static bool empty_item(IV_PAIR const *item)
Definition template.h:344
static VALUE * try_write(SELF *self, INDEX index)
Definition template.h:205
static VALUE const * read(SELF const *self, INDEX index)
Definition template.h:199
static VALUE * write(SELF *self, INDEX index)
Definition template.h:209
#define VALUE
Definition template.h:31
#define ITER
Definition template.h:320
#define VALUE_CLONE
Definition template.h:37
#define VALUE_DELETE
Definition template.h:35
static bool try_remove(SELF *self, INDEX index, VALUE *destination)
Definition template.h:264
#define ITER_CONST
Definition template.h:398
static SELF clone(SELF const *self)
Definition template.h:215
static VALUE const * try_read(SELF const *self, INDEX index)
Definition template.h:180
IV_PAIR item
Definition template.h:283
static void set(SELF *self, INDEX_TYPE index, bool value)
Definition template.h:74
#define KV_PAIR
Definition template.h:584
#define KEY_DELETE
Definition template.h:35
#define KEY_CLONE
Definition template.h:39
static VALUE * try_insert(SELF *self, KEY key, VALUE value)
Definition template.h:328
#define KEY
A simple swiss table implementation. See the abseil docs for swss table here.
Definition template.h:17
#define KEY_EQ
Definition template.h:31
#define KEY_DEBUG
Definition template.h:43
static void delete_entry(SELF *self, KEY key)
Definition template.h:508
KEY key_t
Definition template.h:68
#define KV_PAIR_CONST
Definition template.h:526
#define INDEX_TYPE
Definition template.h:74
#define BITSET
Definition template.h:68
static size_t capacity()
Definition template.h:66
#define DC_TRAIT_MAP(SELF)
Definition trait.h:5
dc_debug_fmt dc_debug_fmt_scope_end(dc_debug_fmt fmt)
Definition fmt.h:39
dc_debug_fmt dc_debug_fmt_scope_begin(dc_debug_fmt fmt)
Definition fmt.h:33
static void dc_debug_fmt_print(dc_debug_fmt fmt, FILE *stream, const char *format,...)
Definition fmt.h:22
static dc_gdb_marker dc_gdb_marker_new()
Definition gdb_marker.h:7
static mutation_tracker mutation_tracker_new()
static void mutation_version_check(mutation_version const *self)
static mutation_version mutation_tracker_get(mutation_tracker const *self)
static void mutation_tracker_mutate(mutation_tracker *self)
#define EXPAND_STRING(NAME)
Definition namespace.h:8
#define NS(pre, post)
Definition namespace.h:4
static nullalloc get()
Definition null.h:14
#define DC_UNREACHABLE(...)
Definition panic.h:43
#define DC_ASSERT(expr,...)
Definition panic.h:36
#define TEMPLATE_ERROR(...)
With the user provided name, even in nested templates.
Definition def.h:56
#define SELF
Definition def.h:52
mutation_tracker iterator_invalidation_tracker
Definition template.h:85
BITSET presence
Definition template.h:77
VALUE * values
Definition template.h:81
dc_gdb_marker derive_c_map_staticlinear
Definition template.h:81
KEY_ENTRY * keys
Definition template.h:80
Debug format helpers for debug printin data structures.
Definition fmt.h:10
tracks a specific version of a value, so that this can be compared later to check modification For ex...
static FILE * stream(SELF *self)
Opens a file for.
Definition template.h:107