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

Go to the source code of this file.

Data Structures

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

Macros

#define KEY   map_key_t
 A simple swiss table implementation. See the abseil docs for swss table here.
#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 SLOT   NS(SELF, slot_t)
#define INVARIANT_CHECK(self)
#define ITER_CONST   NS(SELF, iter_const)
#define KV_PAIR_CONST   NS(ITER_CONST, item)
#define ITER   NS(SELF, iter)
#define KV_PAIR   NS(ITER, item)

Functions

static size_t KEY_HASH (KEY const *key)
static SELF PRIV new_with_exact_capacity (size_t capacity, ref alloc_ref)
static DC_PUBLIC SELF new_with_capacity_for (size_t for_items, ref alloc_ref)
static DC_PUBLIC SELF new (ref alloc_ref)
static DC_PUBLIC SELF clone (SELF const *self)
static VALUE *PRIV try_insert_no_extend_capacity (SELF *self, KEY key, VALUE value)
static void PRIV rehash (SELF *self, size_t new_capacity)
static DC_PUBLIC void extend_capacity_for (SELF *self, size_t expected_items)
static DC_PUBLIC VALUEtry_insert (SELF *self, KEY key, VALUE value)
static DC_PUBLIC VALUEinsert (SELF *self, KEY key, VALUE value)
static DC_PUBLIC VALUE const * try_read (SELF const *self, KEY key)
static DC_PUBLIC VALUE const * read (SELF const *self, KEY key)
static DC_PUBLIC VALUEtry_write (SELF *self, KEY key)
static DC_PUBLIC VALUEwrite (SELF *self, KEY key)
static DC_PUBLIC bool try_remove (SELF *self, KEY key, VALUE *destination)
static DC_PUBLIC VALUE remove (SELF *self, KEY key)
static DC_PUBLIC void delete_entry (SELF *self, KEY key)
static DC_PUBLIC size_t size (SELF const *self)
static void PRIV next_populated_index (SELF const *self, _dc_swiss_optional_index *index)
static DC_PUBLIC void delete (SELF *self)
static DC_PUBLIC bool empty_item (KV_PAIR_CONST const *item)
static DC_PUBLIC KV_PAIR_CONST next (ITER_CONST *iter)
static DC_PUBLIC bool empty (ITER_CONST const *iter)
static DC_PUBLIC ITER_CONST get_iter_const (SELF const *self)
static DC_PUBLIC void debug (SELF const *self, dc_debug_fmt fmt, FILE *stream)
static DC_PUBLIC bool empty_item (KV_PAIR const *item)
static DC_PUBLIC KV_PAIR next (ITER *iter)
static DC_PUBLIC bool empty (ITER const *iter)
static DC_PUBLIC ITER get_iter (SELF *self)
 DC_TRAIT_MAP (SELF)

Variables

DC_STATIC_CONSTANT size_t max_capacity = _dc_swiss_index_capacity

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)->slots); \
DC_ASSUME((self)->ctrl); \
DC_ASSUME((self)->count + (self)->tombstones <= (self)->capacity);
#define DC_MATH_IS_POWER_OF_2(x)
Definition math.h:14
#define DC_ASSUME(expr,...)
Definition panic.h:57

Definition at line 94 of file template.h.

94#define INVARIANT_CHECK(self) \
95 DC_ASSUME(self); \
96 DC_ASSUME(DC_MATH_IS_POWER_OF_2((self)->capacity)); \
97 DC_ASSUME((self)->slots); \
98 DC_ASSUME((self)->ctrl); \
99 DC_ASSUME((self)->count + (self)->tombstones <= (self)->capacity);

◆ ITER

#define ITER   NS(SELF, iter)

Definition at line 539 of file template.h.

◆ ITER_CONST

#define ITER_CONST   NS(SELF, iter_const)

Definition at line 435 of file template.h.

◆ KEY

#define KEY   map_key_t

A simple swiss table implementation. See the abseil docs for swss table here.

Definition at line 18 of file template.h.

◆ KEY_CLONE

#define KEY_CLONE   DC_COPY_CLONE

Definition at line 40 of file template.h.

