Derive-C
Loading...
Searching...
No Matches
template.h File Reference

Go to the source code of this file.

Data Structures

struct  value_t
struct  SELF
 An allocator that prints to stdout when it allocates or frees memory. More...
struct  IV_PAIR
struct  ITER
struct  IV_PAIR_CONST
struct  ITER_CONST

Macros

#define INDEX_BITS   32
 A vector-backed arena, with support for small indices.
#define VALUE   value_t
#define VALUE_DELETE   value_delete
#define VALUE_CLONE   value_clone
#define VALUE_DEBUG   value_debug
#define CHECK_ACCESS_INDEX(self, index)
#define RESIZE_FACTOR   2
#define SLOT   NS(NAME, slot)
#define SLOT_INDEX_TYPE   INDEX_TYPE
#define SLOT_VALUE   VALUE
#define SLOT_VALUE_CLONE   VALUE_CLONE
#define SLOT_VALUE_CLONE   VALUE_CLONE
#define SLOT_VALUE_DELETE   VALUE_DELETE
#define INTERNAL_NAME   SLOT
#define INVARIANT_CHECK(self)
#define IV_PAIR   NS(SELF, iv)
#define ITER   NS(SELF, iter)
#define IV_PAIR_CONST   NS(SELF, iv_const)
#define ITER_CONST   NS(SELF, iter_const)

Typedefs

typedef IV_PAIR item

Functions

static void VALUE_DELETE (value_t *self)
static value_t VALUE_CLONE (value_t const *self)
static void VALUE_DEBUG (VALUE const *self, dc_debug_fmt fmt, FILE *stream)
 DC_STATIC_ASSERT (sizeof(VALUE), "VALUE must be a non-zero sized type")
static SELF new_with_capacity_for (INDEX_TYPE items, ALLOC *alloc)
static INDEX insert (SELF *self, VALUE value)
static VALUEtry_write (SELF *self, INDEX index)
static VALUEwrite (SELF *self, INDEX index)
static VALUE const * try_read (SELF const *self, INDEX index)
static VALUE const * read (SELF const *self, INDEX index)
static SELF clone (SELF const *self)
static INDEX_TYPE size (SELF const *self)
static bool full (SELF const *self)
static bool try_remove (SELF *self, INDEX index, VALUE *destination)
static VALUE remove (SELF *self, INDEX index)
static IV_PAIR iv_empty ()
static bool empty_item (IV_PAIR const *item)
static bool empty (ITER const *iter)
static IV_PAIR next (ITER *iter)
static ITER get_iter (SELF *self)
static void delete (SELF *self)
static IV_PAIR_CONST iv_const_empty ()
static bool empty_item (IV_PAIR_CONST const *item)
static bool empty (ITER_CONST const *iter)
static IV_PAIR_CONST next (ITER_CONST *iter)
static ITER_CONST get_iter_const (SELF const *self)
static void debug (SELF const *self, dc_debug_fmt fmt, FILE *stream)
 DC_TRAIT_ARENA (SELF)

Variables

static const size_t max_entries = MAX_INDEX

Macro Definition Documentation

◆ CHECK_ACCESS_INDEX

#define CHECK_ACCESS_INDEX ( self,
index )
Value:
((index).index < (self)->exclusive_end)

Definition at line 51 of file template.h.

◆ INDEX_BITS

#define INDEX_BITS   32

A vector-backed arena, with support for small indices.

Definition at line 15 of file template.h.

◆ INTERNAL_NAME

#define INTERNAL_NAME   SLOT

Definition at line 67 of file template.h.

◆ INVARIANT_CHECK

#define INVARIANT_CHECK ( self)
Value:
DC_ASSUME(self); \
DC_ASSUME((self)->count <= (self)->capacity); \
DC_ASSUME((self)->exclusive_end >= (self)->count); \
DC_ASSUME((self)->count <= MAX_INDEX);
static size_t capacity()
Definition template.h:66
#define DC_ASSUME(expr,...)
Definition panic.h:56

Definition at line 90 of file template.h.

