mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-19 08:50:25 +01:00
util/set: add macro for destructively iterating set entries
a common usage for sets is for tracking exactly one instance of a pointer for a given period of time, after which the set'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:
parent
539c7ca508
commit
759cc91450
3 changed files with 46 additions and 0 deletions
|
|
@ -560,6 +560,27 @@ _mesa_set_remove_key(struct set *set, const void *key)
|
|||
_mesa_set_remove(set, _mesa_set_search(set, key));
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is an iterator over the set when no deleted entries are present.
|
||||
*
|
||||
* Pass in NULL for the first entry, as in the start of a for loop.
|
||||
*/
|
||||
struct set_entry *
|
||||
_mesa_set_next_entry_unsafe(const struct set *ht, struct set_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_set_next_entry_unsafe(ht, entry);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is an iterator over the hash table.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -111,6 +111,8 @@ _mesa_set_remove_key(struct set *set, const void *key);
|
|||
|
||||
struct set_entry *
|
||||
_mesa_set_next_entry(const struct set *set, struct set_entry *entry);
|
||||
struct set_entry *
|
||||
_mesa_set_next_entry_unsafe(const struct set *set, struct set_entry *entry);
|
||||
|
||||
struct set_entry *
|
||||
_mesa_set_random_entry(struct set *set,
|
||||
|
|
@ -132,6 +134,15 @@ _mesa_set_intersects(struct set *a, struct set *b);
|
|||
entry != NULL; \
|
||||
entry = _mesa_set_next_entry(set, entry))
|
||||
|
||||
/**
|
||||
* This foreach function destroys the table as it iterates.
|
||||
* It is not safe to use when inserting or removing entries.
|
||||
*/
|
||||
#define set_foreach_remove(set, entry) \
|
||||
for (struct set_entry *entry = _mesa_set_next_entry_unsafe(set, NULL); \
|
||||
(set)->entries; \
|
||||
entry->hash = 0, entry->key = (void*)NULL, (set)->entries--, entry = _mesa_set_next_entry_unsafe(set, entry))
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -58,6 +58,20 @@ TEST(set, basic)
|
|||
GTEST_FAIL();
|
||||
}
|
||||
|
||||
_mesa_set_add(s, a);
|
||||
_mesa_set_add(s, b);
|
||||
EXPECT_EQ(s->entries, 2);
|
||||
unsigned count = s->entries;
|
||||
set_foreach_remove(s, he) {
|
||||
EXPECT_TRUE(he->key == a || he->key == b);
|
||||
EXPECT_EQ(s->entries, count--);
|
||||
EXPECT_EQ(s->deleted_entries, 0);
|
||||
}
|
||||
EXPECT_EQ(s->entries, 0);
|
||||
set_foreach(s, he) {
|
||||
GTEST_FAIL();
|
||||
}
|
||||
|
||||
_mesa_set_destroy(s, NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue