30#if !defined(SKIP_INCLUDES)
37#if !defined INDEX_BITS
38 #if !defined PLACEHOLDERS
39TEMPLATE_ERROR(
"The number of bits (8,16,32,64) to use for the arena's key")
45 #if !defined 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_CLONE VALUE_CLONE
97#define SLOT_VALUE_DELETE VALUE_DELETE
98#define INTERNAL_NAME SLOT
120 for (uint8_t block_index = 0; block_index <= self->block_current; block_index++) {
122 block_index == self->block_current
123 ? self->block_current_exclusive_end
125 for (
size_t offset = 0; offset < block_items; offset++) {
126 SLOT* slot = &self->blocks[block_index][offset];
136 (self->block_current_exclusive_end - 1);
138 &self->blocks[self->block_current][self->block_current_exclusive_end],
139 tail_slots *
sizeof(
SLOT));
142#define INVARIANT_CHECK(self) \
144 DC_ASSUME(DC_ARENA_GEO_BLOCK_TO_SIZE((self)->block_current, INITIAL_BLOCK_INDEX_BITS) >= \
145 (self)->block_current_exclusive_end); \
146 DC_ASSUME((self)->count <= MAX_INDEX);
149 uint8_t initial_block = 0;
150 size_t initial_block_items =
156 .free_list = INDEX_NONE,
161 .block_current_exclusive_end = 0,
162 .block_current = initial_block,
179 if (self->free_list != INDEX_NONE) {
184 SLOT* free_slot = &self->blocks[block][offset];
186 DC_ASSUME(!free_slot->present,
"The free list should only contain free slots");
187 self->free_list = free_slot->next_free;
189 free_slot->present =
true;
193 return (INDEX){.index = free_index};
196 if (self->block_current_exclusive_end ==
198 DC_ASSUME(self->block_current <
sizeof(self->blocks) /
sizeof(
SLOT*));
200 self->block_current++;
206 self->blocks[self->block_current] = block_slots;
207 self->block_current_exclusive_end = 0;
210 size_t offset = self->block_current_exclusive_end;
211 NS(
SLOT,
fill)(&self->blocks[self->block_current][offset], value);
215 self->block_current_exclusive_end++;
220 return (INDEX){.index = new_index};
227 if (block > self->block_current) {
233 if (block == self->block_current && offset >= self->block_current_exclusive_end) {
237 SLOT* slot = &self->blocks[block][offset];
238 if (!slot->present) {
268 .free_list = self->free_list,
269 .count = self->count,
270 .alloc = self->alloc,
273 .block_current_exclusive_end = self->block_current_exclusive_end,
274 .block_current = self->block_current,
278 for (
size_t block_index = 0; block_index <= self->block_current; block_index++) {
282 new_self.
blocks[block_index] = block_slots;
284 size_t const to_offset =
285 block_index == self->block_current ? self->block_current_exclusive_end : block_items;
287 for (
size_t offset = 0; offset < to_offset; offset++) {
288 SLOT* src_slot = &self->blocks[block_index][offset];
289 SLOT* dst_slot = &new_self.
blocks[block_index][offset];
291 if (src_slot->present) {
292 dst_slot->present =
true;
296 dst_slot->present =
false;
311 if (block > self->block_current) {
317 if (block == self->block_current && offset >= self->block_current_exclusive_end) {
321 SLOT* slot = &self->blocks[block][offset];
323 *destination = slot->
value;
324 slot->present =
false;
326 self->free_list = index.index;
345 for (uint8_t block = 0; block <= self->block_current; block++) {
346 size_t const to_offset = block == self->block_current
347 ? self->block_current_exclusive_end
350 for (
size_t offset = 0; offset < to_offset; offset++) {
351 SLOT* slot = &self->blocks[block][offset];
364#define IV_PAIR_CONST NS(SELF, iv_const)
372 .index = {.index = INDEX_NONE},
377#define ITER_CONST NS(SELF, iter_const)
392 while (iter->next_index < MAX_INDEX) {
397 if ((block == iter->arena->block_current &&
398 offset >= iter->arena->block_current_exclusive_end) ||
399 (block > iter->arena->block_current)) {
403 SLOT* slot = &iter->arena->blocks[block][offset];
406 .index = (INDEX){.index = iter->next_index},
407 .value = &slot->
value,
434 if (self->free_list == INDEX_NONE) {
446 for (
size_t block = 0; block <= self->block_current; block++) {
451 size_t const to_offset =
452 block == self->block_current ? self->block_current_exclusive_end :
capacity;
461 for (
size_t offset = 0; offset < to_offset; offset++) {
462 SLOT* slot = &self->blocks[block][offset];
497#define IV_PAIR NS(SELF, iv)
505 .index = {.index = INDEX_NONE},
510#define ITER NS(SELF, iter)
525 while (iter->next_index < MAX_INDEX) {
530 if ((block == iter->arena->block_current &&
531 offset >= iter->arena->block_current_exclusive_end) ||
532 (block > iter->arena->block_current)) {
536 SLOT* slot = &iter->arena->blocks[block][offset];
539 .index = (INDEX){.index = iter->next_index},
540 .value = &slot->
value,
564#undef INVARIANT_CHECK
566#undef INITIAL_BLOCK_INDEX_BITS
static void debug(SELF const *self, dc_debug_fmt fmt, FILE *stream)
static void free(SELF *self, void *ptr)
static void * malloc(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 INDEX insert(SELF *self, VALUE value)
static ITER_CONST get_iter_const(SELF const *self)
static ITER get_iter(SELF *self)
static IV_PAIR next(ITER *iter)
static INDEX_TYPE size(SELF const *self)
#define INVARIANT_CHECK(self)
static VALUE remove(SELF *self, INDEX index)
static bool empty_item(IV_PAIR const *item)
static IV_PAIR_CONST iv_const_empty()
SLOT PRIV(block)[DC_ARENA_CHUNKED_BLOCK_SIZE(BLOCK_INDEX_BITS)]
static VALUE * try_write(SELF *self, INDEX index)
static VALUE const * read(SELF const *self, INDEX index)
static VALUE * write(SELF *self, INDEX index)
static bool try_remove(SELF *self, INDEX index, VALUE *destination)
static const size_t max_entries
static SELF clone(SELF const *self)
static VALUE const * try_read(SELF const *self, INDEX index)
static IV_PAIR iv_empty()
static void PRIV set_memory_tracking(SELF const *self)
#define INITIAL_BLOCK_INDEX_BITS
#define DC_TRAIT_ARENA(SELF)
dc_debug_fmt dc_debug_fmt_scope_end(dc_debug_fmt fmt)
dc_debug_fmt dc_debug_fmt_scope_begin(dc_debug_fmt fmt)
static void dc_debug_fmt_print(dc_debug_fmt fmt, FILE *stream, const char *format,...)
static dc_gdb_marker dc_gdb_marker_new()
static 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
@ DC_MEMORY_TRACKER_CAP_NONE
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)
#define DC_ASSERT(expr,...)
#define DC_ASSUME(expr,...)
#define TEMPLATE_ERROR(...)
With the user provided name, even in nested templates.
mutation_tracker iterator_invalidation_tracker
INDEX_TYPE block_current_exclusive_end
dc_gdb_marker derive_c_arena_blocks
SLOT * blocks[DC_ARENA_GEO_MAX_NUM_BLOCKS(INDEX_BITS, INITIAL_BLOCK_INDEX_BITS)]
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 void memory_tracker_present(SELF const *slot)
static void memory_tracker_empty(SELF const *slot)
static void set_empty(SELF *slot, SLOT_INDEX_TYPE next_free)
static void fill(SELF *slot, SLOT_VALUE value)
static FILE * stream(SELF *self)
Opens a file for.