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

Go to the source code of this file.

Data Structures

struct  value_t
struct  KEY_ENTRY
struct  SELF
 An allocator that prints to stdout when it allocates or frees memory. More...
struct  KV_PAIR
struct  ITER
struct  KV_PAIR_CONST
struct  ITER_CONST

Macros

#define KEY   map_key_t
 A simple open-addressed hashmap using robin-hood hashing.
#define KEY_HASH   key_hash
#define KEY_EQ   DC_MEM_EQ
#define KEY_DELETE   DC_NO_DELETE
#define KEY_CLONE   DC_COPY_CLONE
#define KEY_DEBUG   DC_DEFAULT_DEBUG
#define VALUE   value_t
#define VALUE_DELETE   DC_NO_DELETE
#define VALUE_CLONE   DC_COPY_CLONE
#define VALUE_DEBUG   DC_DEFAULT_DEBUG
#define KEY_ENTRY   NS(SELF, key_entry)
#define INVARIANT_CHECK(self)
#define KV_PAIR   NS(SELF, kv)
#define ITER   NS(SELF, iter)
#define KV_PAIR_CONST   NS(SELF, kv_const)
#define ITER_CONST   NS(SELF, iter_const)

Typedefs

typedef KV_PAIR item

Functions

static size_t KEY_HASH (KEY const *key)
static SELF new_with_capacity_for (size_t capacity, ALLOC *alloc)
static SELF new (ALLOC *alloc)
static SELF clone (SELF const *self)
static VALUE *PRIV try_insert_no_extend_capacity (SELF *self, KEY key, VALUE value)
static void extend_capacity_for (SELF *self, size_t expected_items)
static VALUEtry_insert (SELF *self, KEY key, VALUE value)
static VALUEinsert (SELF *self, KEY key, VALUE value)
static VALUEtry_write (SELF *self, KEY key)
static VALUEwrite (SELF *self, KEY key)
static VALUE const * try_read (SELF const *self, KEY key)
static VALUE const * read (SELF const *self, KEY key)
static bool try_remove (SELF *self, KEY key, VALUE *destination)
static VALUE remove (SELF *self, KEY key)
static void delete_entry (SELF *self, KEY key)
static size_t size (SELF const *self)
static bool empty_item (KV_PAIR const *item)
static KV_PAIR next (ITER *iter)
static bool empty (ITER const *iter)
static ITER get_iter (SELF *self)
static void delete (SELF *self)
static bool empty_item (KV_PAIR_CONST const *item)
static KV_PAIR_CONST next (ITER_CONST *iter)
static bool empty (ITER_CONST 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_MAP (SELF)

Macro Definition Documentation

◆ INVARIANT_CHECK

#define INVARIANT_CHECK ( self)
Value:
DC_ASSUME(self); \
DC_ASSUME(DC_MATH_IS_POWER_OF_2((self)->capacity)); \
DC_ASSUME((self)->keys); \
DC_ASSUME((self)->values); \
DC_ASSUME((self)->alloc);
static size_t capacity()
Definition template.h:66
#define DC_MATH_IS_POWER_OF_2(x)
Definition math.h:12
#define DC_ASSUME(expr,...)
Definition panic.h:56

Definition at line 87 of file template.h.

87#define INVARIANT_CHECK(self) \
88 DC_ASSUME(self); \
89 DC_ASSUME(DC_MATH_IS_POWER_OF_2((self)->capacity)); \
90 DC_ASSUME((self)->keys); \
91 DC_ASSUME((self)->values); \
92 DC_ASSUME((self)->alloc);

◆ ITER

#define ITER   NS(SELF, iter)

Definition at line 392 of file template.h.

◆ ITER_CONST

#define ITER_CONST   NS(SELF, iter_const)

Definition at line 465 of file template.h.

◆ KEY

#define KEY   map_key_t

A simple open-addressed hashmap using robin-hood hashing.

Definition at line 15 of file template.h.

◆ KEY_CLONE

#define KEY_CLONE   DC_COPY_CLONE

Definition at line 37 of file template.h.

◆ KEY_DEBUG

#define KEY_DEBUG   DC_DEFAULT_DEBUG

Definition at line 41 of file template.h.

◆ KEY_DELETE

#define KEY_DELETE   DC_NO_DELETE

Definition at line 33 of file template.h.

◆ KEY_ENTRY

#define KEY_ENTRY   NS(SELF, key_entry)

Definition at line 70 of file template.h.

◆ KEY_EQ

#define KEY_EQ   DC_MEM_EQ

Definition at line 29 of file template.h.

◆ KEY_HASH

#define KEY_HASH   key_hash

Definition at line 24 of file template.h.

◆ KV_PAIR

#define KV_PAIR   NS(SELF, kv)

Definition at line 385 of file template.h.

◆ KV_PAIR_CONST

#define KV_PAIR_CONST   NS(SELF, kv_const)

Definition at line 458 of file template.h.

◆ VALUE

#define VALUE   value_t

Definition at line 51 of file template.h.

◆ VALUE_CLONE

#define VALUE_CLONE   DC_COPY_CLONE

Definition at line 59 of file template.h.

◆ VALUE_DEBUG

#define VALUE_DEBUG   DC_DEFAULT_DEBUG

Definition at line 63 of file template.h.

◆ VALUE_DELETE

#define VALUE_DELETE   DC_NO_DELETE

Definition at line 55 of file template.h.

Typedef Documentation

◆ item

Definition at line 393 of file template.h.

Function Documentation

◆ clone()

SELF clone ( SELF const * self)
static

Definition at line 128 of file template.h.

128 {
129 INVARIANT_CHECK(self);
130
131 // JUSTIFY: Naive copy
132 // - We could resize (potentially a smaller map) and rehash
133 // - Not confident it would be any better than just a copy.
134 // JUSTIFY: Individually copy keys
135 // - Many entries are zeroed, no need to copy uninit data
136
137 KEY_ENTRY* keys = (KEY_ENTRY*)NS(ALLOC, calloc)(self->alloc, sizeof(KEY_ENTRY), self->capacity);
138 VALUE* values = (VALUE*)NS(ALLOC, malloc)(self->alloc, sizeof(VALUE) * self->capacity);
139 DC_ASSERT(keys && values);
140
141 for (size_t i = 0; i < self->capacity; i++) {
142 if (self->keys[i].present) {
143 KEY_ENTRY const* old_entry = &self->keys[i];
144 keys[i] = (KEY_ENTRY){
145 .present = true,
146 .distance_from_desired = old_entry->distance_from_desired,
147 .key = KEY_CLONE(&old_entry->key),
148 };
149 values[i] = VALUE_CLONE(&self->values[i]);
150 } else {
152 &values[i], sizeof(VALUE));
153 }
154 }
155
156 return (SELF){
157 .capacity = self->capacity,
158 .items = self->items,
159 .keys = keys,
160 .values = values,
161 .alloc = self->alloc,
162 .derive_c_hashmap = dc_gdb_marker_new(),
163 .iterator_invalidation_tracker = mutation_tracker_new(),
164 };
165}
static void * malloc(SELF *self, size_t size)
Definition template.h:23
static void * calloc(SELF *self, size_t count, size_t size)
Definition template.h:34
#define ALLOC
Definition template.h:64
#define INVARIANT_CHECK(self)
Definition template.h:88
#define VALUE
Definition template.h:31
#define VALUE_CLONE
Definition template.h:37
#define KEY_CLONE
Definition template.h:39
#define KEY_ENTRY
Definition template.h:70
static dc_gdb_marker dc_gdb_marker_new()
Definition gdb_marker.h:7
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_NONE
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
KEY key
Definition template.h:74
uint16_t distance_from_desired
Definition template.h:73