◆ KEY_DEBUG

#define KEY_DEBUG   DC_DEFAULT_DEBUG

Definition at line 44 of file template.h.

◆ KEY_DELETE

#define KEY_DELETE   DC_NO_DELETE

Definition at line 36 of file template.h.

◆ KEY_EQ

#define KEY_EQ   DC_MEM_EQ

Definition at line 32 of file template.h.

◆ KEY_HASH

#define KEY_HASH   key_hash

Definition at line 27 of file template.h.

◆ KV_PAIR

#define KV_PAIR   NS(ITER, item)

Definition at line 540 of file template.h.

◆ KV_PAIR_CONST

#define KV_PAIR_CONST   NS(ITER_CONST, item)

Definition at line 436 of file template.h.

◆ SLOT

#define SLOT   NS(SELF, slot_t)

Definition at line 73 of file template.h.

◆ VALUE

#define VALUE   value_t

Definition at line 54 of file template.h.

◆ VALUE_CLONE

#define VALUE_CLONE   DC_COPY_CLONE

Definition at line 62 of file template.h.

◆ VALUE_DEBUG

#define VALUE_DEBUG   DC_DEFAULT_DEBUG

Definition at line 66 of file template.h.

◆ VALUE_DELETE

#define VALUE_DELETE   DC_NO_DELETE

Definition at line 58 of file template.h.

Function Documentation

◆ clone()

DC_PUBLIC SELF clone ( SELF const * self)
static

Definition at line 141 of file template.h.

141 {
142 INVARIANT_CHECK(self);
143
144 size_t ctrl_capacity = self->capacity + _DC_SWISS_SIMD_PROBE_SIZE;
145
147 self->alloc_ref, sizeof(_dc_swiss_ctrl) * ctrl_capacity);
148 SLOT* slots = (SLOT*)NS(ALLOC, allocate_uninit)(self->alloc_ref, sizeof(SLOT) * self->capacity);
149
150 memcpy(ctrl, self->ctrl, sizeof(_dc_swiss_ctrl) * ctrl_capacity);
151
152 for (size_t i = 0; i < self->capacity; i++) {
153 if (_dc_swiss_is_present(self->ctrl[i])) {
154 slots[i].key = KEY_CLONE(&self->slots[i].key);
155 slots[i].value = VALUE_CLONE(&self->slots[i].value);
156 }
157 }
158
159 return (SELF){
160 .capacity = self->capacity,
161 .count = self->count,
162 .tombstones = self->tombstones,
163 .ctrl = ctrl,
164 .slots = slots,
165 .alloc_ref = self->alloc_ref,
166 .derive_c_hashmap = dc_gdb_marker_new(),
167 .iterator_invalidation_tracker = mutation_tracker_new(),
168 };
169}
static DC_PUBLIC void * allocate_uninit(SELF *self, size_t size)
Definition template.h:92
#define ALLOC
Definition template.h:31
#define SLOT
Definition template.h:65
#define INVARIANT_CHECK(self)
Definition template.h:90
#define VALUE_CLONE
Definition template.h:39
#define KEY_CLONE
Definition template.h:39
#define SELF
Definition def.h:52
static DC_PUBLIC dc_gdb_marker dc_gdb_marker_new()
Definition gdb_marker.h:8
#define _DC_SWISS_SIMD_PROBE_SIZE
Definition utils.h:28
DC_INTERNAL static DC_PURE bool _dc_swiss_is_present(_dc_swiss_ctrl ctrl)
Definition utils.h:40
uint8_t _dc_swiss_ctrl
Definition utils.h:19
static DC_PUBLIC mutation_tracker mutation_tracker_new()
#define NS(pre, post)
Definition namespace.h:14
VALUE value
Definition template.h:78
KEY key
Definition template.h:77

◆ DC_TRAIT_MAP()

DC_TRAIT_MAP ( SELF )

◆ debug()

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

Definition at line 491 of file template.h.