90#define INVARIANT_CHECK(self) \
91 DC_ASSUME(self); \
92 DC_ASSUME((self)->count <= (self)->capacity); \
93 DC_ASSUME((self)->exclusive_end >= (self)->count); \
94 DC_ASSUME((self)->count <= MAX_INDEX);

◆ ITER

#define ITER   NS(SELF, iter)

Definition at line 282 of file template.h.

◆ ITER_CONST

#define ITER_CONST   NS(SELF, iter_const)

Definition at line 368 of file template.h.

◆ IV_PAIR

#define IV_PAIR   NS(SELF, iv)

Definition at line 271 of file template.h.

◆ IV_PAIR_CONST

#define IV_PAIR_CONST   NS(SELF, iv_const)

Definition at line 357 of file template.h.

◆ RESIZE_FACTOR

#define RESIZE_FACTOR   2

Definition at line 55 of file template.h.

◆ SLOT

#define SLOT   NS(NAME, slot)

Definition at line 60 of file template.h.

◆ SLOT_INDEX_TYPE

#define SLOT_INDEX_TYPE   INDEX_TYPE

Definition at line 62 of file template.h.

◆ SLOT_VALUE

#define SLOT_VALUE   VALUE

Definition at line 63 of file template.h.

◆ SLOT_VALUE_CLONE [1/2]

#define SLOT_VALUE_CLONE   VALUE_CLONE

Definition at line 64 of file template.h.

◆ SLOT_VALUE_CLONE [2/2]

#define SLOT_VALUE_CLONE   VALUE_CLONE

Definition at line 64 of file template.h.

◆ SLOT_VALUE_DELETE

#define SLOT_VALUE_DELETE   VALUE_DELETE

Definition at line 66 of file template.h.

◆ VALUE

#define VALUE   value_t

Definition at line 25 of file template.h.

◆ VALUE_CLONE

#define VALUE_CLONE   value_clone

Definition at line 28 of file template.h.

◆ VALUE_DEBUG

#define VALUE_DEBUG   value_debug

Definition at line 30 of file template.h.

◆ VALUE_DELETE

#define VALUE_DELETE   value_delete

Definition at line 26 of file template.h.

Typedef Documentation

◆ item

typedef ITEM const * item
Examples
container/vector/dynamic.c, and container/vector/static.c.

Definition at line 283 of file template.h.

Function Documentation

◆ clone()

SELF clone ( SELF const * self)
static

Definition at line 195 of file template.h.

195 {
196 INVARIANT_CHECK(self);
197 SLOT* slots = (SLOT*)NS(ALLOC, calloc)(self->alloc, self->capacity, sizeof(SLOT));
198 DC_ASSERT(slots);
199
200 for (INDEX_TYPE index = 0; index < self->exclusive_end; index++) {
201 if (self->slots[index].present) {
202 NS(SLOT, memory_tracker_present)(&slots[index]);
203 slots[index].present = true;
204 slots[index].value = VALUE_CLONE(&self->slots[index].value);
205 } else {
206 NS(SLOT, memory_tracker_empty)(&slots[index]);
207 slots[index].present = false;
208 slots[index].next_free = self->slots[index].next_free;
209 }
210 }
211
212 return (SELF){
213 .slots = slots,
214 .capacity = self->capacity,
215 .free_list = self->free_list,
216 .exclusive_end = self->exclusive_end,
217 .count = self->count,
218 .alloc = self->alloc,
219 .derive_c_arena_basic = dc_gdb_marker_new(),
220 .iterator_invalidation_tracker = mutation_tracker_new(),
221 };
222}
static void * calloc(SELF *self, size_t count, size_t size)
Definition template.h:34
#define ALLOC
Definition template.h:64
#define SLOT
Definition template.h:63
#define INVARIANT_CHECK(self)
Definition template.h:88
#define VALUE_CLONE
Definition template.h:37
#define INDEX_TYPE
Definition template.h:74
static dc_gdb_marker dc_gdb_marker_new()
Definition gdb_marker.h:7
static mutation_tracker mutation_tracker_new()
#define NS(pre, post)
Definition namespace.h:4
#define DC_ASSERT(expr,...)
Definition panic.h:36
#define SELF
Definition def.h:52
VALUE value
Definition template.h:78
static void memory_tracker_present(SELF const *slot)
Definition template.h:68
static void memory_tracker_empty(SELF const *slot)
Definition template.h:53