◆ DC_TRAIT_MAP()

DC_TRAIT_MAP ( SELF )

◆ debug()

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

Definition at line 514 of file template.h.

514 {
515 fprintf(stream, EXPAND_STRING(SELF) "@%p {\n", self);
516 fmt = dc_debug_fmt_scope_begin(fmt);
517
518 dc_debug_fmt_print(fmt, stream, "capacity: %lu,\n", self->capacity);
519 dc_debug_fmt_print(fmt, stream, "size: %lu,\n", NS(SELF, size)(self));
520
521 dc_debug_fmt_print(fmt, stream, "keys: @%p,\n", self->keys);
522 dc_debug_fmt_print(fmt, stream, "values: @%p,\n", self->values);
523
524 dc_debug_fmt_print(fmt, stream, "alloc: ");
525 NS(ALLOC, debug)(self->alloc, fmt, stream);
526 fprintf(stream, ",\n");
527
528 dc_debug_fmt_print(fmt, stream, "items: [");
529 fmt = dc_debug_fmt_scope_begin(fmt);
530
531 ITER_CONST iter = NS(SELF, get_iter_const)(self);
533
535 item = NS(ITER_CONST, next)(&iter)) {
536 dc_debug_fmt_print(fmt, stream, "{\n");
537 fmt = dc_debug_fmt_scope_begin(fmt);
538
539 dc_debug_fmt_print(fmt, stream, "key: ");
540 KEY_DEBUG(item.key, fmt, stream);
541 fprintf(stream, ",\n");
542
543 dc_debug_fmt_print(fmt, stream, "value: ");
544 VALUE_DEBUG(item.value, fmt, stream);
545 fprintf(stream, ",\n");
546
547 fmt = dc_debug_fmt_scope_end(fmt);
548 dc_debug_fmt_print(fmt, stream, "},\n");
549 }
550
551 fmt = dc_debug_fmt_scope_end(fmt);
552 dc_debug_fmt_print(fmt, stream, "],\n");
553 fmt = dc_debug_fmt_scope_end(fmt);
554 dc_debug_fmt_print(fmt, stream, "}");
555}
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 INDEX_TYPE size(SELF const *self)
Definition template.h:252
static bool empty_item(IV_PAIR const *item)
Definition template.h:344
#define ITER_CONST
Definition template.h:398
IV_PAIR item
Definition template.h:283
#define KEY_DEBUG
Definition template.h:43
#define KV_PAIR_CONST
Definition template.h:526
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 441 of file template.h.

