[glib] Preserve consistency when removing all nodes from a hash table



commit 5d7b67a6c361f747c8ac32d18248cc0923fe73aa
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu May 26 21:52:50 2011 -0400

    Preserve consistency when removing all nodes from a hash table
    
    During the recent refactorings of GHashTable a bug was introduced
    where removing all nodes from a hash table would leave tombstones
    behind, but make the counts appear like there are none.
    
    Reported and tracked down by Carlos Garnacho,
    https://bugzilla.gnome.org/show_bug.cgi?id=651141
    
    This commit also adds a test that checks the internal consistency
    of GHashTable over several insert/remove/remove-all operations.

 glib/ghash.c |   14 ++++++++++----
 1 files changed, 10 insertions(+), 4 deletions(-)
---
diff --git a/glib/ghash.c b/glib/ghash.c
index eac637f..ecf8dfa 100644
--- a/glib/ghash.c
+++ b/glib/ghash.c
@@ -200,8 +200,10 @@
 
 #define HASH_TABLE_MIN_SHIFT 3  /* 1 << 3 == 8 buckets */
 
-#define HASH_IS_UNUSED(h_) ((h_) == 0)
-#define HASH_IS_TOMBSTONE(h_) ((h_) == 1)
+#define UNUSED_HASH_VALUE 0
+#define TOMBSTONE_HASH_VALUE 1
+#define HASH_IS_UNUSED(h_) ((h_) == UNUSED_HASH_VALUE)
+#define HASH_IS_TOMBSTONE(h_) ((h_) == TOMBSTONE_HASH_VALUE)
 #define HASH_IS_REAL(h_) ((h_) >= 2)
 
 struct _GHashTable
@@ -426,7 +428,7 @@ g_hash_table_remove_node (GHashTable   *hash_table,
   value = hash_table->values[i];
 
   /* Erect tombstone */
-  hash_table->hashes[i] = 1;
+  hash_table->hashes[i] = TOMBSTONE_HASH_VALUE;
 
   /* Be GC friendly */
   hash_table->keys[i] = NULL;
@@ -482,7 +484,7 @@ g_hash_table_remove_all_nodes (GHashTable *hash_table,
           key = hash_table->keys[i];
           value = hash_table->values[i];
 
-          hash_table->hashes[i] = 0;
+          hash_table->hashes[i] = UNUSED_HASH_VALUE;
           hash_table->keys[i] = NULL;
           hash_table->values[i] = NULL;
 
@@ -492,6 +494,10 @@ g_hash_table_remove_all_nodes (GHashTable *hash_table,
           if (hash_table->value_destroy_func != NULL)
             hash_table->value_destroy_func (value);
         }
+      else if (HASH_IS_TOMBSTONE (hash_table->hashes[i]))
+        {
+          hash_table->hashes[i] = UNUSED_HASH_VALUE;
+        }
     }
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]