491 {
492 fprintf(stream, DC_EXPAND_STRING(SELF) "@%p {\n", (void*)self);
493 fmt = dc_debug_fmt_scope_begin(fmt);
494
495 dc_debug_fmt_print(fmt, stream, "capacity: %lu,\n", self->capacity);
496 dc_debug_fmt_print(fmt, stream, "tombstones: %lu,\n", self->tombstones);
497 dc_debug_fmt_print(fmt, stream, "count: %lu,\n", self->count);
498
499 dc_debug_fmt_print(fmt, stream, "ctrl: @%p[%lu + simd probe size additional %lu],\n",
500 (void*)self->ctrl, self->capacity, (size_t)_DC_SWISS_SIMD_PROBE_SIZE);
501 dc_debug_fmt_print(fmt, stream, "slots: @%p[%lu],\n", (void*)self->slots, self->capacity);
502
503 dc_debug_fmt_print(fmt, stream, "alloc: ");
504 NS(ALLOC, debug)(NS(NS(ALLOC, ref), deref)(self->alloc_ref), fmt, stream);
505 fprintf(stream, ",\n");
506
507 dc_debug_fmt_print(fmt, stream, "entries: [\n");
508 fmt = dc_debug_fmt_scope_begin(fmt);
509
510 ITER_CONST iter = NS(SELF, get_iter_const)(self);
511
513 item = NS(ITER_CONST, next)(&iter)) {
514 dc_debug_fmt_print(fmt, stream, "{\n");
515 fmt = dc_debug_fmt_scope_begin(fmt);
516
517 dc_debug_fmt_print(fmt, stream, "key: ");
518 KEY_DEBUG(item.key, fmt, stream);
519 fprintf(stream, ",\n");
520
521 dc_debug_fmt_print(fmt, stream, "value: ");
522 VALUE_DEBUG(item.value, fmt, stream);
523 fprintf(stream, ",\n");
524
525 fmt = dc_debug_fmt_scope_end(fmt);
526 dc_debug_fmt_print(fmt, stream, "},\n");
527 }
528
529 fmt = dc_debug_fmt_scope_end(fmt);
530 dc_debug_fmt_print(fmt, stream, "]\n");
531
532 fmt = dc_debug_fmt_scope_end(fmt);
533 dc_debug_fmt_print(fmt, stream, "}");
534}
static DC_PUBLIC void debug(SELF const *self, dc_debug_fmt fmt, FILE *stream)
Definition template.h:212
#define VALUE_DEBUG
Definition template.h:41
static DC_PUBLIC IV_PAIR next(ITER *iter)
Definition template.h:355
static DC_PUBLIC bool empty_item(IV_PAIR const *item)
Definition template.h:347
#define ITER_CONST
Definition template.h:411
static DC_PUBLIC ITER_CONST get_iter_const(SELF const *self)
Definition template.h:464
IV_PAIR item
Definition template.h:281
#define KEY_DEBUG
Definition template.h:43
#define KV_PAIR_CONST
Definition template.h:522
static DC_PUBLIC void dc_debug_fmt_print(dc_debug_fmt fmt, FILE *stream, const char *format,...)
Definition fmt.h:32
static DC_PUBLIC dc_debug_fmt dc_debug_fmt_scope_end(dc_debug_fmt fmt)
Definition fmt.h:57
static DC_PUBLIC dc_debug_fmt dc_debug_fmt_scope_begin(dc_debug_fmt fmt)
Definition fmt.h:50
#define DC_EXPAND_STRING(NAME)
Definition namespace.h:6
static DC_PUBLIC FILE * stream(SELF *self)
Definition template.h:108

◆ delete()

DC_PUBLIC void delete ( SELF * self)
static

Definition at line 422 of file template.h.

422 {
423 for (size_t i = 0; i < self->capacity; i++) {
424 if (_dc_swiss_is_present(self->ctrl[i])) {
425 KEY_DELETE(&self->slots[i].key);
426 VALUE_DELETE(&self->slots[i].value);
427 }
428 }
429
430 size_t ctrl_capacity = self->capacity + _DC_SWISS_SIMD_PROBE_SIZE;
431 NS(ALLOC, deallocate)(self->alloc_ref, self->ctrl, sizeof(_dc_swiss_ctrl) * ctrl_capacity);
432 NS(ALLOC, deallocate)(self->alloc_ref, self->slots, sizeof(SLOT) * self->capacity);
433}
static DC_PUBLIC void deallocate(SELF *self, void *ptr, size_t size)
Definition template.h:127
#define VALUE_DELETE
Definition template.h:37
#define KEY_DELETE
Definition template.h:35
_dc_swiss_ctrl * ctrl
Definition template.h:84
size_t capacity
Definition template.h:72
SLOT * slots
Definition template.h:71
ref alloc_ref
Definition template.h:49

