30#if !defined(SKIP_INCLUDES)
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")
45 #if !defined DC_PLACEHOLDERS
46TEMPLATE_ERROR(
"The value type to place in the arena must be defined")
52 #define VALUE_DELETE value_delete
54 #define VALUE_CLONE value_clone
56 #define VALUE_DEBUG value_debug
62#if !defined VALUE_DELETE
63 #define VALUE_DELETE DC_NO_DELETE
66#if !defined VALUE_CLONE
67 #define VALUE_CLONE DC_COPY_CLONE
70#if !defined VALUE_DEBUG
71 #define VALUE_DEBUG DC_DEFAULT_DEBUG
77#if !defined INITIAL_BLOCK_INDEX_BITS
78 #define INITIAL_BLOCK_INDEX_BITS 8
82 "INITIAL_BLOCK_INDEX_BITS must be less than INDEX_BITS");
84 "INITIAL_BLOCK_INDEX_BITS must be greater than zero");
91#define SLOT NS(NAME, slot)
93#define SLOT_INDEX_TYPE INDEX_TYPE
94#define SLOT_VALUE VALUE
95#define SLOT_VALUE_CLONE VALUE_CLONE
96#define SLOT_VALUE_DELETE VALUE_DELETE
97#define INTERNAL_NAME SLOT
103 INDEX_TYPE free_list;
117#define INVARIANT_CHECK(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);
124 uint8_t initial_block = 0;
125 size_t initial_block_items =
127 SLOT* initial_block_slots =
131 .free_list = INDEX_NONE,
133 .alloc_ref = alloc_ref,
136 .block_current_exclusive_end = 0,
137 .block_current = initial_block,
150 "Arena is full, cannot insert {count=%lu, max_index=%lu, value=%s}",
155 if (self->free_list != INDEX_NONE) {
156 INDEX_TYPE free_index = self->free_list;
160 SLOT* free_slot = &self->blocks[block][offset];
162 DC_ASSUME(!free_slot->present,
"The free list should only contain free slots");
163 self->free_list = free_slot->next_free;
169 return (INDEX){.index = free_index};
172 if (self->block_current_exclusive_end ==
174 DC_ASSUME(self->block_current <
sizeof(self->blocks) /
sizeof(
SLOT*));
176 self->block_current++;
182 self->blocks[self->block_current] = block_slots;
183 self->block_current_exclusive_end = 0;
186 size_t offset = self->block_current_exclusive_end;
187 NS(
SLOT,
fill)(&self->blocks[self->block_current][offset], value);
191 self->block_current_exclusive_end++;
194 return (INDEX){.index = new_index};
201 if (block > self->block_current) {
207 if (block == self->block_current && offset >= self->block_current_exclusive_end) {
211 SLOT* slot = &self->blocks[block][offset];
212 if (!slot->present) {
221 DC_ASSERT(value,
"Cannot read item, index not found {index=%lu}", (
size_t)index.index);
231 DC_ASSERT(value,
"Cannot write item, index not found {index=%lu}", (
size_t)index.index);
244 .free_list = self->free_list,
245 .count = self->count,
246 .alloc_ref = self->alloc_ref,
249 .block_current_exclusive_end = self->block_current_exclusive_end,
250 .block_current = self->block_current,
254 for (
size_t block_index = 0; block_index <= self->block_current; block_index++) {
258 new_self.
blocks[block_index] = block_slots;
260 size_t const to_offset =
261 block_index == self->block_current ? self->block_current_exclusive_end : block_items;
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];
278 if (block > self->block_current) {
284 if (block == self->block_current && offset >= self->block_current_exclusive_end) {
288 SLOT* slot = &self->blocks[block][offset];
290 *destination = slot->
value;
293 self->free_list = index.index;
306 "Failed to remove item, index not found {index=%lu}", (
size_t)index.index);
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
318 for (
size_t offset = 0; offset < to_offset; offset++) {
319 SLOT* slot = &self->blocks[block][offset];
328 self->blocks[block], block_size);
333#define IV_PAIR_CONST NS(SELF, iv_const)
341 .index = {.index = INDEX_NONE},
346#define ITER_CONST NS(SELF, iter_const)
350 return item->value == NULL;
355 INDEX_TYPE next_index;
363 while (iter->next_index < MAX_INDEX) {
368 if ((block == iter->arena->block_current &&
369 offset >= iter->arena->block_current_exclusive_end) ||
370 (block > iter->arena->block_current)) {
374 SLOT* slot = &iter->arena->blocks[block][offset];
377 .index = (INDEX){.index = iter->next_index},
378 .value = &slot->
value,
395 INDEX_TYPE search_index = iter->next_index;
396 while (search_index < MAX_INDEX) {
401 if ((block == iter->arena->block_current &&
402 offset >= iter->arena->block_current_exclusive_end) ||
403 (block > iter->arena->block_current)) {
407 SLOT* slot = &iter->arena->blocks[block][offset];
433 if (self->free_list == INDEX_NONE) {
445 for (
size_t block = 0; block <= self->block_current; block++) {
450 size_t const to_offset =
451 block == self->block_current ? self->block_current_exclusive_end : capacity;
460 for (
size_t offset = 0; offset < to_offset; offset++) {
461 SLOT* slot = &self->blocks[block][offset];
496#define IV_PAIR NS(SELF, iv)
504 .index = {.index = INDEX_NONE},
509#define ITER NS(SELF, iter)
516 INDEX_TYPE next_index;
524 while (iter->next_index < MAX_INDEX) {
529 if ((block == iter->arena->block_current &&
530 offset >= iter->arena->block_current_exclusive_end) ||
531 (block > iter->arena->block_current)) {
535 SLOT* slot = &iter->arena->blocks[block][offset];
538 .index = (INDEX){.index = iter->next_index},
539 .value = &slot->
value,
556 INDEX_TYPE search_index = iter->next_index;
557 while (search_index < MAX_INDEX) {
562 if ((block == iter->arena->block_current &&
563 offset >= iter->arena->block_current_exclusive_end) ||
564 (block > iter->arena->block_current)) {
568 SLOT* slot = &iter->arena->blocks[block][offset];
591#undef INVARIANT_CHECK
593#undef INITIAL_BLOCK_INDEX_BITS
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_uninit(SELF *self, size_t size)
#define DC_ARENA_GEO_MAX_NUM_BLOCKS(INDEX_BITS, INITIAL_BLOCK_INDEX_BITS)
#define DC_ARENA_GEO_BLOCK_TO_SIZE(BLOCK, INITIAL_BLOCK_INDEX_BITS)
#define DC_ARENA_GEO_INDEX_TO_OFFSET(IDX, BLOCK, INITIAL_BLOCK_INDEX_BITS)
#define DC_ARENA_GEO_BLOCK_OFFSET_TO_INDEX(BLOCK, OFFSET, INITIAL_BLOCK_INDEX_BITS)
#define DC_ARENA_GEO_INDEX_TO_BLOCK(IDX, INITIAL_BLOCK_INDEX_BITS)
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 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 INITIAL_BLOCK_INDEX_BITS
#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_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_EXPAND_STRING(NAME)
#define DC_ASSERT(expr,...)
#define DC_ASSUME(expr,...)
mutation_tracker iterator_invalidation_tracker
INDEX_TYPE block_current_exclusive_end
dc_gdb_marker derive_c_arena_blocks
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_PUBLIC FILE * stream(SELF *self)