◆ DC_STATIC_ASSERT()

DC_STATIC_ASSERT ( sizeof(VALUE) ,
"VALUE must be a non-zero sized type"  )

◆ DC_TRAIT_ARENA()

DC_TRAIT_ARENA ( SELF )

◆ debug()

void debug ( SELF const * self,
dc_debug_fmt fmt,
FILE * stream )
static

Definition at line 425 of file template.h.

425 {
426 fprintf(stream, EXPAND_STRING(SELF) "@%p {\n", self);
427 fmt = dc_debug_fmt_scope_begin(fmt);
428 dc_debug_fmt_print(fmt, stream, "capacity: %lu,\n", self->capacity);
429 dc_debug_fmt_print(fmt, stream, "count: %lu,\n", self->count);
430 dc_debug_fmt_print(fmt, stream, "slots: %p,\n", self->slots);
431
432 dc_debug_fmt_print(fmt, stream, "alloc: ");
433 NS(ALLOC, debug)(self->alloc, fmt, stream);
434 fprintf(stream, ",\n");
435
436 dc_debug_fmt_print(fmt, stream, "items: [");
437 fmt = dc_debug_fmt_scope_begin(fmt);
438
439 ITER_CONST iter = NS(SELF, get_iter_const)(self);
441 item = NS(ITER_CONST, next)(&iter)) {
442 dc_debug_fmt_print(fmt, stream, "{\n");
443 fmt = dc_debug_fmt_scope_begin(fmt);
444
445 dc_debug_fmt_print(fmt, stream, "key: ");
446 NS(INDEX, debug)(&item.index, fmt, stream);
447 fprintf(stream, ",\n");
448
449 dc_debug_fmt_print(fmt, stream, "value: ");
450 VALUE_DEBUG(item.value, fmt, stream);
451 fprintf(stream, ",\n");
452
453 fmt = dc_debug_fmt_scope_end(fmt);
454 dc_debug_fmt_print(fmt, stream, "},\n");
455 }
456
457 fmt = dc_debug_fmt_scope_end(fmt);
458 dc_debug_fmt_print(fmt, stream, "],\n");
459 fmt = dc_debug_fmt_scope_end(fmt);
460 dc_debug_fmt_print(fmt, stream, "}");
461}
static void debug(SELF const *self, dc_debug_fmt fmt, FILE *stream)
Definition template.h:62
static ITER_CONST get_iter_const(SELF const *self)
Definition template.h:449
#define VALUE_DEBUG
Definition template.h:39
static IV_PAIR next(ITER *iter)
Definition template.h:352
static bool empty_item(IV_PAIR const *item)
Definition template.h:344
#define IV_PAIR_CONST
Definition template.h:399
#define ITER_CONST
Definition template.h:398
IV_PAIR item
Definition template.h:283
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
#define EXPAND_STRING(NAME)
Definition namespace.h:8
static FILE * stream(SELF *self)
Opens a file for.
Definition template.h:107

◆ delete()

void delete ( SELF * self)
static

Definition at line 342 of file template.h.

342 {
343 INVARIANT_CHECK(self);
344 ITER iter = NS(SELF, get_iter)(self);
345
346 for (IV_PAIR entry = NS(ITER, next)(&iter); !NS(ITER, empty_item)(&entry);
347 entry = NS(ITER, next)(&iter)) {
348 VALUE_DELETE(entry.value);
349 }
350
351 NS(ALLOC, free)(self->alloc, self->slots);
352}
static void free(SELF *self, void *ptr)
Definition template.h:56
static ITER get_iter(SELF *self)
Definition template.h:370
#define IV_PAIR
Definition template.h:321
#define ITER
Definition template.h:320
#define VALUE_DELETE
Definition template.h:35
SLOT * slots
Definition template.h:71
ALLOC * alloc
Definition template.h:71

