[Mesa-dev] [PATCH 08/14] util: Implement the insertion functionality

Thomas Helland thomashelland90 at gmail.com
Sun Jan 1 18:37:52 UTC 2017


---
 src/util/non_replacing_hash_table.c | 41 +++++++++++++++++++++++++++++++------
 1 file changed, 35 insertions(+), 6 deletions(-)

diff --git a/src/util/non_replacing_hash_table.c b/src/util/non_replacing_hash_table.c
index 1730b1ee0d..a4c57e9349 100644
--- a/src/util/non_replacing_hash_table.c
+++ b/src/util/non_replacing_hash_table.c
@@ -317,12 +317,14 @@ hash_table_insert(struct hash_table *ht, uint32_t hash,
             break;
       }
 
-      /* Implement replacement when another insert happens
-       * with a matching key.  This is a relatively common
-       * feature of hash tables, with the alternative
-       * generally being "insert the new value as well, and
-       * return it first when the key is searched for".
-       *
+      /* When another insert happens with a matching key,
+       * we check if there is a chain of matchin keys.
+       * If there is, we follow this chain until the end.
+       * We then do a linear probe until we find an empty spot.
+       * We insert the entry, and update the entry at our past
+       * matching key's position to point to the positon of
+       * the newly added data.
+       * 
        * Note that the hash table doesn't have a delete
        * callback.  If freeing of old data pointers is
        * required to avoid memory leaks, perform a search
@@ -331,8 +333,35 @@ hash_table_insert(struct hash_table *ht, uint32_t hash,
       if (!entry_is_deleted(ht, entry) &&
           entry->hash == hash &&
           ht->key_equals_function(key, entry->key)) {
+         struct hash_entry *old_entry = entry;
+
+         /* Follow the chain of matching key's to the end */
+         while (old_entry->next_data != 0) {
+            entry = ht->table + old_entry->next_data;
+            /* We might have deleted the last entry, and have a
+             * dangling reference, so check that the keys match
+             * before we continue on traversing through the chain.
+             * If the key's don't match we undo our change of entry.
+             */
+            if (!ht->key_equals_function(key, entry->key)) {
+               entry = old_entry;
+               continue;
+            }
+            old_entry = entry;
+         }
+
+         /* Do a linear search for an empty spot in the table */
+         while (!entry_is_free(entry)) {
+            entry = ht->table + ((entry - ht->table + 1) % ht->size);
+         }
+
+         /* Now that we have an empty spot we add our data */
          entry->key = key;
          entry->data = data;
+         ht->entries++;
+
+         /* And update the matching key chain */
+         old_entry->next_data = entry - ht->table;
          return entry;
       }
 
-- 
2.11.0



More information about the mesa-dev mailing list