util/hash_table: add macro for destructively iterating entries

a common usage for hash tables is for tracking exactly one instance of a pointer
for a given period of time, after which the table's entries are purged and it
is reused

this macro enables the purge phase of such usage to reset the table to a
pristine state, avoiding future rehashing due to ballooning of deleted entries

Reviewed-by: Adam Jackson <ajax@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8498>
This commit is contained in:
Mike Blumenkrantz
2021-01-12 14:49:48 -05:00
committed by Marge Bot
parent 759cc91450
commit 31e546a762
3 changed files with 42 additions and 0 deletions
+21
View File
@@ -524,6 +524,27 @@ void _mesa_hash_table_remove_key(struct hash_table *ht,
_mesa_hash_table_remove(ht, _mesa_hash_table_search(ht, key));
}
/**
* This function is an iterator over the hash_table when no deleted entries are present.
*
* Pass in NULL for the first entry, as in the start of a for loop.
*/
struct hash_entry *
_mesa_hash_table_next_entry_unsafe(const struct hash_table *ht, struct hash_entry *entry)
{
assert(!ht->deleted_entries);
if (!ht->entries)
return NULL;
if (entry == NULL)
entry = ht->table;
else
entry = entry + 1;
if (entry != ht->table + ht->size)
return entry->key ? entry : _mesa_hash_table_next_entry_unsafe(ht, entry);
return NULL;
}
/**
* This function is an iterator over the hash table.
*
+11
View File
@@ -103,6 +103,8 @@ void _mesa_hash_table_remove_key(struct hash_table *ht,
struct hash_entry *_mesa_hash_table_next_entry(struct hash_table *ht,
struct hash_entry *entry);
struct hash_entry *_mesa_hash_table_next_entry_unsafe(const struct hash_table *ht,
struct hash_entry *entry);
struct hash_entry *
_mesa_hash_table_random_entry(struct hash_table *ht,
bool (*predicate)(struct hash_entry *entry));
@@ -136,6 +138,15 @@ _mesa_hash_table_reserve(struct hash_table *ht, unsigned size);
for (struct hash_entry *entry = _mesa_hash_table_next_entry(ht, NULL); \
entry != NULL; \
entry = _mesa_hash_table_next_entry(ht, entry))
/**
* This foreach function destroys the table as it iterates.
* It is not safe to use when inserting or removing entries.
*/
#define hash_table_foreach_remove(ht, entry) \
for (struct hash_entry *entry = _mesa_hash_table_next_entry_unsafe(ht, NULL); \
(ht)->entries; \
entry->hash = 0, entry->key = (void*)NULL, entry->data = NULL, \
(ht)->entries--, entry = _mesa_hash_table_next_entry_unsafe(ht, entry))
static inline void
hash_table_call_foreach(struct hash_table *ht,
+10
View File
@@ -93,6 +93,16 @@ int main()
assert(0);
}
for (i = 0; i < SIZE; ++i) {
flags[i] = false;
_mesa_hash_table_insert(ht, make_key(i), &flags[i]);
}
hash_table_foreach_remove(ht, entry) {
assert(key_id(entry->key) < SIZE);
}
assert(!ht->entries);
assert(!ht->deleted_entries);
_mesa_hash_table_destroy(ht, NULL);
return 0;