4#if !defined(SKIP_INCLUDES)
11#if !defined INDEX_BITS
12 #if !defined DC_PLACEHOLDERS
13TEMPLATE_ERROR(
"The number of bits (8,16,32,64) to use for the arena's key")
19 #if !defined DC_PLACEHOLDERS
20TEMPLATE_ERROR(
"The value type to place in the arena must be defined")
26 #define VALUE_DELETE value_delete
28 #define VALUE_CLONE value_clone
30 #define VALUE_DEBUG value_debug
36#if !defined VALUE_DELETE
37 #define VALUE_DELETE DC_NO_DELETE
40#if !defined VALUE_CLONE
41 #define VALUE_CLONE DC_COPY_CLONE
44#if !defined VALUE_DEBUG
45 #define VALUE_DEBUG DC_DEFAULT_DEBUG
51#define CHECK_ACCESS_INDEX(self, index) ((index).index < (self)->exclusive_end)
55#define RESIZE_FACTOR 2
60#define SLOT NS(NAME, slot)
62#define SLOT_INDEX_TYPE INDEX_TYPE
63#define SLOT_VALUE VALUE
64#define SLOT_VALUE_CLONE VALUE_CLONE
65#define SLOT_VALUE_CLONE VALUE_CLONE
66#define SLOT_VALUE_DELETE VALUE_DELETE
67#define INTERNAL_NAME SLOT
90#define INVARIANT_CHECK(self) \
92 DC_ASSUME((self)->count <= (self)->capacity); \
93 DC_ASSUME((self)->exclusive_end >= (self)->count); \
94 DC_ASSUME((self)->count <= MAX_INDEX);
97 DC_ASSERT(items > 0,
"Cannot create arena with capacity for 0 items {items=%lu}",
100 DC_ASSERT(capacity <= CAPACITY_EXCLUSIVE_UPPER,
101 "Index capacity too large {capacity=%lu, max_capacity=%lu}", (
size_t)capacity,
102 (
size_t)CAPACITY_EXCLUSIVE_UPPER);
105 for (INDEX_TYPE index = 0; index < capacity; index++) {
111 .capacity = (INDEX_TYPE)capacity,
112 .free_list = INDEX_NONE,
115 .alloc_ref = alloc_ref,
124 "Arena is full, cannot insert {count=%lu, max_index=%lu, value=%s}",
128 if (self->free_list != INDEX_NONE) {
129 INDEX_TYPE free_index = self->free_list;
130 SLOT* slot = &self->slots[free_index];
133 self->free_list = slot->next_free;
137 return (INDEX){.index = free_index};
140 if (self->exclusive_end == self->capacity) {
142 "Cannot increase capacity for new item {capacity=%lu, max_capacity=%lu, item=%s}",
143 (
size_t)self->capacity, (
size_t)CAPACITY_EXCLUSIVE_UPPER,
145 size_t old_size = self->capacity *
sizeof(
SLOT);
148 self->capacity *
sizeof(
SLOT));
149 self->slots = new_alloc;
151 for (
size_t index = self->exclusive_end; index < self->capacity; index++) {
156 INDEX_TYPE new_index = (INDEX_TYPE)self->exclusive_end;
157 SLOT* slot = &self->slots[new_index];
161 self->exclusive_end++;
162 return (INDEX){.index = new_index};
170 SLOT* slot = &self->slots[index.index];
171 if (!slot->present) {
179 DC_ASSERT(value,
"Cannot write item, index not found {index=%lu}", (
size_t)index.index);
188 SLOT* slot = &self->slots[index.index];
189 if (!slot->present) {
197 DC_ASSERT(value,
"Cannot read item, index not found {index=%lu}", (
size_t)index.index);
205 for (INDEX_TYPE index = 0; index < self->exclusive_end; index++) {
211 .capacity = self->capacity,
212 .free_list = self->free_list,
213 .exclusive_end = self->exclusive_end,
214 .count = self->count,
215 .alloc_ref = self->alloc_ref,
228 if (self->capacity == CAPACITY_EXCLUSIVE_UPPER) {
229 if (self->free_list == INDEX_NONE) {
246 SLOT* entry = &self->slots[index.index];
247 if (entry->present) {
248 *destination = entry->
value;
252 self->free_list = index.index;
265 "Failed to remove item, index not found {index=%lu}", (
size_t)index.index);
269#define IV_PAIR NS(SELF, iv)
277 return (
IV_PAIR){.index = (INDEX){.index = INDEX_NONE}, .value = NULL};
280#define ITER NS(SELF, iter)
287 INDEX_TYPE next_index;
297 return iter->next_index == INDEX_NONE || iter->next_index >= iter->arena->exclusive_end;
304 while (iter->next_index < INDEX_NONE && iter->next_index < iter->arena->exclusive_end) {
306 .index = (INDEX){.index = iter->next_index},
307 .value = &iter->arena->slots[iter->next_index].value,
312 while (iter->next_index < INDEX_NONE && iter->next_index < iter->arena->exclusive_end &&
313 !iter->arena->slots[iter->next_index].present) {
317 if (result.
value && result.
value == &iter->arena->slots[result.
index.index].value &&
318 iter->arena->slots[result.
index.index].present) {
328 INDEX_TYPE index = 0;
329 while (index < INDEX_NONE && index < self->exclusive_end && !self->slots[index].present) {
355#define IV_PAIR_CONST NS(SELF, iv_const)
363 return (
IV_PAIR_CONST){.index = (INDEX){.index = INDEX_NONE}, .value = NULL};
366#define ITER_CONST NS(SELF, iter_const)
372 return item->value == NULL;
377 INDEX_TYPE next_index;
385 return iter->next_index == INDEX_NONE || iter->next_index >= iter->arena->exclusive_end;
392 while (iter->next_index < INDEX_NONE && iter->next_index < iter->arena->exclusive_end) {
394 .index = (INDEX){.index = iter->next_index},
395 .value = &iter->arena->slots[iter->next_index].value,
398 while (iter->next_index != INDEX_NONE && iter->next_index < iter->arena->exclusive_end &&
399 !iter->arena->slots[iter->next_index].present) {
403 if (result.
value && iter->arena->slots[result.
index.index].present) {
413 INDEX_TYPE index = 0;
414 while (index < INDEX_NONE && index < self->exclusive_end && !self->slots[index].present) {
466#undef INVARIANT_CHECK
469#undef CHECK_ACCESS_INDEX
static DC_PUBLIC void deallocate(SELF *self, void *ptr, size_t size)
static DC_PUBLIC void debug(SELF const *self, dc_debug_fmt fmt, FILE *stream)
static DC_PUBLIC void * allocate_zeroed(SELF *self, size_t size)
static DC_PUBLIC void * reallocate(SELF *self, void *ptr, size_t old_size, size_t new_size)
static DC_PUBLIC VALUE const * try_read(SELF const *self, INDEX index)
static DC_PUBLIC VALUE * try_write(SELF *self, INDEX index)
static DC_PUBLIC IV_PAIR iv_empty()
static DC_PUBLIC const size_t max_entries
#define INVARIANT_CHECK(self)
static DC_PUBLIC IV_PAIR next(ITER *iter)
static DC_PUBLIC INDEX insert(SELF *self, VALUE value)
static DC_PUBLIC bool empty(ITER const *iter)
static DC_PUBLIC bool full(SELF const *self)
static DC_PUBLIC VALUE const * read(SELF const *self, INDEX index)
static DC_PUBLIC bool try_remove(SELF *self, INDEX index, VALUE *destination)
static DC_PUBLIC VALUE * write(SELF *self, INDEX index)
static DC_PUBLIC bool empty_item(IV_PAIR const *item)
static DC_PUBLIC VALUE remove(SELF *self, INDEX index)
static DC_PUBLIC ITER get_iter(SELF *self)
static DC_PUBLIC IV_PAIR_CONST iv_const_empty()
static DC_PUBLIC ITER_CONST get_iter_const(SELF const *self)
static DC_PUBLIC size_t size(SELF const *self)
static DC_PUBLIC SELF clone(SELF const *self)
#define CHECK_ACCESS_INDEX(self, index)
static DC_PUBLIC SELF new_with_capacity_for(INDEX_TYPE items, ref alloc_ref)
#define DC_TRAIT_ARENA(SELF)
#define TEMPLATE_ERROR(...)
With the user provided name, even in nested templates.
#define DC_DEBUG(DEBUG_FN, DEBUG_PTR)
static DC_PUBLIC void dc_debug_fmt_print(dc_debug_fmt fmt, FILE *stream, const char *format,...)
static DC_PUBLIC dc_debug_fmt dc_debug_fmt_scope_end(dc_debug_fmt fmt)
static DC_PUBLIC dc_debug_fmt dc_debug_fmt_scope_begin(dc_debug_fmt fmt)
static DC_PUBLIC dc_gdb_marker dc_gdb_marker_new()
static DC_INLINE DC_CONST size_t dc_math_next_power_of_2(size_t x)
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_EXPAND_STRING(NAME)
#define DC_ASSERT(expr,...)
#define DC_ASSUME(expr,...)
mutation_tracker iterator_invalidation_tracker
dc_gdb_marker derive_c_arena_basic
Debug format helpers for debug printin data structures.
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)
static DC_INTERNAL void set_empty(SELF *slot, SLOT_INDEX_TYPE next_free)
static DC_INTERNAL void fill(SELF *slot, SLOT_VALUE value)
static DC_INTERNAL void memory_tracker_empty(SELF const *slot)
static DC_PUBLIC FILE * stream(SELF *self)