441 {
442 DC_ASSUME(self);
443
444 for (size_t i = 0; i < self->capacity; i++) {
445 if (self->keys[i].present) {
446 KEY_DELETE(&self->keys[i].key);
447 VALUE_DELETE(&self->values[i]);
448 }
449 }
450
451 NS(ALLOC, free)(self->alloc, (void*)self->keys);
452 NS(ALLOC, free)(self->alloc, (void*)self->values);
453}
static void free(SELF *self, void *ptr)
Definition template.h:56
#define VALUE_DELETE
Definition template.h:35
#define KEY_DELETE
Definition template.h:35
bool present
Definition template.h:72
size_t capacity
Definition template.h:72
VALUE * values
Definition template.h:81
ALLOC * alloc
Definition template.h:71
KEY_ENTRY * keys
Definition template.h:80

◆ delete_entry()

void delete_entry ( SELF * self,
KEY key )
static

Definition at line 375 of file template.h.

375 {
376 VALUE value = NS(SELF, remove)(self, key);
377 VALUE_DELETE(&value);
378}
static VALUE remove(SELF *self, INDEX index)
Definition template.h:292

◆ empty() [1/2]

bool empty ( ITER const * iter)
static

Definition at line 421 of file template.h.

421 {
422 DC_ASSUME(iter);
423 mutation_version_check(&iter->version);
424 return iter->index >= iter->map->capacity;
425}
static void mutation_version_check(mutation_version const *self)

◆ empty() [2/2]

bool empty ( ITER_CONST const * iter)
static

Definition at line 494 of file template.h.

494 {
495 DC_ASSUME(iter);
496 mutation_version_check(&iter->version);
497 return iter->index >= iter->map->capacity;
498}

◆ empty_item() [1/2]

bool empty_item ( KV_PAIR const * item)
static

Definition at line 395 of file template.h.

395 {
396 return item->key == NULL && item->value == NULL;
397}

◆ empty_item() [2/2]

bool empty_item ( KV_PAIR_CONST const * item)
static

Definition at line 468 of file template.h.

468 {
469 return item->key == NULL && item->value == NULL;
470}

◆ extend_capacity_for()

void extend_capacity_for ( SELF * self,
size_t expected_items )
static

Definition at line 223 of file template.h.