◆ empty() [1/2]

bool empty ( ITER const * iter)
static

Definition at line 293 of file template.h.

293 {
294 DC_ASSUME(iter);
295 mutation_version_check(&iter->version);
296 // JUSTIFY: If no entries are left, then the previous '.._next' call moved
297 // the index to the exclusive end
298 // NOTE: `index + 1 > exclusive_end` implies `index >= exclusive_end`
299 return iter->next_index == INDEX_NONE || iter->next_index >= iter->arena->exclusive_end;
300}
static void mutation_version_check(mutation_version const *self)

◆ empty() [2/2]

bool empty ( ITER_CONST const * iter)
static

Definition at line 382 of file template.h.

382 {
383 DC_ASSUME(iter);
384 mutation_version_check(&iter->version);
385 return iter->next_index == INDEX_NONE || iter->next_index >= iter->arena->exclusive_end;
386}

◆ empty_item() [1/2]

bool empty_item ( IV_PAIR const * item)
static

Definition at line 285 of file template.h.

285{ return item->value == NULL; }

◆ empty_item() [2/2]

bool empty_item ( IV_PAIR_CONST const * item)
static

Definition at line 373 of file template.h.

373{ return item->value == NULL; }

◆ full()

bool full ( SELF const * self)
static

Definition at line 229 of file template.h.

229 {
230 INVARIANT_CHECK(self);
231 if (self->capacity == CAPACITY_EXCLUSIVE_UPPER) {
232 if (self->free_list == INDEX_NONE) {
233 return true;
234 }
235 }
236 return false;
237}

◆ get_iter()

ITER get_iter ( SELF * self)
static

Definition at line 328 of file template.h.

328 {
329 INVARIANT_CHECK(self);
330 INDEX_TYPE index = 0;
331 while (index < INDEX_NONE && index < self->exclusive_end && !self->slots[index].present) {
332 index++;
333 }
334
335 return (ITER){
336 .arena = self,
337 .next_index = index,
339 };
340}
static mutation_version mutation_tracker_get(mutation_tracker const *self)
mutation_tracker iterator_invalidation_tracker
Definition template.h:85

◆ get_iter_const()

ITER_CONST get_iter_const ( SELF const * self)
static

Definition at line 411 of file template.h.

411 {
412 INVARIANT_CHECK(self);
413 INDEX_TYPE index = 0;
414 while (index < INDEX_NONE && index < self->exclusive_end && !self->slots[index].present) {
415 index++;
416 }
417
418 return (ITER_CONST){
419 .arena = self,
420 .next_index = index,
421 .version = mutation_tracker_get(&self->iterator_invalidation_tracker),
422 };
423}

◆ insert()

INDEX insert ( SELF * self,
VALUE value )
static

Definition at line 119 of file template.h.

119 {
120 INVARIANT_CHECK(self);
121 DC_ASSERT(self->count < MAX_INDEX);
122
124 if (self->free_list != INDEX_NONE) {
125 INDEX_TYPE free_index = self->free_list;
126 SLOT* slot = &self->slots[free_index];
127 DC_ASSUME(!slot->present);
128 self->free_list = slot->next_free;
129 slot->present = true;
131 slot->value = value;
132 self->count++;
133 return (INDEX){.index = free_index};
134 }
135
136 if (self->exclusive_end == self->capacity) {
137 DC_ASSERT(self->capacity <= (CAPACITY_EXCLUSIVE_UPPER / RESIZE_FACTOR));
138 self->capacity *= RESIZE_FACTOR;
139 SLOT* new_alloc =
140 (SLOT*)NS(ALLOC, realloc)(self->alloc, self->slots, self->capacity * sizeof(SLOT));
141 DC_ASSERT(new_alloc);
142 self->slots = new_alloc;
143
144 for (size_t index = self->exclusive_end; index < self->capacity; index++) {
145 NS(SLOT, memory_tracker_empty)(&self->slots[index]);
146 }
147 }
148
149 INDEX_TYPE new_index = self->exclusive_end;
150 SLOT* slot = &self->slots[new_index];
151 slot->present = true;
153 slot->value = value;
154 self->count++;
155 self->exclusive_end++;
156 return (INDEX){.index = new_index};
157}
static void * realloc(SELF *self, void *ptr, size_t size)
Definition template.h:45
#define RESIZE_FACTOR
Definition template.h:55
static void mutation_tracker_mutate(mutation_tracker *self)
size_t capacity
Definition template.h:72
INDEX_TYPE free_list
Definition template.h:77
size_t exclusive_end
Definition template.h:79
size_t count
Definition template.h:76

