util/hash_table: add u64 foreach macro

needs some nontrivial wrapping but can mostly fallback to the regular impl.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27762>
This commit is contained in:
Alyssa Rosenzweig 2024-02-22 13:34:52 -04:00 committed by Marge Bot
parent cc1501628f
commit d964f57a48
3 changed files with 69 additions and 0 deletions

View file

@ -57,6 +57,7 @@ ForEachMacros:
- hash_table_foreach
- hash_table_foreach_remove
- hash_table_u64_foreach
- rb_tree_foreach
- rb_tree_foreach_rev

View file

@ -960,3 +960,49 @@ _mesa_hash_table_u64_remove(struct hash_table_u64 *ht, uint64_t key)
FREE(_key);
}
}
/*
* Iterates in order ("freed key", "deleted key", regular entries...)
*/
struct hash_entry_u64
_mesa_hash_table_u64_next_entry(struct hash_table_u64 *ht,
struct hash_entry_u64 *ent)
{
/* First entry: freed key */
if (!ent && ht->freed_key_data) {
return (struct hash_entry_u64){
.key = FREED_KEY_VALUE,
.data = ht->freed_key_data,
};
}
/* Second entry: deleted key */
if ((!ent || ent->key == FREED_KEY_VALUE) && ht->deleted_key_data) {
return (struct hash_entry_u64){
.key = DELETED_KEY_VALUE,
.data = ht->deleted_key_data,
};
}
/* All other entries: regular */
struct hash_entry *next =
_mesa_hash_table_next_entry(ht->table, ent ? ent->_entry : NULL);
if (!next)
return (struct hash_entry_u64){.data = NULL};
uint64_t key;
if (sizeof(void *) == 8) {
key = (uintptr_t)next->key;
} else {
const struct hash_key_u64 *_key = next->key;
key = _key->value;
}
return (struct hash_entry_u64){
.key = key,
.data = next->data,
._entry = next,
};
}

View file

@ -171,6 +171,12 @@ struct hash_table_u64 {
void *deleted_key_data;
};
struct hash_entry_u64 {
uint64_t key;
void *data;
struct hash_entry *_entry;
};
struct hash_table_u64 *
_mesa_hash_table_u64_create(void *mem_ctx);
@ -190,6 +196,22 @@ _mesa_hash_table_u64_remove(struct hash_table_u64 *ht, uint64_t key);
void
_mesa_hash_table_u64_clear(struct hash_table_u64 *ht);
struct hash_entry_u64
_mesa_hash_table_u64_next_entry(struct hash_table_u64 *ht,
struct hash_entry_u64 *ent);
/**
* This foreach function is safe against deletion (which just replaces
* an entry's data with the deleted marker), but not against insertion
* (which may rehash the table, making entry a dangling pointer).
*/
#define hash_table_u64_foreach(ht, entry) \
for (struct hash_entry_u64 entry = \
_mesa_hash_table_u64_next_entry(ht, NULL); \
entry.data != NULL; \
entry = _mesa_hash_table_u64_next_entry(ht, &entry))
#ifdef __cplusplus
} /* extern C */
#endif