◆ delete_entry()

DC_PUBLIC void delete_entry ( SELF * self,
KEY key )
static

Definition at line 403 of file template.h.

403 {
404 VALUE value = NS(SELF, remove)(self, key);
405 VALUE_DELETE(&value);
406}
#define VALUE
Definition template.h:35
static DC_PUBLIC VALUE remove(SELF *self, INDEX index)
Definition template.h:292

◆ empty() [1/2]

DC_PUBLIC bool empty ( ITER const * iter)
static

Definition at line 576 of file template.h.

576 {
577 DC_ASSUME(iter);
578 mutation_version_check(&iter->version);
579 return iter->next_index == _DC_SWISS_NO_INDEX;
580}
#define _DC_SWISS_NO_INDEX
Definition utils.h:98
static DC_PUBLIC void mutation_version_check(mutation_version const *self)

◆ empty() [2/2]

DC_PUBLIC bool empty ( ITER_CONST const * iter)
static

Definition at line 472 of file template.h.

472 {
473 DC_ASSUME(iter);
474 mutation_version_check(&iter->version);
475 return iter->next_index == _DC_SWISS_NO_INDEX;
476}

◆ empty_item() [1/2]

DC_PUBLIC bool empty_item ( KV_PAIR const * item)
static

Definition at line 553 of file template.h.

553 {
554 return item->key == NULL && item->value == NULL;
555}

◆ empty_item() [2/2]

DC_PUBLIC bool empty_item ( KV_PAIR_CONST const * item)
static

Definition at line 449 of file template.h.

449 {
450 return item->key == NULL && item->value == NULL;
451}

◆ extend_capacity_for()

DC_PUBLIC void extend_capacity_for ( SELF * self,
size_t expected_items )
static

Definition at line 269 of file template.h.

269 {
270 INVARIANT_CHECK(self);
272
273 size_t new_capacity = dc_swiss_capacity(expected_items);
274 if (new_capacity > self->capacity) {
275 PRIV(NS(SELF, rehash))(self, new_capacity);
276 }
277}
static DC_INTERNAL void PRIV rehash(SELF *self, size_t new_capacity)
Definition template.h:260
static DC_INTERNAL size_t dc_swiss_capacity(size_t for_items)
Definition utils.h:56
static DC_PUBLIC void mutation_tracker_mutate(mutation_tracker *self)
#define PRIV(name)
Definition namespace.h:20
mutation_tracker iterator_invalidation_tracker
Definition template.h:87

◆ get_iter()

DC_PUBLIC ITER get_iter ( SELF * self)
static

Definition at line 582 of file template.h.

582 {
583 INVARIANT_CHECK(self);
584
585 _dc_swiss_optional_index index = 0;
586 PRIV(NS(SELF, next_populated_index))(self, &index);
587
588 return (ITER){
589 .map = self,
590 .next_index = index,
592 };
593}
#define ITER
Definition template.h:322
static void PRIV next_populated_index(SELF const *self, _dc_swiss_optional_index *index)
Definition template.h:413
size_t _dc_swiss_optional_index
Definition utils.h:99
static DC_PUBLIC mutation_version mutation_tracker_get(mutation_tracker const *self)

◆ get_iter_const()

DC_PUBLIC ITER_CONST get_iter_const ( SELF const * self)
static

Definition at line 478 of file template.h.

478 {
479 INVARIANT_CHECK(self);
480
481 _dc_swiss_optional_index index = 0;
482 PRIV(NS(SELF, next_populated_index))(self, &index);
483
484 return (ITER_CONST){
485 .map = self,
486 .next_index = index,
487 .version = mutation_tracker_get(&self->iterator_invalidation_tracker),
488 };
489}

