mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-10 07:00:24 +01:00
hash: Compare hash values before calling keys_equal
If the hash value is different, the keys cannot be equal. Testing this beforehand can avoid a few function calls and shares this optimization across all cairo-hash uses.
This commit is contained in:
parent
02665975d3
commit
400d055f3c
5 changed files with 32 additions and 41 deletions
|
|
@ -127,6 +127,25 @@ struct _cairo_hash_table {
|
|||
unsigned long iterating; /* Iterating, no insert, no resize */
|
||||
};
|
||||
|
||||
/**
|
||||
* _cairo_hash_table_uid_keys_equal:
|
||||
* @key_a: the first key to be compared
|
||||
* @key_b: the second key to be compared
|
||||
*
|
||||
* Provides a cairo_hash_keys_equal_func_t which always returns
|
||||
* %TRUE. This is useful to create hash tables using keys whose hash
|
||||
* completely describes the key, because in this special case
|
||||
* comparing the hashes is sufficient to guarantee that the keys are
|
||||
* equal.
|
||||
*
|
||||
* Return value: %TRUE.
|
||||
**/
|
||||
static cairo_bool_t
|
||||
_cairo_hash_table_uid_keys_equal (const void *key_a, const void *key_b)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_hash_table_create:
|
||||
* @keys_equal: a function to return %TRUE if two keys are equal
|
||||
|
|
@ -139,6 +158,9 @@ struct _cairo_hash_table {
|
|||
* _cairo_hash_table_remove), and other times both a key and a value
|
||||
* will be necessary, (as in _cairo_hash_table_insert).
|
||||
*
|
||||
* If @keys_equal is %NULL, two keys will be considered equal if and
|
||||
* only if their hashes are equal.
|
||||
*
|
||||
* See #cairo_hash_entry_t for more details.
|
||||
*
|
||||
* Return value: the new hash table or %NULL if out of memory.
|
||||
|
|
@ -154,7 +176,10 @@ _cairo_hash_table_create (cairo_hash_keys_equal_func_t keys_equal)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
hash_table->keys_equal = keys_equal;
|
||||
if (keys_equal == NULL)
|
||||
hash_table->keys_equal = _cairo_hash_table_uid_keys_equal;
|
||||
else
|
||||
hash_table->keys_equal = keys_equal;
|
||||
|
||||
hash_table->arrangement = &hash_table_arrangements[0];
|
||||
|
||||
|
|
@ -316,7 +341,7 @@ _cairo_hash_table_lookup (cairo_hash_table_t *hash_table,
|
|||
|
||||
entry = hash_table->entries[idx];
|
||||
if (ENTRY_IS_LIVE (entry)) {
|
||||
if (hash_table->keys_equal (key, entry))
|
||||
if (entry->hash == key->hash && hash_table->keys_equal (key, entry))
|
||||
return entry;
|
||||
} else if (ENTRY_IS_FREE (entry))
|
||||
return NULL;
|
||||
|
|
@ -330,7 +355,7 @@ _cairo_hash_table_lookup (cairo_hash_table_t *hash_table,
|
|||
|
||||
entry = hash_table->entries[idx];
|
||||
if (ENTRY_IS_LIVE (entry)) {
|
||||
if (hash_table->keys_equal (key, entry))
|
||||
if (entry->hash == key->hash && hash_table->keys_equal (key, entry))
|
||||
return entry;
|
||||
} else if (ENTRY_IS_FREE (entry))
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -152,15 +152,6 @@ _cairo_sub_font_glyph_init_key (cairo_sub_font_glyph_t *sub_font_glyph,
|
|||
sub_font_glyph->base.hash = scaled_font_glyph_index;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_sub_font_glyphs_equal (const void *key_a, const void *key_b)
|
||||
{
|
||||
const cairo_sub_font_glyph_t *sub_font_glyph_a = key_a;
|
||||
const cairo_sub_font_glyph_t *sub_font_glyph_b = key_b;
|
||||
|
||||
return sub_font_glyph_a->base.hash == sub_font_glyph_b->base.hash;
|
||||
}
|
||||
|
||||
static cairo_sub_font_glyph_t *
|
||||
_cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index,
|
||||
unsigned int subset_id,
|
||||
|
|
@ -314,7 +305,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
|
|||
sub_font->num_glyphs_in_latin_subset = 0;
|
||||
sub_font->max_glyphs_per_subset = max_glyphs_per_subset;
|
||||
|
||||
sub_font->sub_font_glyphs = _cairo_hash_table_create (_cairo_sub_font_glyphs_equal);
|
||||
sub_font->sub_font_glyphs = _cairo_hash_table_create (NULL);
|
||||
if (unlikely (sub_font->sub_font_glyphs == NULL)) {
|
||||
free (sub_font);
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
|
|
|||
|
|
@ -638,9 +638,6 @@ _cairo_scaled_font_keys_equal (const void *abstract_key_a,
|
|||
const cairo_scaled_font_t *key_a = abstract_key_a;
|
||||
const cairo_scaled_font_t *key_b = abstract_key_b;
|
||||
|
||||
if (key_a->hash_entry.hash != key_b->hash_entry.hash)
|
||||
return FALSE;
|
||||
|
||||
return key_a->original_font_face == key_b->original_font_face &&
|
||||
memcmp ((unsigned char *)(&key_a->font_matrix.xx),
|
||||
(unsigned char *)(&key_b->font_matrix.xx),
|
||||
|
|
@ -668,15 +665,6 @@ _cairo_scaled_font_matches (const cairo_scaled_font_t *scaled_font,
|
|||
cairo_font_options_equal (&scaled_font->options, options);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_scaled_glyphs_equal (const void *abstract_a, const void *abstract_b)
|
||||
{
|
||||
const cairo_scaled_glyph_t *a = abstract_a;
|
||||
const cairo_scaled_glyph_t *b = abstract_b;
|
||||
|
||||
return a->hash_entry.hash == b->hash_entry.hash;
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic #cairo_scaled_font_t object management
|
||||
*/
|
||||
|
|
@ -725,7 +713,7 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
|
|||
return status;
|
||||
}
|
||||
|
||||
scaled_font->glyphs = _cairo_hash_table_create (_cairo_scaled_glyphs_equal);
|
||||
scaled_font->glyphs = _cairo_hash_table_create (NULL);
|
||||
if (unlikely (scaled_font->glyphs == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
|
|
|
|||
|
|
@ -500,13 +500,6 @@ _device_flush (void *device)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_xrender_formats_equal (const void *A, const void *B)
|
||||
{
|
||||
const cairo_xcb_xrender_format_t *a = A, *b = B;
|
||||
return a->key.hash == b->key.hash;
|
||||
}
|
||||
|
||||
static void
|
||||
_pluck_xrender_format (void *entry,
|
||||
void *closure)
|
||||
|
|
@ -633,7 +626,7 @@ _cairo_xcb_connection_get (xcb_connection_t *xcb_connection)
|
|||
cairo_list_init (&connection->fonts);
|
||||
cairo_list_init (&connection->screens);
|
||||
cairo_list_init (&connection->link);
|
||||
connection->xrender_formats = _cairo_hash_table_create (_xrender_formats_equal);
|
||||
connection->xrender_formats = _cairo_hash_table_create (NULL);
|
||||
if (connection->xrender_formats == NULL) {
|
||||
CAIRO_MUTEX_FINI (connection->device.mutex);
|
||||
free (connection);
|
||||
|
|
@ -641,7 +634,7 @@ _cairo_xcb_connection_get (xcb_connection_t *xcb_connection)
|
|||
goto unlock;
|
||||
}
|
||||
|
||||
connection->visual_to_xrender_format = _cairo_hash_table_create (_xrender_formats_equal);
|
||||
connection->visual_to_xrender_format = _cairo_hash_table_create (NULL);
|
||||
if (connection->visual_to_xrender_format == NULL) {
|
||||
_cairo_hash_table_destroy (connection->xrender_formats);
|
||||
CAIRO_MUTEX_FINI (connection->device.mutex);
|
||||
|
|
|
|||
|
|
@ -97,9 +97,6 @@ _linear_pattern_cache_entry_equal (const void *A, const void *B)
|
|||
{
|
||||
const struct pattern_cache_entry *a = A, *b = B;
|
||||
|
||||
if (a->key.hash != b->key.hash)
|
||||
return FALSE;
|
||||
|
||||
return _cairo_linear_pattern_equal (&a->pattern.gradient.linear,
|
||||
&b->pattern.gradient.linear);
|
||||
}
|
||||
|
|
@ -109,9 +106,6 @@ _radial_pattern_cache_entry_equal (const void *A, const void *B)
|
|||
{
|
||||
const struct pattern_cache_entry *a = A, *b = B;
|
||||
|
||||
if (a->key.hash != b->key.hash)
|
||||
return FALSE;
|
||||
|
||||
return _cairo_radial_pattern_equal (&a->pattern.gradient.radial,
|
||||
&b->pattern.gradient.radial);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue