diff options
author | Caio Marcelo de Oliveira Filho <[email protected]> | 2019-06-10 12:10:54 -0700 |
---|---|---|
committer | Caio Marcelo de Oliveira Filho <[email protected]> | 2019-06-12 15:57:16 -0700 |
commit | eb41ce1b012f24fc7cba664dcc12129342e26843 (patch) | |
tree | f4115acb7fb1da2c84d759bd2919ac2892cd4d0f | |
parent | c129cb38613be79198ff57987d5b419f8b04973d (diff) |
util/hash_table: Properly handle the NULL key in hash_table_u64
The hash_table_u64 should support any uint64_t as input. It does
special handling for the "deleted" key, storing the data in the table
itself; do the same for the "freed" key.
Fixes: b38dab101ca "util/hash_table: Assert that keys are not reserved pointers"
Reviewed-by: Lionel Landwerlin <[email protected]>
Reviewed-by: Kenneth Graunke <[email protected]>
-rw-r--r-- | src/util/hash_table.c | 41 | ||||
-rw-r--r-- | src/util/hash_table.h | 1 |
2 files changed, 37 insertions, 5 deletions
diff --git a/src/util/hash_table.c b/src/util/hash_table.c index a764fabbf05..58104abd739 100644 --- a/src/util/hash_table.c +++ b/src/util/hash_table.c @@ -628,9 +628,12 @@ key_u64_equals(const void *a, const void *b) return aa->value == bb->value; } +#define FREED_KEY_VALUE 0 + struct hash_table_u64 * _mesa_hash_table_u64_create(void *mem_ctx) { + STATIC_ASSERT(FREED_KEY_VALUE != DELETED_KEY_VALUE); struct hash_table_u64 *ht; ht = CALLOC_STRUCT(hash_table_u64); @@ -661,18 +664,33 @@ _mesa_hash_table_u64_destroy(struct hash_table_u64 *ht, if (ht->deleted_key_data) { if (delete_function) { struct hash_table *table = ht->table; - struct hash_entry deleted_entry; + struct hash_entry entry; /* Create a fake entry for the delete function. */ - deleted_entry.hash = table->key_hash_function(table->deleted_key); - deleted_entry.key = table->deleted_key; - deleted_entry.data = ht->deleted_key_data; + entry.hash = table->key_hash_function(table->deleted_key); + entry.key = table->deleted_key; + entry.data = ht->deleted_key_data; - delete_function(&deleted_entry); + delete_function(&entry); } ht->deleted_key_data = NULL; } + if (ht->freed_key_data) { + if (delete_function) { + struct hash_table *table = ht->table; + struct hash_entry entry; + + /* Create a fake entry for the delete function. */ + entry.hash = table->key_hash_function(uint_key(FREED_KEY_VALUE)); + entry.key = uint_key(FREED_KEY_VALUE); + entry.data = ht->freed_key_data; + + delete_function(&entry); + } + ht->freed_key_data = NULL; + } + _mesa_hash_table_destroy(ht->table, delete_function); free(ht); } @@ -681,6 +699,11 @@ void _mesa_hash_table_u64_insert(struct hash_table_u64 *ht, uint64_t key, void *data) { + if (key == FREED_KEY_VALUE) { + ht->freed_key_data = data; + return; + } + if (key == DELETED_KEY_VALUE) { ht->deleted_key_data = data; return; @@ -715,6 +738,9 @@ _mesa_hash_table_u64_search(struct hash_table_u64 *ht, uint64_t key) { struct hash_entry *entry; + if (key == FREED_KEY_VALUE) + return ht->freed_key_data; + if (key == DELETED_KEY_VALUE) return ht->deleted_key_data; @@ -730,6 +756,11 @@ _mesa_hash_table_u64_remove(struct hash_table_u64 *ht, uint64_t key) { struct hash_entry *entry; + if (key == FREED_KEY_VALUE) { + ht->freed_key_data = NULL; + return; + } + if (key == DELETED_KEY_VALUE) { ht->deleted_key_data = NULL; return; diff --git a/src/util/hash_table.h b/src/util/hash_table.h index c808a06d428..be7b50ff1fe 100644 --- a/src/util/hash_table.h +++ b/src/util/hash_table.h @@ -173,6 +173,7 @@ hash_table_call_foreach(struct hash_table *ht, */ struct hash_table_u64 { struct hash_table *table; + void *freed_key_data; void *deleted_key_data; }; |