Derive-C
Loading...
Searching...
No Matches
template.h
Go to the documentation of this file.
1
28
30#if !defined(SKIP_INCLUDES)
31 #include "includes.h"
32#endif
33
36
37#if !defined INDEX_BITS
38 #if !defined DC_PLACEHOLDERS
39TEMPLATE_ERROR("The number of bits (8,16,32,64) to use for the arena's key")
40 #endif
41 #define INDEX_BITS 32
42#endif
43
44#if !defined VALUE
45 #if !defined DC_PLACEHOLDERS
46TEMPLATE_ERROR("The value type to place in the arena must be defined")
47 #endif
48typedef struct {
49 int x;
50} value_t;
51 #define VALUE value_t
52 #define VALUE_DELETE value_delete
53static void VALUE_DELETE(value_t* /* self */) {}
54 #define VALUE_CLONE value_clone
55static value_t VALUE_CLONE(value_t const* self) { return *self; }
56 #define VALUE_DEBUG value_debug
57static void VALUE_DEBUG(VALUE const* /* self */, dc_debug_fmt /* fmt */, FILE* /* stream */) {}
58#endif
59
60DC_STATIC_ASSERT(sizeof(VALUE), "VALUE must be a non-zero sized type");
61
62#if !defined VALUE_DELETE
63 #define VALUE_DELETE DC_NO_DELETE
64#endif
65
66#if !defined VALUE_CLONE
67 #define VALUE_CLONE DC_COPY_CLONE
68#endif
69
70#if !defined VALUE_DEBUG
71 #define VALUE_DEBUG DC_DEFAULT_DEBUG
72#endif
73
76
77#if !defined INITIAL_BLOCK_INDEX_BITS
78 #define INITIAL_BLOCK_INDEX_BITS 8
79#endif
80
82 "INITIAL_BLOCK_INDEX_BITS must be less than INDEX_BITS");
84 "INITIAL_BLOCK_INDEX_BITS must be greater than zero");
85
86static const size_t NS(SELF, max_entries) = MAX_INDEX;
87
88typedef VALUE NS(SELF, value_t);
89typedef ALLOC NS(SELF, alloc_t);
90
91#define SLOT NS(NAME, slot)
92
93#define SLOT_INDEX_TYPE INDEX_TYPE // [DERIVE-C] for template
94#define SLOT_VALUE VALUE // [DERIVE-C] for template
95#define SLOT_VALUE_CLONE VALUE_CLONE // [DERIVE-C] for template
96#define SLOT_VALUE_DELETE VALUE_DELETE // [DERIVE-C] for template
97#define INTERNAL_NAME SLOT // [DERIVE-C] for template
99
100typedef struct {
101 // INVARIANT: If free_list == EMPTY_INDEX, then all values from [0, count)
102 // are present
103 INDEX_TYPE free_list;
104 size_t count;
105
106 NS(ALLOC, ref) alloc_ref;
109
111 // JUSTIFY: Block is a uint8_t
112 // - We can have at most 63 blocks, as we can have 64 bit indices, with an initial 1 bit size.
115} SELF;
116
117#define INVARIANT_CHECK(self) \
118 DC_ASSUME(self); \
119 DC_ASSUME(DC_ARENA_GEO_BLOCK_TO_SIZE((self)->block_current, INITIAL_BLOCK_INDEX_BITS) >= \
120 (self)->block_current_exclusive_end); \
121 DC_ASSUME((self)->count <= MAX_INDEX);
122
123DC_PUBLIC static SELF NS(SELF, new)(NS(ALLOC, ref) alloc_ref) {
124 uint8_t initial_block = 0;
125 size_t initial_block_items =
127 SLOT* initial_block_slots =
128 (SLOT*)NS(ALLOC, allocate_uninit)(alloc_ref, initial_block_items * sizeof(SLOT));
129
130 SELF self = {
131 .free_list = INDEX_NONE,
132 .count = 0,
133 .alloc_ref = alloc_ref,
134 .derive_c_arena_blocks = dc_gdb_marker_new(),
135 .iterator_invalidation_tracker = mutation_tracker_new(),
136 .block_current_exclusive_end = 0,
137 .block_current = initial_block,
138 .blocks =
139 {
140 initial_block_slots,
141 },
142 };
143
144 return self;
145}
146
147DC_PUBLIC static INDEX NS(SELF, insert)(SELF* self, VALUE value) {
148 INVARIANT_CHECK(self);
149 DC_ASSERT(self->count < MAX_INDEX,
150 "Arena is full, cannot insert {count=%lu, max_index=%lu, value=%s}",
151 (size_t)self->count, (size_t)MAX_INDEX, DC_DEBUG(VALUE_DEBUG, &value));
152
153 mutation_tracker_mutate(&self->iterator_invalidation_tracker);
154
155 if (self->free_list != INDEX_NONE) {
156 INDEX_TYPE free_index = self->free_list;
157
158 uint8_t block = DC_ARENA_GEO_INDEX_TO_BLOCK(free_index, INITIAL_BLOCK_INDEX_BITS);
159 size_t offset = DC_ARENA_GEO_INDEX_TO_OFFSET(free_index, block, INITIAL_BLOCK_INDEX_BITS);
160 SLOT* free_slot = &self->blocks[block][offset];
161
162 DC_ASSUME(!free_slot->present, "The free list should only contain free slots");
163 self->free_list = free_slot->next_free;
164
165 NS(SLOT, fill)(free_slot, value);
166
167 self->count++;
168
169 return (INDEX){.index = free_index};
170 }
171
172 if (self->block_current_exclusive_end ==
174 DC_ASSUME(self->block_current < sizeof(self->blocks) / sizeof(SLOT*));
175
176 self->block_current++;
177 size_t block_items =
179 SLOT* block_slots =
180 (SLOT*)NS(ALLOC, allocate_uninit)(self->alloc_ref, block_items * sizeof(SLOT));
181
182 self->blocks[self->block_current] = block_slots;
183 self->block_current_exclusive_end = 0;
184 }
185
186 size_t offset = self->block_current_exclusive_end;
187 NS(SLOT, fill)(&self->blocks[self->block_current][offset], value);
188 INDEX_TYPE new_index = (INDEX_TYPE)(DC_ARENA_GEO_BLOCK_OFFSET_TO_INDEX(
189 self->block_current, offset, INITIAL_BLOCK_INDEX_BITS));
190
191 self->block_current_exclusive_end++;
192 self->count++;
193
194 return (INDEX){.index = new_index};
195}
196
197DC_PUBLIC static VALUE const* NS(SELF, try_read)(SELF const* self, INDEX index) {
198 INVARIANT_CHECK(self);
199
200 uint8_t block = DC_ARENA_GEO_INDEX_TO_BLOCK(index.index, INITIAL_BLOCK_INDEX_BITS);
201 if (block > self->block_current) {
202 return NULL;
203 }
204
205 size_t offset = DC_ARENA_GEO_INDEX_TO_OFFSET(index.index, block, INITIAL_BLOCK_INDEX_BITS);
206
207 if (block == self->block_current && offset >= self->block_current_exclusive_end) {
208 return NULL;
209 }
210
211 SLOT* slot = &self->blocks[block][offset];
212 if (!slot->present) {
213 return NULL;
214 }
215
216 return &slot->value;
217}
218
219DC_PUBLIC static VALUE const* NS(SELF, read)(SELF const* self, INDEX index) {
220 VALUE const* value = NS(SELF, try_read)(self, index);
221 DC_ASSERT(value, "Cannot read item, index not found {index=%lu}", (size_t)index.index);
222 return value;
223}
224
225DC_PUBLIC static VALUE* NS(SELF, try_write)(SELF* self, INDEX index) {
226 return (VALUE*)NS(SELF, try_read)(self, index);
227}
228
229DC_PUBLIC static VALUE* NS(SELF, write)(SELF* self, INDEX index) {
230 VALUE* value = NS(SELF, try_write)(self, index);
231 DC_ASSERT(value, "Cannot write item, index not found {index=%lu}", (size_t)index.index);
232 return value;
233}
234
235DC_PUBLIC static size_t NS(SELF, size)(SELF const* self) {
236 INVARIANT_CHECK(self);
237 return self->count;
238}
239
240DC_PUBLIC static SELF NS(SELF, clone)(SELF const* self) {
241 INVARIANT_CHECK(self);
242
243 SELF new_self = {
244 .free_list = self->free_list,
245 .count = self->count,
246 .alloc_ref = self->alloc_ref,
247 .derive_c_arena_blocks = dc_gdb_marker_new(),
248 .iterator_invalidation_tracker = mutation_tracker_new(),
249 .block_current_exclusive_end = self->block_current_exclusive_end,
250 .block_current = self->block_current,
251 .blocks = {},
252 };
253
254 for (size_t block_index = 0; block_index <= self->block_current; block_index++) {
255 size_t block_items = DC_ARENA_GEO_BLOCK_TO_SIZE(block_index, INITIAL_BLOCK_INDEX_BITS);
256 SLOT* block_slots =
257 (SLOT*)NS(ALLOC, allocate_uninit)(self->alloc_ref, block_items * sizeof(SLOT));
258 new_self.blocks[block_index] = block_slots;
259
260 size_t const to_offset =
261 block_index == self->block_current ? self->block_current_exclusive_end : block_items;
262
263 for (size_t offset = 0; offset < to_offset; offset++) {
264 SLOT* src_slot = &self->blocks[block_index][offset];
265 SLOT* dst_slot = &new_self.blocks[block_index][offset];
266 NS(SLOT, clone_from)(src_slot, dst_slot);
267 }
268 }
269
270 return new_self;
271}
272
273DC_PUBLIC static bool NS(SELF, try_remove)(SELF* self, INDEX index, VALUE* destination) {
274 INVARIANT_CHECK(self);
275 mutation_tracker_mutate(&self->iterator_invalidation_tracker);
276
277 uint8_t block = DC_ARENA_GEO_INDEX_TO_BLOCK(index.index, INITIAL_BLOCK_INDEX_BITS);
278 if (block > self->block_current) {
279 return false;
280 }
281
282 size_t offset = DC_ARENA_GEO_INDEX_TO_OFFSET(index.index, block, INITIAL_BLOCK_INDEX_BITS);
283
284 if (block == self->block_current && offset >= self->block_current_exclusive_end) {
285 return false;
286 }
287
288 SLOT* slot = &self->blocks[block][offset];
289 if (slot->present) {
290 *destination = slot->value;
291
292 NS(SLOT, set_empty)(slot, self->free_list);
293 self->free_list = index.index;
294 self->count--;
295 return true;
296 }
297 return false;
298}
299
300DC_PUBLIC static VALUE NS(SELF, remove)(SELF* self, INDEX index) {
301 INVARIANT_CHECK(self);
302 mutation_tracker_mutate(&self->iterator_invalidation_tracker);
303
304 VALUE value;
305 DC_ASSERT(NS(SELF, try_remove)(self, index, &value),
306 "Failed to remove item, index not found {index=%lu}", (size_t)index.index);
307 return value;
308}
309
310DC_PUBLIC static void NS(SELF, delete)(SELF* self) {
311 INVARIANT_CHECK(self);
312
313 for (uint8_t block = 0; block <= self->block_current; block++) {
314 size_t const to_offset = block == self->block_current
315 ? self->block_current_exclusive_end
317
318 for (size_t offset = 0; offset < to_offset; offset++) {
319 SLOT* slot = &self->blocks[block][offset];
320 if (slot->present) {
321 VALUE_DELETE(&slot->value);
322 }
323 }
324
325 size_t block_size =
328 self->blocks[block], block_size);
329 NS(ALLOC, deallocate)(self->alloc_ref, self->blocks[block], block_size);
330 }
331}
332
333#define IV_PAIR_CONST NS(SELF, iv_const)
334typedef struct {
335 INDEX index;
336 VALUE const* value;
338
340 return (IV_PAIR_CONST){
341 .index = {.index = INDEX_NONE},
342 .value = NULL,
343 };
344}
345
346#define ITER_CONST NS(SELF, iter_const)
348
350 return item->value == NULL;
351}
352
353typedef struct {
354 SELF const* arena;
355 INDEX_TYPE next_index;
356 mutation_version version;
357} ITER_CONST;
358
360 DC_ASSUME(iter);
361 mutation_version_check(&iter->version);
362
363 while (iter->next_index < MAX_INDEX) {
364 uint8_t block = DC_ARENA_GEO_INDEX_TO_BLOCK(iter->next_index, INITIAL_BLOCK_INDEX_BITS);
365 size_t offset =
367
368 if ((block == iter->arena->block_current &&
369 offset >= iter->arena->block_current_exclusive_end) ||
370 (block > iter->arena->block_current)) {
371 break;
372 }
373
374 SLOT* slot = &iter->arena->blocks[block][offset];
375 if (slot->present) {
376 IV_PAIR_CONST const result = {
377 .index = (INDEX){.index = iter->next_index},
378 .value = &slot->value,
379 };
380 iter->next_index++;
381 return result;
382 }
383
384 iter->next_index++;
385 }
386
387 return NS(SELF, iv_const_empty)();
388}
389
390DC_PUBLIC static bool NS(ITER_CONST, empty)(ITER_CONST const* iter) {
391 DC_ASSUME(iter);
392 mutation_version_check(&iter->version);
393
394 // Scan forward to see if there are any present slots remaining
395 INDEX_TYPE search_index = iter->next_index;
396 while (search_index < MAX_INDEX) {
397 uint8_t block = DC_ARENA_GEO_INDEX_TO_BLOCK(search_index, INITIAL_BLOCK_INDEX_BITS);
398 size_t offset = DC_ARENA_GEO_INDEX_TO_OFFSET(search_index, block, INITIAL_BLOCK_INDEX_BITS);
399
400 // Check if we're past the valid range
401 if ((block == iter->arena->block_current &&
402 offset >= iter->arena->block_current_exclusive_end) ||
403 (block > iter->arena->block_current)) {
404 return true;
405 }
406
407 SLOT* slot = &iter->arena->blocks[block][offset];
408 if (slot->present) {
409 return false;
410 }
411
412 search_index++;
413 }
414
415 return true;
416}
417
419 INVARIANT_CHECK(self);
420
421 return (ITER_CONST){
422 .arena = self,
423 .next_index = 0,
424 .version = mutation_tracker_get(&self->iterator_invalidation_tracker),
425 };
426}
427
428DC_PUBLIC static void NS(SELF, debug)(SELF const* self, dc_debug_fmt fmt, FILE* stream) {
429 fprintf(stream, DC_EXPAND_STRING(SELF) "@%p {\n", (void*)self);
430 fmt = dc_debug_fmt_scope_begin(fmt);
431 dc_debug_fmt_print(fmt, stream, "count: %lu,\n", self->count);
432
433 if (self->free_list == INDEX_NONE) {
434 dc_debug_fmt_print(fmt, stream, "free_list: INDEX_NONE,\n");
435 } else {
436 dc_debug_fmt_print(fmt, stream, "free_list: %lu,\n", (size_t)self->free_list);
437 }
438
439 dc_debug_fmt_print(fmt, stream, "alloc: ");
440 NS(ALLOC, debug)(NS(NS(ALLOC, ref), deref)(self->alloc_ref), fmt, stream);
441 fprintf(stream, ",\n");
442
443 dc_debug_fmt_print(fmt, stream, "blocks: [\n");
444 fmt = dc_debug_fmt_scope_begin(fmt);
445 for (size_t block = 0; block <= self->block_current; block++) {
446 dc_debug_fmt_print(fmt, stream, "{\n");
447 fmt = dc_debug_fmt_scope_begin(fmt);
448
449 size_t const capacity = DC_ARENA_GEO_BLOCK_TO_SIZE(block, INITIAL_BLOCK_INDEX_BITS);
450 size_t const to_offset =
451 block == self->block_current ? self->block_current_exclusive_end : capacity;
452
453 dc_debug_fmt_print(fmt, stream, "block_index: %lu,\n", block);
454 dc_debug_fmt_print(fmt, stream, "block_ptr: %p,\n", (void*)self->blocks[block]);
455 dc_debug_fmt_print(fmt, stream, "capacity: %lu,\n", capacity);
456 dc_debug_fmt_print(fmt, stream, "size: %lu,\n", to_offset);
457 dc_debug_fmt_print(fmt, stream, "slots: [\n");
458 fmt = dc_debug_fmt_scope_begin(fmt);
459
460 for (size_t offset = 0; offset < to_offset; offset++) {
461 SLOT* slot = &self->blocks[block][offset];
462 dc_debug_fmt_print(fmt, stream, "{\n");
463 fmt = dc_debug_fmt_scope_begin(fmt);
464
465 dc_debug_fmt_print(fmt, stream, "present: %s,\n", slot->present ? "true" : "false");
466 if (slot->present) {
467 dc_debug_fmt_print(fmt, stream, "value: ");
468 VALUE_DEBUG(&slot->value, fmt, stream);
469 fprintf(stream, ",\n");
470 } else {
471 dc_debug_fmt_print(fmt, stream, "next_free: %lu,\n", (size_t)slot->next_free);
472 }
473
474 fmt = dc_debug_fmt_scope_end(fmt);
475 dc_debug_fmt_print(fmt, stream, "},\n");
476 }
477
478 fmt = dc_debug_fmt_scope_end(fmt);
479 dc_debug_fmt_print(fmt, stream, "],\n");
480
481 /* Close the block's scope and print its closing brace */
482 fmt = dc_debug_fmt_scope_end(fmt);
483 dc_debug_fmt_print(fmt, stream, "},\n");
484 }
485
486 fmt = dc_debug_fmt_scope_end(fmt);
487 dc_debug_fmt_print(fmt, stream, "],\n");
488
489 fmt = dc_debug_fmt_scope_end(fmt);
490 dc_debug_fmt_print(fmt, stream, "}");
491}
492
493#undef ITER_CONST
494#undef IV_PAIR_CONST
495
496#define IV_PAIR NS(SELF, iv)
497typedef struct {
498 INDEX index;
499 VALUE const* value;
500} IV_PAIR;
501
503 return (IV_PAIR){
504 .index = {.index = INDEX_NONE},
505 .value = NULL,
506 };
507}
508
509#define ITER NS(SELF, iter)
510typedef IV_PAIR NS(ITER, item);
511
512DC_PUBLIC static bool NS(ITER, empty_item)(IV_PAIR const* item) { return item->value == NULL; }
513
514typedef struct {
515 SELF* arena;
516 INDEX_TYPE next_index;
517 mutation_version version;
518} ITER;
519
520DC_PUBLIC static IV_PAIR NS(ITER, next)(ITER* iter) {
521 DC_ASSUME(iter);
522 mutation_version_check(&iter->version);
523
524 while (iter->next_index < MAX_INDEX) {
525 uint8_t block = DC_ARENA_GEO_INDEX_TO_BLOCK(iter->next_index, INITIAL_BLOCK_INDEX_BITS);
526 size_t offset =
528
529 if ((block == iter->arena->block_current &&
530 offset >= iter->arena->block_current_exclusive_end) ||
531 (block > iter->arena->block_current)) {
532 break;
533 }
534
535 SLOT* slot = &iter->arena->blocks[block][offset];
536 if (slot->present) {
537 IV_PAIR result = {
538 .index = (INDEX){.index = iter->next_index},
539 .value = &slot->value,
540 };
541 iter->next_index++;
542 return result;
543 }
544
545 iter->next_index++;
546 }
547
548 return NS(SELF, iv_empty)();
549}
550
551DC_PUBLIC static bool NS(ITER, empty)(ITER const* iter) {
552 DC_ASSUME(iter);
553 mutation_version_check(&iter->version);
554
555 // Scan forward to see if there are any present slots remaining
556 INDEX_TYPE search_index = iter->next_index;
557 while (search_index < MAX_INDEX) {
558 uint8_t block = DC_ARENA_GEO_INDEX_TO_BLOCK(search_index, INITIAL_BLOCK_INDEX_BITS);
559 size_t offset = DC_ARENA_GEO_INDEX_TO_OFFSET(search_index, block, INITIAL_BLOCK_INDEX_BITS);
560
561 // Check if we're past the valid range
562 if ((block == iter->arena->block_current &&
563 offset >= iter->arena->block_current_exclusive_end) ||
564 (block > iter->arena->block_current)) {
565 return true;
566 }
567
568 SLOT* slot = &iter->arena->blocks[block][offset];
569 if (slot->present) {
570 return false;
571 }
572
573 search_index++;
574 }
575
576 return true;
577}
578
580 INVARIANT_CHECK(self);
581
582 return (ITER){
583 .arena = self,
584 .next_index = 0,
585 .version = mutation_tracker_get(&self->iterator_invalidation_tracker),
586 };
587}
588
589#undef ITER
590#undef IV_PAIR
591#undef INVARIANT_CHECK
592#undef SLOT
593#undef INITIAL_BLOCK_INDEX_BITS
594
597
598#undef VALUE_DEBUG
599#undef VALUE_CLONE
600#undef VALUE_DELETE
601#undef VALUE
602#undef INDEX_BITS
603
605
static DC_PUBLIC void deallocate(SELF *self, void *ptr, size_t size)
Definition template.h:127
static DC_PUBLIC void debug(SELF const *self, dc_debug_fmt fmt, FILE *stream)
Definition template.h:212
static DC_PUBLIC void * allocate_uninit(SELF *self, size_t size)
Definition template.h:92
#define ALLOC
Definition template.h:31
#define VALUE
Definition template.h:35
#define DC_ARENA_GEO_MAX_NUM_BLOCKS(INDEX_BITS, INITIAL_BLOCK_INDEX_BITS)
Definition utils.h:19
#define DC_ARENA_GEO_BLOCK_TO_SIZE(BLOCK, INITIAL_BLOCK_INDEX_BITS)
Definition utils.h:12
#define DC_ARENA_GEO_INDEX_TO_OFFSET(IDX, BLOCK, INITIAL_BLOCK_INDEX_BITS)
Definition utils.h:9
#define DC_ARENA_GEO_BLOCK_OFFSET_TO_INDEX(BLOCK, OFFSET, INITIAL_BLOCK_INDEX_BITS)
Definition utils.h:16
#define DC_ARENA_GEO_INDEX_TO_BLOCK(IDX, INITIAL_BLOCK_INDEX_BITS)
Definition utils.h:4
static DC_PUBLIC VALUE const * try_read(SELF const *self, INDEX index)
Definition template.h:180
static DC_PUBLIC VALUE * try_write(SELF *self, INDEX index)
Definition template.h:205
static DC_PUBLIC IV_PAIR iv_empty()
Definition template.h:343
static DC_PUBLIC const size_t max_entries
Definition template.h:262
#define INDEX_BITS
Definition template.h:13
#define VALUE_DEBUG
Definition template.h:41
#define IV_PAIR
Definition template.h:323
#define SLOT
Definition template.h:65
#define INVARIANT_CHECK(self)
Definition template.h:90
static DC_PUBLIC IV_PAIR next(ITER *iter)
Definition template.h:355
static DC_PUBLIC INDEX insert(SELF *self, VALUE value)
Definition template.h:126
static DC_PUBLIC bool empty(ITER const *iter)
Definition template.h:349
static DC_PUBLIC VALUE const * read(SELF const *self, INDEX index)
Definition template.h:199
static DC_PUBLIC bool try_remove(SELF *self, INDEX index, VALUE *destination)
Definition template.h:264
#define IV_PAIR_CONST
Definition template.h:412
ALLOC alloc_t
Definition template.h:63
static DC_PUBLIC VALUE * write(SELF *self, INDEX index)
Definition template.h:209
static DC_PUBLIC bool empty_item(IV_PAIR const *item)
Definition template.h:347
static DC_PUBLIC VALUE remove(SELF *self, INDEX index)
Definition template.h:292
#define ITER
Definition template.h:322
#define VALUE_CLONE
Definition template.h:39
static DC_PUBLIC ITER get_iter(SELF *self)
Definition template.h:373
#define VALUE_DELETE
Definition template.h:37
#define ITER_CONST
Definition template.h:411
static DC_PUBLIC IV_PAIR_CONST iv_const_empty()
Definition template.h:432
static DC_PUBLIC ITER_CONST get_iter_const(SELF const *self)
Definition template.h:464
static DC_PUBLIC size_t size(SELF const *self)
Definition template.h:252
static DC_PUBLIC SELF clone(SELF const *self)
Definition template.h:215
IV_PAIR item
Definition template.h:281
#define VALUE
Definition template.h:51
#define INITIAL_BLOCK_INDEX_BITS
Definition template.h:78
#define DC_TRAIT_ARENA(SELF)
Definition trait.h:5
#define TEMPLATE_ERROR(...)
With the user provided name, even in nested templates.
Definition def.h:56
#define SELF
Definition def.h:52
#define DC_DEBUG(DEBUG_FN, DEBUG_PTR)
Definition dump.h:92
static DC_PUBLIC void dc_debug_fmt_print(dc_debug_fmt fmt, FILE *stream, const char *format,...)
Definition fmt.h:32
static DC_PUBLIC dc_debug_fmt dc_debug_fmt_scope_end(dc_debug_fmt fmt)
Definition fmt.h:57
static DC_PUBLIC dc_debug_fmt dc_debug_fmt_scope_begin(dc_debug_fmt fmt)
Definition fmt.h:50
static DC_PUBLIC dc_gdb_marker dc_gdb_marker_new()
Definition gdb_marker.h:8
static DC_PUBLIC void dc_memory_tracker_set(dc_memory_tracker_level level, dc_memory_tracker_capability cap, const volatile void *addr, size_t size)
@ DC_MEMORY_TRACKER_LVL_CONTAINER
@ DC_MEMORY_TRACKER_CAP_WRITE
static DC_PUBLIC void mutation_tracker_mutate(mutation_tracker *self)
static DC_PUBLIC void mutation_version_check(mutation_version const *self)
static DC_PUBLIC mutation_tracker mutation_tracker_new()
static DC_PUBLIC mutation_version mutation_tracker_get(mutation_tracker const *self)
#define DC_PUBLIC
Definition namespace.h:25
#define NS(pre, post)
Definition namespace.h:14
#define DC_EXPAND_STRING(NAME)
Definition namespace.h:6
#define DC_ASSERT(expr,...)
Definition panic.h:37
#define DC_STATIC_ASSERT
Definition panic.h:22
#define DC_ASSUME(expr,...)
Definition panic.h:57
VALUE * value
Definition template.h:340
INDEX_TYPE block_current
Definition template.h:82
mutation_tracker iterator_invalidation_tracker
Definition template.h:87
INDEX_TYPE block_current_exclusive_end
Definition template.h:83
BLOCK_VECTOR blocks
Definition template.h:46
dc_gdb_marker derive_c_arena_blocks
Definition template.h:107
VALUE value
Definition template.h:78
Debug format helpers for debug printin data structures.
Definition fmt.h:11
tracks a specific version of a value, so that this can be compared later to check modification For ex...
static DC_INTERNAL void clone_from(SELF const *from_slot, SELF *to_slot)
Definition template.h:94
static DC_INTERNAL void set_empty(SELF *slot, SLOT_INDEX_TYPE next_free)
Definition template.h:73
static DC_INTERNAL void fill(SELF *slot, SLOT_VALUE value)
Definition template.h:88
static DC_PUBLIC FILE * stream(SELF *self)
Definition template.h:108