Skip to content

Commit 4028aec

Browse files
committed
atom_table: fix inverted rehash load-factor check
Invert the condition: grow once the load factor would exceed the threshold. Add a test-structs regression test that bulk-inserts many atoms in batches and verifies each is retrievable by index and by name. Signed-off-by: Paul Guyot <pguyot@kallisys.net>
1 parent f7594af commit 4028aec

2 files changed

Lines changed: 58 additions & 1 deletion

File tree

src/libAtomVM/atom_table.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ static inline bool maybe_rehash(struct AtomTable *table, int new_entries)
352352
{
353353
int new_count = table->count + new_entries;
354354
int threshold = ATOM_TABLE_THRESHOLD(table->capacity);
355-
if (new_count > threshold) {
355+
if (new_count <= threshold) {
356356
return false;
357357
}
358358

tests/test-structs.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include <assert.h>
2222
#include <stdlib.h>
23+
#include <string.h>
2324

2425
#include "atom_table.h"
2526
#include "utils.h"
@@ -479,13 +480,69 @@ void test_atom_table(void)
479480
atom_table_destroy(table);
480481
}
481482

483+
static void test_atom_table_bulk_grow(void)
484+
{
485+
struct AtomTable *table = atom_table_new();
486+
487+
const int batches = 40;
488+
const int per_batch = 17;
489+
int next_id = 0;
490+
491+
// Bulk atom_table_ensure_atoms does not copy the atom bytes: the stored keys
492+
// point into the supplied buffer (modules keep their binary alive). Use a
493+
// single buffer that outlives the table for all batches.
494+
uint8_t *buf = malloc(batches * per_batch * 64);
495+
assert(buf != NULL);
496+
uint8_t *p = buf;
497+
498+
for (int b = 0; b < batches; b++) {
499+
uint8_t *batch_start = p;
500+
char name[64];
501+
for (int i = 0; i < per_batch; i++) {
502+
int len = snprintf(name, sizeof(name), "bulk_atom_%d", next_id++);
503+
*p++ = (uint8_t) len;
504+
memcpy(p, name, len);
505+
p += len;
506+
}
507+
atom_index_t translate[per_batch];
508+
enum AtomTableEnsureAtomResult r
509+
= atom_table_ensure_atoms(table, batch_start, per_batch, translate, 0);
510+
assert(r == AtomTableEnsureAtomOk);
511+
}
512+
513+
int total = batches * per_batch;
514+
assert((int) atom_table_count(table) == total);
515+
516+
// Every atom must still be retrievable both by index and by name.
517+
for (int id = 0; id < total; id++) {
518+
char name[64];
519+
int len = snprintf(name, sizeof(name), "bulk_atom_%d", id);
520+
521+
size_t got_len;
522+
const uint8_t *got = atom_table_get_atom_string(table, id, &got_len);
523+
assert(got != NULL);
524+
assert((int) got_len == len);
525+
assert(memcmp(got, name, len) == 0);
526+
527+
atom_index_t found;
528+
enum AtomTableEnsureAtomResult r = atom_table_ensure_atom(
529+
table, (const uint8_t *) name, len, AtomTableAlreadyExisting, &found);
530+
assert(r == AtomTableEnsureAtomOk);
531+
assert((int) found == id);
532+
}
533+
534+
atom_table_destroy(table);
535+
free(buf);
536+
}
537+
482538
int main(int argc, char **argv)
483539
{
484540
UNUSED(argc);
485541
UNUSED(argv);
486542

487543
test_valueshashtable();
488544
test_atom_table();
545+
test_atom_table_bulk_grow();
489546

490547
return EXIT_SUCCESS;
491548
}

0 commit comments

Comments
 (0)