223 {
224 INVARIANT_CHECK(self);
225
227 size_t const target_capacity = dc_apply_capacity_policy(expected_items);
228 if (target_capacity > self->capacity) {
229 SELF new_map = NS(SELF, new_with_capacity_for)(expected_items, self->alloc);
230 for (size_t index = 0; index < self->capacity; index++) {
231 KEY_ENTRY* entry = &self->keys[index];
232 if (entry->present) {
233 PRIV(NS(SELF, try_insert_no_extend_capacity))(&new_map, entry->key,
234 self->values[index]);
235 }
236 }
237 NS(ALLOC, free)(self->alloc, (void*)self->keys);
238 NS(ALLOC, free)(self->alloc, (void*)self->values);
239
240 INVARIANT_CHECK(&new_map);
241 *self = new_map;
242 }
243}
SLOT PRIV(block)[DC_ARENA_CHUNKED_BLOCK_SIZE(BLOCK_INDEX_BITS)]
Definition template.h:73
static SELF new_with_capacity_for(INDEX_TYPE items, ALLOC *alloc)
Definition template.h:96
static VALUE *PRIV try_insert_no_extend_capacity(SELF *self, KEY key, VALUE value)
Definition template.h:198
static size_t dc_apply_capacity_policy(size_t capacity)
Definition utils.h:7
static void mutation_tracker_mutate(mutation_tracker *self)
mutation_tracker iterator_invalidation_tracker
Definition template.h:85

◆ get_iter()

ITER get_iter ( SELF * self)
static

Definition at line 427 of file template.h.

427 {
428 DC_ASSUME(self);
429 size_t first_index = 0;
430 while (first_index < self->capacity && !self->keys[first_index].present) {
431 first_index++;
432 }
433 return (ITER){
434 .map = self,
435 .index = first_index,
436 .curr = (KV_PAIR){.key = NULL, .value = NULL},
438 };
439}
#define ITER
Definition template.h:320
#define KV_PAIR
Definition template.h:584
static mutation_version mutation_tracker_get(mutation_tracker const *self)

◆ get_iter_const()

ITER_CONST get_iter_const ( SELF const * self)
static

Definition at line 500 of file template.h.

500 {
501 DC_ASSUME(self);
502 size_t first_index = 0;
503 while (first_index < self->capacity && !self->keys[first_index].present) {
504 first_index++;
505 }
506 return (ITER_CONST){
507 .map = self,
508 .index = first_index,
509 .curr = (KV_PAIR_CONST){.key = NULL, .value = NULL},
510 .version = mutation_tracker_get(&self->iterator_invalidation_tracker),
511 };
512}

◆ insert()

VALUE * insert ( SELF * self,
KEY key,
VALUE value )
static

Definition at line 255 of file template.h.

255 {
256 VALUE* value_ptr = NS(SELF, try_insert)(self, key, value);
257 DC_ASSERT(value_ptr);
258 return value_ptr;
259}
static VALUE * try_insert(SELF *self, KEY key, VALUE value)
Definition template.h:328

◆ KEY_HASH()

size_t KEY_HASH ( KEY const * key)
static

◆ new()

SELF new ( ALLOC * alloc)
static

Definition at line 124 of file template.h.

124 {
126}
static size_t const DC_INITIAL_CAPACITY
Definition utils.h:12

◆ new_with_capacity_for()

SELF new_with_capacity_for ( size_t capacity,
ALLOC * alloc )
static

Definition at line 94 of file template.h.

94 {
96 size_t const real_capacity = dc_apply_capacity_policy(capacity);
97 DC_ASSERT(real_capacity > 0);
98 // JUSTIFY: calloc of keys
99 // - A cheap way to get all precense flags as zeroed (os & allocater supported get zeroed page)
100 // - for the values, we do not need this (no precense checks are done on values)
101 KEY_ENTRY* keys = (KEY_ENTRY*)NS(ALLOC, calloc)(alloc, sizeof(KEY_ENTRY), real_capacity);
102 VALUE* values = (VALUE*)NS(ALLOC, malloc)(alloc, sizeof(VALUE) * real_capacity);
103 DC_ASSERT(keys && values);
104
105 // JUSTIFY: no access for values & but keys are fine
106 // - Keys are calloced/zeroed as we use this for item lookup, therefore it is valid to read
107 // them.
108 // - Values are only accessed when the corresponding key is present, so we can mark them as
109 // deleted.
111 sizeof(VALUE) * real_capacity);
112
113 return (SELF){
114 .capacity = real_capacity,
115 .items = 0,
116 .keys = keys,
117 .values = values,
118 .alloc = alloc,
119 .derive_c_hashmap = dc_gdb_marker_new(),
120 .iterator_invalidation_tracker = mutation_tracker_new(),
121 };
122}

◆ next() [1/2]

KV_PAIR next ( ITER * iter)
static

Definition at line 406 of file template.h.

