hashmap: refactor interface

- `hashmap_insert()` no longer takes key as argument, and
  takes the pointer to be associated with the entry as argument.
- Rename `hashmap_entry_delete` -> `hashmap_delete`.
- Make `user_data` the first argument for `hashmap_walk_func`.
- Other misc renames.
This commit is contained in:
CismonX 2025-03-06 06:40:28 +08:00
parent b585a05c91
commit c2a91d6420
No known key found for this signature in database
GPG key ID: 3094873E29A482FB
5 changed files with 84 additions and 110 deletions

View file

@ -527,7 +527,7 @@ fsck_apply (
entry->name = json_string_value(name_node);
entry->name_len = name_len;
*hashmap_insert(assoc_map, key_assoc, hashcode_assoc) = entry;
hashmap_insert(assoc_map, hashcode_assoc, entry);
return 0;
callback:
@ -670,10 +670,8 @@ update_guid (
uint8_t *guid,
unsigned long hashcode
) {
hashmap_entry_delete(guid_map, entry, old_entry_id);
union hashmap_key key = { .ptr = guid };
*hashmap_insert(guid_map, key, hashcode) = entry;
hashmap_delete(guid_map, entry, old_entry_id);
hashmap_insert(guid_map, hashcode, entry);
memcpy(entry->guid, guid, UUID_LEN);
}
@ -768,13 +766,11 @@ build_maps (
.node = root,
.children = children,
};
union hashmap_key key_id = { .u64 = root_id };
unsigned long hashcode_id = hash_digest(&root_id, sizeof(root_id));
*hashmap_insert(id_map, key_id, hashcode_id) = root_entry;
unsigned long hashcode_id = hash_digest(&root_id, sizeof(root_id));
hashmap_insert(id_map, hashcode_id, root_entry);
union hashmap_key key_guid = { .ptr = root_entry->guid };
unsigned long hashcode_guid = hash_digest(root_entry->guid, UUID_LEN);
*hashmap_insert(guid_map, key_guid, hashcode_guid) = root_entry;
unsigned long hashcode_guid = hash_digest(root_entry->guid, UUID_LEN);
hashmap_insert(guid_map, hashcode_guid, root_entry);
struct idmap_iter_ctx iter_ctx = {
.id_map = id_map,
@ -879,8 +875,8 @@ free_blcookie (
static void
free_entry_cb (
void *entry,
void *UNUSED_VAR(user_data)
void *UNUSED_VAR(user_data),
void *entry
) {
free(entry);
}
@ -1321,8 +1317,8 @@ maps_iter_cb (
entry->node = node;
entry->children = children;
memcpy(entry->guid, guid, UUID_LEN);
*hashmap_insert(ctx->id_map, key, hashcode) = entry;
*hashmap_insert(ctx->guid_map, key_guid, hashcode_guid) = entry;
hashmap_insert(ctx->id_map, hashcode, entry);
hashmap_insert(ctx->guid_map, hashcode_guid, entry);
// bookmark bar, mobile bookmarks, other bookmarks, ...
if (parent->id == BOOKMARKS_ROOT_ID) {
@ -1359,7 +1355,7 @@ maps_iter_cb (
entry->name = name;
entry->name_len = name_len;
*hashmap_insert(assoc_map, key_assoc, hashcode_assoc) = entry;
hashmap_insert(assoc_map, hashcode_assoc, entry);
end:
#ifdef BOOKMARKFS_BACKEND_CHROMIUM_WRITE
@ -2265,9 +2261,7 @@ bookmark_create (
.node = node,
.children = is_dir ? json_object_sget(node, "children") : NULL,
};
union hashmap_key key = { .u64 = id };
*hashmap_insert(ctx->id_map, key, hash_digest(&id, sizeof(id))) = entry;
hashmap_insert(ctx->id_map, hash_digest(&id, sizeof(id)), entry);
void *guid = lctx.guid;
unsigned long hashcode_guid = lctx.hashcode;
@ -2275,16 +2269,9 @@ bookmark_create (
guid = bctx.guid;
hashcode_guid = bctx.hashcode;
key.ptr = &(struct assocmap_key) {
.parent_id = parent_id,
.name = name,
.name_len = name_len,
};
*hashmap_insert(ctx->assoc_map, key, lctx.hashcode) = entry;
hashmap_insert(ctx->assoc_map, lctx.hashcode, entry);
}
key.ptr = guid;
*hashmap_insert(ctx->guid_map, key, hashcode_guid) = entry;
hashmap_insert(ctx->guid_map, hashcode_guid, entry);
memcpy(entry->guid, guid, UUID_LEN);
ctx->dirty = DIRTY_LEVEL_DATA;
@ -2344,10 +2331,10 @@ bookmark_delete (
long guidmap_entry_id = lctx.entry_id;
if (!(ctx->flags & BACKEND_FILENAME_GUID)) {
guidmap_entry_id = -1;
hashmap_entry_delete(ctx->assoc_map, entry, lctx.entry_id);
hashmap_delete(ctx->assoc_map, entry, lctx.entry_id);
}
hashmap_entry_delete(ctx->guid_map, entry, guidmap_entry_id);
hashmap_entry_delete(ctx->id_map, entry, -1);
hashmap_delete(ctx->guid_map, entry, guidmap_entry_id);
hashmap_delete(ctx->id_map, entry, -1);
free(entry);
// Remove from store
@ -2566,10 +2553,10 @@ bookmark_rename (
long new_guidmap_entry_id = new_lctx.entry_id;
if (!filename_is_guid) {
new_guidmap_entry_id = -1;
hashmap_entry_delete(ctx->assoc_map, new_entry, new_lctx.entry_id);
hashmap_delete(ctx->assoc_map, new_entry, new_lctx.entry_id);
}
hashmap_entry_delete(ctx->guid_map, new_entry, new_guidmap_entry_id);
hashmap_entry_delete(ctx->id_map, new_entry, -1);
hashmap_delete(ctx->guid_map, new_entry, new_guidmap_entry_id);
hashmap_delete(ctx->id_map, new_entry, -1);
free(new_entry);
}
@ -2577,16 +2564,8 @@ bookmark_rename (
update_guid(old_entry, ctx->guid_map, old_lctx.entry_id, new_lctx.guid,
new_lctx.hashcode);
} else {
hashmap_entry_delete(ctx->assoc_map, old_entry, old_lctx.entry_id);
union hashmap_key key = {
.ptr = &(struct assocmap_key) {
.parent_id = new_parent_id,
.name = old_entry->name,
.name_len = new_name_len,
},
};
*hashmap_insert(ctx->assoc_map, key, new_lctx.hashcode) = old_entry;
hashmap_delete(ctx->assoc_map, old_entry, old_lctx.entry_id);
hashmap_insert(ctx->assoc_map, new_lctx.hashcode, old_entry);
}
ctx->dirty = DIRTY_LEVEL_DATA;

View file

@ -533,7 +533,7 @@ fsck_apply (
dentry->name_len = name_len;
memcpy(dentry->name, name, name_len);
*hashmap_insert(map, key, hashcode) = dentry;
hashmap_insert(map, hashcode, dentry);
goto end;
callback:
@ -2347,7 +2347,7 @@ bookmark_check_cb (
map = hashmap_create(dentmap_comp, dentmap_hash);
ctx->dentry_map = map;
}
*hashmap_insert(map, key, hashcode) = dentry;
hashmap_insert(map, hashcode, dentry);
return 0;
}
if (dentry->id == (uint64_t)id) {
@ -2457,7 +2457,7 @@ bookmark_list_cb (
dentry->name_len = name_len;
memcpy(dentry->name, name, name_len);
*hashmap_insert(map, key, hashcode) = dentry;
hashmap_insert(map, hashcode, dentry);
}
return ctx->status;
@ -2547,8 +2547,8 @@ free_dentmap (
static void
free_dentmap_entry (
void *entry,
void *UNUSED_VAR(user_data)
void *UNUSED_VAR(user_data),
void *entry
) {
struct bookmark_dentry *dentry = entry;

View file

@ -458,7 +458,7 @@ bm_fh_free (
struct fs_file_handle *fh,
long entry_id
) {
hashmap_entry_delete(ctx.fh_map, fh, entry_id);
hashmap_delete(ctx.fh_map, fh, entry_id);
free(fh);
}
@ -493,8 +493,7 @@ bm_fh_new (
.id = id,
.refcount = 1,
};
union hashmap_key key = { .u64 = id };
*hashmap_insert(ctx.fh_map, key, hashcode) = fh;
hashmap_insert(ctx.fh_map, hashcode, fh);
return fh;
}

View file

@ -155,14 +155,14 @@ count_tz (
*/
static int
find_entry (
struct hashmap const *h,
struct hashmap const *map,
void const *entry,
struct bucket **home_ptr
) {
unsigned exp = h->exp;
unsigned long hashcode = h->entry_hash(entry);
unsigned exp = map->exp;
unsigned long hashcode = map->entry_hash(entry);
size_t hash_idx = HASH_TO_IDX(hashcode, exp);
struct bucket *home = h->buckets + hash_idx;
struct bucket *home = map->buckets + hash_idx;
unsigned long hop = home->bits;
unsigned long hash_mask = BUCKET_HASH_MASK(exp);
@ -172,10 +172,10 @@ find_entry (
debug_assert(hop_idx < exp);
struct bucket *b = home + hop_idx;
if ((b->bits & hash_mask) != (hashcode << h->exp)) {
if ((b->bits & hash_mask) != (hashcode << map->exp)) {
continue;
}
if (entry != h->buckets[b - h->buckets].entry) {
if (entry != map->buckets[b - map->buckets].entry) {
continue;
}
@ -241,10 +241,10 @@ make_room (
static int
rehash (
struct hashmap *h,
struct hashmap *map,
bool grow
) {
unsigned new_exp = h->exp;
unsigned new_exp = map->exp;
if (grow) {
if (unlikely(++new_exp > EXP_MAX)) {
log_puts("rehash(): hashmap size exceeds max limit");
@ -257,9 +257,9 @@ rehash (
size_t new_nbuckets = BUCKET_CNT(new_exp);
struct bucket *new_buckets = xcalloc(new_nbuckets, sizeof(struct bucket));
struct bucket *old_buckets_end = h->buckets + h->num_buckets;
unsigned long new_hop_mask = BUCKET_HOP_MASK(new_exp);
for (struct bucket *old_b = h->buckets; old_b < old_buckets_end; ++old_b) {
struct bucket *old_b_end = map->buckets + map->num_buckets;
unsigned long new_hop_mask = BUCKET_HOP_MASK(new_exp);
for (struct bucket *old_b = map->buckets; old_b < old_b_end; ++old_b) {
void *old_e = old_b->entry;
if (old_e == NULL) {
continue;
@ -267,7 +267,7 @@ rehash (
// Cannot trivially deduce hashcode from old hash fragment,
// since we have to find its home bucket.
unsigned long hashcode = h->entry_hash(old_e);
unsigned long hashcode = map->entry_hash(old_e);
size_t new_hash_idx = HASH_TO_IDX(hashcode, new_exp);
struct bucket *new_home = new_buckets + new_hash_idx;
@ -283,10 +283,10 @@ rehash (
new_b->entry = old_e;
}
free(h->buckets);
h->buckets = new_buckets;
h->num_buckets = new_nbuckets;
h->exp = new_exp;
free(map->buckets);
map->buckets = new_buckets;
map->num_buckets = new_nbuckets;
map->exp = new_exp;
return 0;
fail:
@ -328,34 +328,34 @@ hashmap_create (
void
hashmap_destroy (
struct hashmap *h
struct hashmap *map
) {
if (h == NULL) {
if (map == NULL) {
return;
}
free(h->buckets);
free(h);
free(map->buckets);
free(map);
}
void
hashmap_foreach (
struct hashmap const *h,
struct hashmap const *map,
hashmap_walk_func *walk_func,
void *user_data
) {
struct bucket *end = h->buckets + h->num_buckets;
for (struct bucket *b = h->buckets; b < end; ++b) {
struct bucket *end = map->buckets + map->num_buckets;
for (struct bucket *b = map->buckets; b < end; ++b) {
void *entry = b->entry;
if (entry == NULL) {
continue;
}
walk_func(b->entry, user_data);
walk_func(user_data, b->entry);
}
}
void
hashmap_entry_delete (
hashmap_delete (
struct hashmap *h,
void const *entry,
long entry_id
@ -386,42 +386,44 @@ hashmap_entry_delete (
}
}
void **
void
hashmap_insert (
struct hashmap *h,
union hashmap_key key,
unsigned long hashcode
struct hashmap *map,
unsigned long hashcode,
void *entry
) {
unsigned exp = h->exp;
unsigned exp = map->exp;
size_t hash_idx = HASH_TO_IDX(hashcode, exp);
struct bucket *home = h->buckets + hash_idx;
struct bucket *home = map->buckets + hash_idx;
int hop_idx = make_room(home, h->buckets + h->num_buckets, exp);
int hop_idx = make_room(home, map->buckets + map->num_buckets, exp);
if (unlikely(hop_idx < 0)) {
debug_printf("hashmap_insert(): rehashing (%zu/%zu)",
h->num_used, h->num_buckets - (exp - 1));
xassert(0 == rehash(h, true));
return hashmap_insert(h, key, hashcode);
map->num_used, map->num_buckets - (exp - 1));
xassert(0 == rehash(map, true));
hashmap_insert(map, hashcode, entry);
return;
}
BIT_SET(home->bits, hop_idx);
struct bucket *b = home + hop_idx;
b->bits = (b->bits & BUCKET_HOP_MASK(exp)) | (hashcode << exp);
++h->num_used;
return &b->entry;
++map->num_used;
debug_assert(entry != NULL);
b->entry = entry;
}
void *
hashmap_search (
struct hashmap const *h,
struct hashmap const *map,
union hashmap_key key,
unsigned long hashcode,
unsigned long *entry_id_ptr
) {
unsigned exp = h->exp;
unsigned exp = map->exp;
size_t hash_idx = HASH_TO_IDX(hashcode, exp);
struct bucket *home = h->buckets + hash_idx;
struct bucket *home = map->buckets + hash_idx;
unsigned long hop = home->bits;
unsigned long hash_mask = BUCKET_HASH_MASK(exp);
@ -438,7 +440,7 @@ hashmap_search (
}
void *e = b->entry;
debug_assert(e != NULL);
if (0 != h->entry_comp(key, e)) {
if (0 != map->entry_comp(key, e)) {
continue;
}
if (entry_id_ptr != NULL) {

View file

@ -33,8 +33,8 @@ union hashmap_key {
};
typedef void (hashmap_walk_func) (
void *entry,
void *user_data
void *user_data,
void *entry
);
/**
@ -67,7 +67,7 @@ hashmap_create (
void
hashmap_destroy (
struct hashmap *h
struct hashmap *map
);
/**
@ -76,7 +76,7 @@ hashmap_destroy (
*/
void
hashmap_foreach (
struct hashmap const *h,
struct hashmap const *map,
hashmap_walk_func *walk_func,
void *user_data
);
@ -95,7 +95,7 @@ hashmap_foreach (
*/
void *
hashmap_search (
struct hashmap const *h,
struct hashmap const *map,
union hashmap_key key,
unsigned long hashcode,
unsigned long *entry_id_ptr
@ -105,16 +105,12 @@ hashmap_search (
* Insert an entry into the hashmap.
*
* Invalidates all entry IDs given by previous hashmap_search() calls.
*
* Returns a pointer to the inserted entry.
* The entry must be set to a non-NULL value using this pointer
* prior to any further search/insert/delete calls on this hashmap.
*/
void **
void
hashmap_insert (
struct hashmap *h,
union hashmap_key key,
unsigned long hashcode
struct hashmap *map,
unsigned long hashcode,
void *entry
);
/**
@ -124,12 +120,10 @@ hashmap_insert (
* The entry_id argument should either be the value given by the
* hashmap_search() or hashmap_insert() function call where the
* entry is returned from, or -1 (less efficient).
*
* Unlike hashmap_insert(), previously entry IDs are not affected.
*/
void
hashmap_entry_delete (
struct hashmap *h,
hashmap_delete (
struct hashmap *map,
void const *entry,
long entry_id
);