{
gpointer key;
gpointer value;
+ guint key_hash;
GHashNode *next;
};
static void g_hash_table_resize (GHashTable *hash_table);
static GHashNode** g_hash_table_lookup_node (GHashTable *hash_table,
- gconstpointer key);
+ gconstpointer key,
+ guint *hash_return);
static GHashNode* g_hash_node_new (gpointer key,
- gpointer value);
+ gpointer value,
+ guint key_hash);
static void g_hash_node_destroy (GHashNode *hash_node,
GDestroyNotify key_destroy_func,
GDestroyNotify value_destroy_func);
static inline GHashNode**
g_hash_table_lookup_node (GHashTable *hash_table,
- gconstpointer key)
+ gconstpointer key,
+ guint *hash_return)
{
GHashNode **node;
+ guint hash_value;
+
+ hash_value = (* hash_table->hash_func) (key);
+ node = &hash_table->nodes[hash_value % hash_table->size];
- node = &hash_table->nodes
- [(* hash_table->hash_func) (key) % hash_table->size];
+ if (hash_return)
+ *hash_return = hash_value;
/* Hash table lookup needs to be fast.
* We therefore remove the extra conditional of testing
* whether to call the key_equal_func or not from
* the inner loop.
+ *
+ * Additional optimisation: first check if our full hash
+ * values are equal so we can avoid calling the full-blown
+ * key equality function in most cases.
*/
if (hash_table->key_equal_func)
- while (*node && !(*hash_table->key_equal_func) ((*node)->key, key))
+ while (*node && (((*node)->key_hash != hash_value) ||
+ !(*hash_table->key_equal_func) ((*node)->key, key)))
node = &(*node)->next;
else
while (*node && (*node)->key != key)
node = &(*node)->next;
-
+
return node;
}
g_return_val_if_fail (hash_table != NULL, NULL);
- node = *g_hash_table_lookup_node (hash_table, key);
+ node = *g_hash_table_lookup_node (hash_table, key, NULL);
return node ? node->value : NULL;
}
g_return_val_if_fail (hash_table != NULL, FALSE);
- node = *g_hash_table_lookup_node (hash_table, lookup_key);
+ node = *g_hash_table_lookup_node (hash_table, lookup_key, NULL);
if (node)
{
gpointer value)
{
GHashNode **node;
+ guint key_hash;
g_return_if_fail (hash_table != NULL);
g_return_if_fail (hash_table->ref_count > 0);
- node = g_hash_table_lookup_node (hash_table, key);
+ node = g_hash_table_lookup_node (hash_table, key, &key_hash);
if (*node)
{
}
else
{
- *node = g_hash_node_new (key, value);
+ *node = g_hash_node_new (key, value, key_hash);
hash_table->nnodes++;
G_HASH_TABLE_RESIZE (hash_table);
}
gpointer value)
{
GHashNode **node;
+ guint key_hash;
g_return_if_fail (hash_table != NULL);
g_return_if_fail (hash_table->ref_count > 0);
- node = g_hash_table_lookup_node (hash_table, key);
+ node = g_hash_table_lookup_node (hash_table, key, &key_hash);
if (*node)
{
}
else
{
- *node = g_hash_node_new (key, value);
+ *node = g_hash_node_new (key, value, key_hash);
hash_table->nnodes++;
G_HASH_TABLE_RESIZE (hash_table);
}
g_return_val_if_fail (hash_table != NULL, FALSE);
- node = g_hash_table_lookup_node (hash_table, key);
+ node = g_hash_table_lookup_node (hash_table, key, NULL);
if (*node)
{
dest = *node;
g_return_val_if_fail (hash_table != NULL, FALSE);
- node = g_hash_table_lookup_node (hash_table, key);
+ node = g_hash_table_lookup_node (hash_table, key, NULL);
if (*node)
{
dest = *node;
{
next = node->next;
- hash_val = (* hash_table->hash_func) (node->key) % new_size;
+ hash_val = node->key_hash % new_size;
node->next = new_nodes[hash_val];
new_nodes[hash_val] = node;
static GHashNode*
g_hash_node_new (gpointer key,
- gpointer value)
+ gpointer value,
+ guint key_hash)
{
GHashNode *hash_node = g_slice_new (GHashNode);
hash_node->key = key;
hash_node->value = value;
+ hash_node->key_hash = key_hash;
hash_node->next = NULL;
return hash_node;