406 {
407 DC_ASSUME(iter);
409 if (iter->index < iter->map->capacity) {
410 iter->curr = (KV_PAIR){.key = &iter->map->keys[iter->index].key,
411 .value = &iter->map->values[iter->index]};
412 iter->index++;
413 while (iter->index < iter->map->capacity && !iter->map->keys[iter->index].present) {
414 iter->index++;
415 }
416 return iter->curr;
417 }
418 return (KV_PAIR){.key = NULL, .value = NULL};
419}
mutation_version version
Definition template.h:326
SELF * map
Definition template.h:400
KV_PAIR curr
Definition template.h:402
size_t index
Definition template.h:401

◆ next() [2/2]

KV_PAIR_CONST next ( ITER_CONST * iter)
static

Definition at line 479 of file template.h.

479 {
480 DC_ASSUME(iter);
482 if (iter->index < iter->map->capacity) {
483 iter->curr = (KV_PAIR_CONST){.key = &iter->map->keys[iter->index].key,
484 .value = &iter->map->values[iter->index]};
485 iter->index++;
486 while (iter->index < iter->map->capacity && !iter->map->keys[iter->index].present) {
487 iter->index++;
488 }
489 return iter->curr;
490 }
491 return (KV_PAIR_CONST){.key = NULL, .value = NULL};
492}
SELF const * map
Definition template.h:473
size_t index
Definition template.h:474
mutation_version version
Definition template.h:404
IV_PAIR_CONST curr
Definition template.h:378

◆ read()

VALUE const * read ( SELF const * self,
KEY key )
static

Definition at line 303 of file template.h.

303 {
304 VALUE const* value = NS(SELF, try_read)(self, key);
305 DC_ASSERT(value);
306 return value;
307}
static VALUE const * try_read(SELF const *self, INDEX index)
Definition template.h:180

◆ remove()

VALUE remove ( SELF * self,
KEY key )
static

Definition at line 369 of file template.h.

369 {
370 VALUE value;
371 DC_ASSERT(NS(SELF, try_remove)(self, key, &value));
372 return value;
373}
static bool try_remove(SELF *self, INDEX index, VALUE *destination)
Definition template.h:264

◆ size()

size_t size ( SELF const * self)
static

Definition at line 380 of file template.h.

380 {
381 INVARIANT_CHECK(self);
382 return self->items;
383}

◆ try_insert()

VALUE * try_insert ( SELF * self,
KEY key,
VALUE value )
static

Definition at line 245 of file template.h.

245 {
246 INVARIANT_CHECK(self);
248 if (dc_apply_capacity_policy(self->items) > self->capacity / 2) {
249 NS(SELF, extend_capacity_for)(self, self->items * 2);
250 }
251
252 return PRIV(NS(SELF, try_insert_no_extend_capacity))(self, key, value);
253}
static void extend_capacity_for(SELF *self, size_t expected_items)
Definition template.h:317
size_t items
Definition template.h:79

◆ try_insert_no_extend_capacity()

VALUE *PRIV try_insert_no_extend_capacity ( SELF * self,
KEY key,
VALUE value )
static

Definition at line 167 of file template.h.

167 {
168 uint16_t distance_from_desired = 0;
169 size_t const hash = KEY_HASH(&key);
170 size_t index = dc_math_modulus_power_of_2_capacity(hash, self->capacity);
171
172 VALUE* inserted_to_entry = NULL;
173
174 for (;;) {
175 KEY_ENTRY* entry = &self->keys[index];
176 DC_ASSUME(distance_from_desired < self->capacity);
177
178 if (entry->present) {
179 if (KEY_EQ(&entry->key, &key)) {
180 return NULL;
181 }
182
183 if (entry->distance_from_desired < distance_from_desired) {
184 KEY const switch_key = entry->key;
185 uint16_t const switch_distance_from_desired = entry->distance_from_desired;
186 VALUE const switch_value = self->values[index];
187
188 entry->key = key;
189 entry->distance_from_desired = distance_from_desired;
190 self->values[index] = value;
191
192 key = switch_key;
193 distance_from_desired = switch_distance_from_desired;
194 value = switch_value;
195
196 if (!inserted_to_entry) {
197 inserted_to_entry = &self->values[index];
198 }
199 }
200
201 distance_from_desired++;
202 index = dc_math_modulus_power_of_2_capacity(index + 1, self->capacity);
203 } else {
204 entry->present = true;
205 entry->distance_from_desired = distance_from_desired;
206 entry->key = key;
207
209 &self->values[index], sizeof(VALUE));
210
211 self->values[index] = value;
212
213 if (!inserted_to_entry) {
214 inserted_to_entry = &self->values[index];
215 }
216
217 self->items++;
218 return inserted_to_entry;
219 }
220 }
221}
#define KEY_HASH
Definition template.h:26
#define KEY
A simple swiss table implementation. See the abseil docs for swss table here.
Definition template.h:17
#define KEY_EQ
Definition template.h:31
static size_t DC_INLINE DC_CONST dc_math_modulus_power_of_2_capacity(size_t index, size_t capacity)
Definition math.h:63
@ DC_MEMORY_TRACKER_CAP_WRITE