◆ insert()

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

Definition at line 300 of file template.h.

300 {
301 VALUE* value_ptr = NS(SELF, try_insert)(self, key, value);
302 DC_ASSERT(value_ptr, "Failed to insert item {key=%s, value=%s}", DC_DEBUG(KEY_DEBUG, &key),
303 DC_DEBUG(VALUE_DEBUG, &value));
304 return value_ptr;
305}
#define KEY_DEBUG
Definition template.h:34
static DC_PUBLIC VALUE * try_insert(SELF *self, KEY key, VALUE value)
Definition template.h:318
#define DC_DEBUG(DEBUG_FN, DEBUG_PTR)
Definition dump.h:92
#define DC_ASSERT(expr,...)
Definition panic.h:37

◆ KEY_HASH()

size_t KEY_HASH ( KEY const * key)
static

Definition at line 28 of file template.h.

28{ return *key; }

◆ new()

DC_PUBLIC SELF new ( ref alloc_ref)
static

Definition at line 137 of file template.h.

137 {
139}
static DC_PUBLIC SELF new_with_capacity_for(INDEX_TYPE items, ref alloc_ref)
Definition template.h:96
#define DC_SWISS_INITIAL_CAPACITY
Definition utils.h:13

◆ new_with_capacity_for()

DC_PUBLIC SELF new_with_capacity_for ( size_t for_items,
ref alloc_ref )
static

Definition at line 130 of file template.h.

130 {
131 DC_ASSERT(for_items > 0, "Cannot create map with capacity for 0 items {for_items=%lu}",
132 for_items);
133
134 return PRIV(NS(SELF, new_with_exact_capacity))(dc_swiss_capacity(for_items), alloc_ref);
135}
static DC_INTERNAL SELF PRIV new_with_exact_capacity(size_t capacity, ref alloc_ref)
Definition template.h:148

◆ new_with_exact_capacity()

SELF PRIV new_with_exact_capacity ( size_t capacity,
ref alloc_ref )
static

Definition at line 101 of file template.h.

101 {
104 size_t ctrl_capacity = capacity + _DC_SWISS_SIMD_PROBE_SIZE;
105
107 alloc_ref, sizeof(_dc_swiss_ctrl) * ctrl_capacity);
108 SLOT* slots = (SLOT*)NS(ALLOC, allocate_uninit)(alloc_ref, sizeof(SLOT) * capacity);
109
110 for (size_t i = 0; i < capacity; i++) {
111 ctrl[i] = DC_SWISS_VAL_EMPTY;
112 }
113 ctrl[capacity] = DC_SWISS_VAL_SENTINEL;
114 for (size_t i = 1; i < _DC_SWISS_SIMD_PROBE_SIZE; i++) {
115 ctrl[capacity + i] = ctrl[i - 1]; // currently empty
116 }
117
118 return (SELF){
119 .capacity = capacity,
120 .count = 0,
121 .tombstones = 0,
122 .ctrl = ctrl,
123 .slots = slots,
124 .alloc_ref = alloc_ref,
125 .derive_c_hashmap = dc_gdb_marker_new(),
126 .iterator_invalidation_tracker = mutation_tracker_new(),
127 };
128}
static DC_PUBLIC void * allocate_zeroed(SELF *self, size_t size)
Definition template.h:117
#define DC_SWISS_VAL_EMPTY
Definition utils.h:37
#define DC_SWISS_VAL_SENTINEL
Definition utils.h:35

◆ next() [1/2]

DC_PUBLIC KV_PAIR next ( ITER * iter)
static

Definition at line 557 of file template.h.

557 {
559
561 if (index == _DC_SWISS_NO_INDEX) {
562 return (KV_PAIR){
563 .key = NULL,
564 .value = NULL,
565 };
566 }
567
568 iter->next_index++;
569 PRIV(NS(SELF, next_populated_index))(iter->map, &iter->next_index);
570 return (KV_PAIR){
571 .key = &iter->map->slots[index].key,
572 .value = &iter->map->slots[index].value,
573 };
574}
#define KV_PAIR
Definition template.h:585
INDEX_TYPE next_index
Definition template.h:327
mutation_version version
Definition template.h:328
SELF * map
Definition template.h:411

