Open addressing with Robin Hood probing. Branch-prediction-optimized lookup. The O(1) key–value store behind subscriptions, registries, caches, and @context term mappings.
fwHash provides open-addressing hash tables with Robin Hood probing. Robin Hood probing keeps the variance in probe sequence lengths low, which improves cache behavior and allows the lookup hot path to be structured so the CPU branch predictor almost always predicts correctly — the common case (key found on first probe) is fast and the slow path is genuinely rare.
fwHash is used wherever a GE needs O(1) keyed lookup at runtime:
fwHash uses trace levels 80–99 (reserved). See the full trace level table for all assignments across the fw-lib stack.
// Hash code function — calculates hash from a key name
typedef unsigned int (*KHashCodeFunction)(const char* name);
// Compare function — returns 0 if name matches the item
typedef int (*KHashCompareFunction)(const char* name, void* itemP);
typedef struct KHashTable KHashTable; // Opaque
KHashTable* fwHashTableCreate(
FaAlloc* kaP, // Memory allocator (NULL for malloc)
KHashCodeFunction hashFunction, // User hash function
KHashCompareFunction compareFunction, // User compare function
int slots // Number of slots (power of 2 recommended)
);
Creates a new hash table. Returns NULL on allocation failure. Pass NULL for kaP to use malloc. Performance tip: use a power-of-2 value for slots (e.g., 64, 128, 256) to enable fast bitmask-based slot calculation instead of modulo.
| Function | Returns | Description |
|---|---|---|
fwHashItemAdd(ht, name, data) | 0 / -1 | Add item; head insertion, O(1) |
fwHashItemLookup(ht, name) | void* / NULL | Find item by name, O(1) average |
fwHashItemRemove(ht, name) | 0 / -1 | Remove item; caller frees data |
fwHashRelease(ht) | void | Free all hash table structures (not item data) |
// Lookup with a custom compare function (different from table default)
void* fwHashItemCustomLookup(KHashTable* ht, const char* name,
KHashCompareFunction compareFunction);
// Scan all slots — O(n), use only when hash code is unknown
void* fwHashItemLookupInAllSlots(KHashTable* ht, const char* name,
KHashCompareFunction compareFunction);
hash & mask instead of hash % size, eliminating a division instruction__builtin_expect marks the hit path as the common case, keeping the CPU branch predictor happyunsigned int myHashCode(const char* name)
{
unsigned int hash = 5381;
while (*name)
hash = ((hash << 5) + hash) + *name++;
return hash;
}
int myCompare(const char* name, void* itemP)
{
return strcmp(name, ((MyItem*)itemP)->name);
}
// Use 64 slots — power of 2 for best performance
KHashTable* ht = fwHashTableCreate(NULL, myHashCode, myCompare, 64);
MyItem* item = malloc(sizeof(MyItem));
item->name = "key1";
item->value = 42;
fwHashItemAdd(ht, item->name, item);
MyItem* found = (MyItem*) fwHashItemLookup(ht, "key1");
fwHashItemRemove(ht, "key1");
free(item); // Caller must free item data
fwHashRelease(ht);