◆ try_read()

VALUE const * try_read ( SELF const * self,
KEY key )
static

Definition at line 285 of file template.h.

285 {
286 INVARIANT_CHECK(self);
287 size_t const hash = KEY_HASH(&key);
288 size_t index = dc_math_modulus_power_of_2_capacity(hash, self->capacity);
289
290 for (;;) {
291 KEY_ENTRY* entry = &self->keys[index];
292 if (entry->present) {
293 if (KEY_EQ(&entry->key, &key)) {
294 return &self->values[index];
295 }
296 index = dc_math_modulus_power_of_2_capacity(index + 1, self->capacity);
297 } else {
298 return NULL;
299 }
300 }
301}

◆ try_remove()

bool try_remove ( SELF * self,
KEY key,
VALUE * destination )
static

Definition at line 309 of file template.h.

309 {
310 INVARIANT_CHECK(self);
312 size_t const hash = KEY_HASH(&key);
313 size_t index = dc_math_modulus_power_of_2_capacity(hash, self->capacity);
314
315 for (;;) {
316 KEY_ENTRY* entry = &self->keys[index];
317 if (entry->present) {
318 if (KEY_EQ(&entry->key, &key)) {
319 self->items--;
320
321 *destination = self->values[index];
322 KEY_DELETE(&entry->key);
323
324 // NOTE: For robin hood hashing, we need probe chains to be unbroken
325 // - Need to find the entries that might use this chain (
326 // distance_to_desired > 0 until the next not-present or
327 // distance_to_desired=0 slot)
328 // hence we shift entries the left (being careful with modulus index)
329
330 size_t free_index = index;
331 KEY_ENTRY* free_entry = entry;
332
333 size_t check_index =
334 dc_math_modulus_power_of_2_capacity(free_index + 1, self->capacity);
335 KEY_ENTRY* check_entry = &self->keys[check_index];
336
337 while (check_entry->present && (check_entry->distance_from_desired > 0)) {
338 free_entry->key = check_entry->key;
339 free_entry->distance_from_desired = check_entry->distance_from_desired - 1;
340 self->values[free_index] = self->values[check_index];
341
342 free_index = check_index;
343 free_entry = check_entry;
344
345 check_index =
346 dc_math_modulus_power_of_2_capacity(free_index + 1, self->capacity);
347 check_entry = &self->keys[check_index];
348 }
349
350 // JUSTIFY: Only setting free entry to false
351 // - We remove, then shift down an index
352 // - The removed entry already has the flag set
353 // - the free entry was the last one removed/moved down an index, so it
354 // should be false.
355
356 free_entry->present = false;
358 &self->values[free_index], sizeof(VALUE));
359
360 return true;
361 }
362 index = dc_math_modulus_power_of_2_capacity(index + 1, self->capacity);
363 } else {
364 return false;
365 }
366 }
367}

◆ try_write()

VALUE * try_write ( SELF * self,
KEY key )
static

Definition at line 261 of file template.h.

261 {
262 INVARIANT_CHECK(self);
263 size_t const hash = KEY_HASH(&key);
264 size_t index = dc_math_modulus_power_of_2_capacity(hash, self->capacity);
265
266 for (;;) {
267 KEY_ENTRY* entry = &self->keys[index];
268 if (entry->present) {
269 if (KEY_EQ(&entry->key, &key)) {
270 return &self->values[index];
271 }
272 index = dc_math_modulus_power_of_2_capacity(index + 1, self->capacity);
273 } else {
274 return NULL;
275 }
276 }
277}

◆ write()

VALUE * write ( SELF * self,
KEY key )
static

Definition at line 279 of file template.h.

279 {
280 VALUE* value = NS(SELF, try_write)(self, key);
281 DC_ASSERT(value);
282 return value;
283}
static VALUE * try_write(SELF *self, INDEX index)
Definition template.h:205