◆ next() [2/2]

DC_PUBLIC KV_PAIR_CONST next ( ITER_CONST * iter)
static

Definition at line 453 of file template.h.

453 {
455
457 if (index == _DC_SWISS_NO_INDEX) {
458 return (KV_PAIR_CONST){
459 .key = NULL,
460 .value = NULL,
461 };
462 }
463
464 iter->next_index++;
465 PRIV(NS(SELF, next_populated_index))(iter->map, &iter->next_index);
466 return (KV_PAIR_CONST){
467 .key = &iter->map->slots[index].key,
468 .value = &iter->map->slots[index].value,
469 };
470}
INDEX_TYPE next_index
Definition template.h:416
SELF const * map
Definition template.h:484
mutation_version version
Definition template.h:417

◆ next_populated_index()

void PRIV next_populated_index ( SELF const * self,
_dc_swiss_optional_index * index )
static

Definition at line 413 of file template.h.

414 {
415 size_t i = *index;
416 while (i < self->capacity && !_dc_swiss_is_present(self->ctrl[i])) {
417 ++i;
418 }
419 *index = (i == self->capacity) ? _DC_SWISS_NO_INDEX : i;
420}

◆ read()

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

Definition at line 340 of file template.h.

340 {
341 VALUE const* value = NS(SELF, try_read)(self, key);
342 DC_ASSERT(value, "Cannot read item {key=%s}", DC_DEBUG(KEY_DEBUG, &key));
343 return value;
344}
static DC_PUBLIC VALUE const * try_read(SELF const *self, INDEX index)
Definition template.h:180

◆ rehash()

void PRIV rehash ( SELF * self,
size_t new_capacity )
static

Definition at line 242 of file template.h.

242 {
243 INVARIANT_CHECK(self);
244
245 // NOTE: This code also works for shrinking the hashmap
246 // - we never expect to do this, so are defensive.
247 // - We do expect to rehash with the same capacity (tombstone cleanup)
248 DC_ASSUME(new_capacity >= self->capacity);
250
251 SELF new_map = PRIV(NS(SELF, new_with_exact_capacity))(new_capacity, self->alloc_ref);
252
253 for (size_t i = 0; i < self->capacity; i++) {
254 if (_dc_swiss_is_present(self->ctrl[i])) {
255 (void)PRIV(NS(SELF, try_insert_no_extend_capacity))(&new_map, self->slots[i].key,
256 self->slots[i].value);
257 }
258 }
259
261
262 size_t ctrl_capacity = self->capacity + _DC_SWISS_SIMD_PROBE_SIZE;
263 NS(ALLOC, deallocate)(self->alloc_ref, self->ctrl, sizeof(_dc_swiss_ctrl) * ctrl_capacity);
264 NS(ALLOC, deallocate)(self->alloc_ref, self->slots, sizeof(SLOT) * self->capacity);
265
266 *self = new_map;
267}
static DC_INTERNAL VALUE *PRIV try_insert_no_extend_capacity(SELF *self, KEY key, VALUE value)
Definition template.h:190

◆ remove()

DC_PUBLIC VALUE remove ( SELF * self,
KEY key )
static

Definition at line 396 of file template.h.

396 {
397 VALUE value;
398 DC_ASSERT(NS(SELF, try_remove)(self, key, &value), "Failed to remove item {key=%s}",
399 DC_DEBUG(KEY_DEBUG, &key));
400 return value;
401}
static DC_PUBLIC bool try_remove(SELF *self, INDEX index, VALUE *destination)
Definition template.h:264

◆ size()

DC_PUBLIC size_t size ( SELF const * self)
static

Definition at line 408 of file template.h.

408 {
409 INVARIANT_CHECK(self);
410 return self->count;
411}

◆ try_insert()

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

Definition at line 279 of file template.h.