◆ iv_const_empty()

IV_PAIR_CONST iv_const_empty ( )
static

Definition at line 364 of file template.h.

364 {
365 return (IV_PAIR_CONST){.index = (INDEX){.index = INDEX_NONE}, .value = NULL};
366}

◆ iv_empty()

IV_PAIR iv_empty ( )
static

Definition at line 278 of file template.h.

278 {
279 return (IV_PAIR){.index = (INDEX){.index = INDEX_NONE}, .value = NULL};
280}

◆ new_with_capacity_for()

SELF new_with_capacity_for ( INDEX_TYPE items,
ALLOC * alloc )
static

Definition at line 96 of file template.h.

96 {
97 DC_ASSERT(items > 0);
98 size_t capacity = dc_math_next_power_of_2(items);
99 DC_ASSERT(capacity <= CAPACITY_EXCLUSIVE_UPPER);
100 SLOT* slots = (SLOT*)NS(ALLOC, calloc)(alloc, capacity, sizeof(SLOT));
101 DC_ASSERT(slots);
102
103 for (INDEX_TYPE index = 0; index < capacity; index++) {
104 NS(SLOT, memory_tracker_empty)(&slots[index]);
105 }
106
107 return (SELF){
108 .slots = slots,
109 .capacity = (INDEX_TYPE)capacity,
110 .free_list = INDEX_NONE,
111 .exclusive_end = 0,
112 .count = 0,
113 .alloc = alloc,
114 .derive_c_arena_basic = dc_gdb_marker_new(),
115 .iterator_invalidation_tracker = mutation_tracker_new(),
116 };
117}
static DC_INLINE DC_CONST size_t dc_math_next_power_of_2(size_t x)
Definition math.h:48

◆ next() [1/2]

IV_PAIR next ( ITER * iter)
static

Definition at line 302 of file template.h.

302 {
303 DC_ASSUME(iter);
305
306 while (iter->next_index < INDEX_NONE && iter->next_index < iter->arena->exclusive_end) {
307 IV_PAIR result = {
308 .index = (INDEX){.index = iter->next_index},
309 .value = &iter->arena->slots[iter->next_index].value,
310 };
311
312 iter->next_index++;
313 // advance to next present entry
314 while (iter->next_index < INDEX_NONE && iter->next_index < iter->arena->exclusive_end &&
315 !iter->arena->slots[iter->next_index].present) {
316 iter->next_index++;
317 }
318
319 if (result.value && result.value == &iter->arena->slots[result.index.index].value &&
320 iter->arena->slots[result.index.index].present) {
321 return result;
322 }
323 }
324
325 return NS(SELF, iv_empty)();
326}
static IV_PAIR iv_empty()
Definition template.h:341
INDEX_TYPE next_index
Definition template.h:325
mutation_version version
Definition template.h:326
SELF * arena
Definition template.h:324
VALUE * value
Definition template.h:338
INDEX index
Definition template.h:337

◆ next() [2/2]

IV_PAIR_CONST next ( ITER_CONST * iter)
static

Definition at line 388 of file template.h.

