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:
committed by
Marge Bot
parent
759cc91450
commit
31e546a762
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user