279 {
280 INVARIANT_CHECK(self);
281
282 if (self->count >= NS(SELF, max_capacity)) {
283 return NULL;
284 }
285
286 switch (_dc_swiss_heuristic_should_extend(self->tombstones, self->count, self->capacity)) {
288 PRIV(NS(SELF, rehash))(self, self->capacity * 2);
289 break;
291 PRIV(NS(SELF, rehash))(self, self->capacity);
292 break;
294 break;
295 }
296
297 return PRIV(NS(SELF, try_insert_no_extend_capacity))(self, key, value);
298}
DC_STATIC_CONSTANT size_t max_capacity
Definition template.h:130
@ DC_SWISS_DO_NOTHING
Definition utils.h:78
@ DC_SWISS_DOUBLE_CAPACITY
Definition utils.h:76
@ DC_SWISS_CLEANUP_TOMBSONES
Definition utils.h:77
static DC_INTERNAL _dc_swiss_rehash_action _dc_swiss_heuristic_should_extend(size_t tombstones, size_t count, size_t capacity)
Definition utils.h:82
size_t count
Definition template.h:78
size_t tombstones
Definition template.h:82

◆ try_insert_no_extend_capacity()

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

Definition at line 171 of file template.h.

171 {
172 INVARIANT_CHECK(self);
173 DC_ASSUME(self->count + self->tombstones < self->capacity);
175
176 const size_t mask = self->capacity - 1;
177
178 const size_t hash = KEY_HASH(&key);
180
182
183 // `H1` - the bucket starting position
184 size_t const start = hash & mask;
185
186 for (size_t step = 0;; step += _DC_SWISS_SIMD_PROBE_SIZE) {
187 const size_t group_start = (start + step) & mask;
188
189 _dc_swiss_ctrl_group const group = _dc_swiss_group_load(&self->ctrl[group_start]);
190 _dc_swiss_ctrl_group_bitmask const matches = _dc_swiss_group_match(group, id);
191
192 _DC_SWISS_BITMASK_FOR_EACH(matches, group_offset) {
193 size_t const index =
194 _dc_swiss_group_index_to_slot(group_start, group_offset, self->capacity);
195
196 // Sentinel value, skip over it.
197 if (index == _DC_SWISS_NO_INDEX)
198 continue;
199
200 if (KEY_EQ(&self->slots[index].key, &key)) {
201 return NULL;
202 }
203 }
204
205 if (first_deleted == _DC_SWISS_NO_INDEX) {
206 _dc_swiss_ctrl_group_bitmask const deleted =
208 if (deleted != 0) {
209 size_t const slot = _dc_swiss_group_index_to_slot(
210 group_start, _dc_swiss_ctrl_group_bitmask_lowest(deleted), self->capacity);
211 if (slot != _DC_SWISS_NO_INDEX) {
212 first_deleted = slot;
213 }
214 }
215 }
216
218 if (empty != 0) {
219 size_t const empty_idx = _dc_swiss_group_index_to_slot(
221 DC_ASSUME(empty_idx != _DC_SWISS_NO_INDEX, "Empty value cannot match the sentinel");
222
223 bool const has_deleted = first_deleted != _DC_SWISS_NO_INDEX;
224 size_t const insert_index = has_deleted ? first_deleted : empty_idx;
225
226 if (has_deleted) {
227 self->tombstones--;
228 }
229
230 self->slots[insert_index] = (SLOT){
231 .value = value,
232 .key = key,
233 };
234 _dc_swiss_ctrl_set_at(self->ctrl, self->capacity, insert_index, id);
235
236 self->count++;
237 return &self->slots[insert_index].value;
238 }
239 }
240}
static DC_PUBLIC bool empty(ITER const *iter)
Definition template.h:349
#define KEY_HASH
Definition template.h:26
#define KEY_EQ
Definition template.h:31
__m128i _dc_swiss_ctrl_group
Definition utils.h:18
#define _DC_SWISS_BITMASK_FOR_EACH(mask, idx_var)
Definition utils.h:129
static DC_INTERNAL size_t _dc_swiss_group_index_to_slot(size_t group_start, _dc_swiss_ctrl_group_offset idx, size_t capacity)
Definition utils.h:136
static DC_INTERNAL _dc_swiss_ctrl_group_offset _dc_swiss_ctrl_group_bitmask_lowest(_dc_swiss_ctrl_group_bitmask mask)
Definition utils.h:118
#define DC_SWISS_VAL_DELETED
Definition utils.h:36
static DC_INTERNAL void _dc_swiss_ctrl_set_at(_dc_swiss_ctrl *self, size_t capacity, size_t index, _dc_swiss_ctrl val)
Definition utils.h:63
uint16_t _dc_swiss_ctrl_group_bitmask
Definition utils.h:26
static DC_INTERNAL _dc_swiss_ctrl_group _dc_swiss_group_load(const _dc_swiss_ctrl *group_ptr)
Definition utils.h:106
static DC_INTERNAL _dc_swiss_ctrl_group_bitmask _dc_swiss_group_match(_dc_swiss_ctrl_group group, uint8_t value)
Definition utils.h:111
static DC_INTERNAL _dc_swiss_ctrl _dc_swiss_ctrl_from_hash(size_t hash)
Definition utils.h:51

◆ try_read()

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

Definition at line 307 of file template.h.

307 {
308 const size_t mask = self->capacity - 1;
309
310 const size_t hash = KEY_HASH(&key);
312
313 const size_t start = hash & mask;
314
315 for (size_t step = 0;; step += _DC_SWISS_SIMD_PROBE_SIZE) {
316 size_t const group_start = (start + step) & mask;
317 _dc_swiss_ctrl_group const group = _dc_swiss_group_load(&self->ctrl[group_start]);
318 _dc_swiss_ctrl_group_bitmask const matches = _dc_swiss_group_match(group, id);
319
320 _DC_SWISS_BITMASK_FOR_EACH(matches, group_offset) {
321 size_t const i =
322 _dc_swiss_group_index_to_slot(group_start, group_offset, self->capacity);
323
324 // Sentinel
325 if (i == _DC_SWISS_NO_INDEX)
326 continue;
327
328 if (KEY_EQ(&self->slots[i].key, &key)) {
329 return &self->slots[i].value;
330 }
331 }
332
334 if (empty != 0) {
335 return NULL;
336 }
337 }
338}

◆ try_remove()

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

Definition at line 357 of file template.h.

357 {
358 INVARIANT_CHECK(self);
359 DC_ASSERT(destination != NULL, "Passed NULL destination pointer");
360
361 const size_t mask = self->capacity - 1;
362 const size_t hash = KEY_HASH(&key);
364
365 const size_t start = hash & mask;
366
367 for (size_t step = 0;; step += _DC_SWISS_SIMD_PROBE_SIZE) {
368 const size_t group_start = (start + step) & mask;
369
370 _dc_swiss_ctrl_group const group = _dc_swiss_group_load(&self->ctrl[group_start]);
371 _dc_swiss_ctrl_group_bitmask const matches = _dc_swiss_group_match(group, id);
372
373 _DC_SWISS_BITMASK_FOR_EACH(matches, group_offset) {
374 size_t const index =
375 _dc_swiss_group_index_to_slot(group_start, group_offset, self->capacity);
376
377 if (index == _DC_SWISS_NO_INDEX)
378 continue;
379
380 if (KEY_EQ(&self->slots[index].key, &key)) {
381 *destination = self->slots[index].value;
383 self->count--;
384 self->tombstones++;
385 return true;
386 }
387 }
388
390 if (empty != 0) {
391 return false;
392 }
393 }
394}

◆ try_write()

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

Definition at line 346 of file template.h.

346 {
347 INVARIANT_CHECK(self);
348 return (VALUE*)NS(SELF, try_read)((SELF const*)self, key);
349}

◆ write()

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

Definition at line 351 of file template.h.

351 {
352 VALUE* value = NS(SELF, try_write)(self, key);
353 DC_ASSERT(value, "Cannot write item {key=%s}", DC_DEBUG(KEY_DEBUG, &key));
354 return value;
355}
static DC_PUBLIC VALUE * try_write(SELF *self, INDEX index)
Definition template.h:205

Variable Documentation

◆ max_capacity

Definition at line 92 of file template.h.