388 {
389 DC_ASSUME(iter);
391
392 while (iter->next_index < INDEX_NONE && iter->next_index < iter->arena->exclusive_end) {
393 IV_PAIR_CONST result = {
394 .index = (INDEX){.index = iter->next_index},
395 .value = &iter->arena->slots[iter->next_index].value,
396 };
397 iter->next_index++;
398 while (iter->next_index != INDEX_NONE && iter->next_index < iter->arena->exclusive_end &&
399 !iter->arena->slots[iter->next_index].present) {
400 iter->next_index++;
401 }
402
403 if (result.value && iter->arena->slots[result.index.index].present) {
404 return result;
405 }
406 }
407
408 return NS(SELF, iv_const_empty)();
409}
static IV_PAIR_CONST iv_const_empty()
Definition template.h:419
INDEX_TYPE next_index
Definition template.h:403
mutation_version version
Definition template.h:404
SELF const * arena
Definition template.h:402
VALUE const * value
Definition template.h:416

◆ read()

VALUE const * read ( SELF const * self,
INDEX index )
static

Definition at line 189 of file template.h.

189 {
190 VALUE const* value = NS(SELF, try_read)(self, index);
191 DC_ASSERT(value);
192 return value;
193}
#define VALUE
Definition template.h:31
static VALUE const * try_read(SELF const *self, INDEX index)
Definition template.h:180

◆ remove()

VALUE remove ( SELF * self,
INDEX index )
static

Definition at line 262 of file template.h.

262 {
263 INVARIANT_CHECK(self);
265
266 VALUE value;
267 DC_ASSERT(NS(SELF, try_remove)(self, index, &value));
268 return value;
269}
static bool try_remove(SELF *self, INDEX index, VALUE *destination)
Definition template.h:264

◆ size()

INDEX_TYPE size ( SELF const * self)
static

Definition at line 224 of file template.h.

224 {
225 INVARIANT_CHECK(self);
226 return self->count;
227}

◆ try_read()

VALUE const * try_read ( SELF const * self,
INDEX index )
static

Definition at line 177 of file template.h.

177 {
178 INVARIANT_CHECK(self);
179 if (!CHECK_ACCESS_INDEX(self, index)) {
180 return NULL;
181 }
182 SLOT* slot = &self->slots[index.index];
183 if (!slot->present) {
184 return NULL;
185 }
186 return &slot->value;
187}
#define CHECK_ACCESS_INDEX(self, index)
Definition template.h:51

◆ try_remove()

bool try_remove ( SELF * self,
INDEX index,
VALUE * destination )
static

Definition at line 241 of file template.h.

241 {
242 INVARIANT_CHECK(self);
244
245 if (!CHECK_ACCESS_INDEX(self, index)) {
246 return false;
247 }
248
249 SLOT* entry = &self->slots[index.index];
250 if (entry->present) {
251 *destination = entry->value;
252 entry->present = false;
254 entry->next_free = self->free_list;
255 self->free_list = index.index;
256 self->count--;
257 return true;
258 }
259 return false;
260}

◆ try_write()

VALUE * try_write ( SELF * self,
INDEX index )
static

Definition at line 159 of file template.h.

159 {
160 INVARIANT_CHECK(self);
161 if (!CHECK_ACCESS_INDEX(self, index)) {
162 return NULL;
163 }
164 SLOT* slot = &self->slots[index.index];
165 if (!slot->present) {
166 return NULL;
167 }
168 return &slot->value;
169}

◆ VALUE_CLONE()

value_t VALUE_CLONE ( value_t const * self)
static

◆ VALUE_DEBUG()

void VALUE_DEBUG ( VALUE const * self,
dc_debug_fmt fmt,
FILE * stream )
static

◆ VALUE_DELETE()

void VALUE_DELETE ( value_t * self)
static

◆ write()

VALUE * write ( SELF * self,
INDEX index )
static

Definition at line 171 of file template.h.

171 {
172 VALUE* value = NS(SELF, try_write)(self, index);
173 DC_ASSERT(value);
174 return value;
175}
static VALUE * try_write(SELF *self, INDEX index)
Definition template.h:205

Variable Documentation

◆ max_entries

const size_t max_entries = MAX_INDEX
static

Definition at line 239 of file template.h.