/* * From Knuth -- a good choice for hash/rehash values is p, p-2 where * p and p-2 are both prime. These tables are sized to have an extra 10% * free to avoid exponential performance degradation as the hash table fills
*/
/** * Frees the given set. * * If delete_function is passed, it gets called on each entry present before * freeing.
*/ void
_mesa_set_destroy(struct set *ht, void (*delete_function)(struct set_entry *entry))
{ if (!ht) return;
/** * Clears all values from the given set. * * If delete_function is passed, it gets called on each entry present before * the set is cleared.
*/ void
_mesa_set_clear(struct set *set, void (*delete_function)(struct set_entry *entry))
{ if (!set) return;
/** * Finds a set entry with the given key and hash of that key. * * Returns NULL if no entry is found.
*/ staticstruct set_entry *
set_search(conststruct set *ht, uint32_t hash, constvoid *key)
{
assert(!key_pointer_is_reserved(key));
void
_mesa_set_resize(struct set *set, uint32_t entries)
{ /* You can't shrink a set below its number of entries */ if (set->entries > entries)
entries = set->entries;
unsigned size_index = 0; while (hash_sizes[size_index].max_entries < entries)
size_index++;
set_rehash(set, size_index);
}
/** * Find a matching entry for the given key, or insert it if it doesn't already * exist. * * Note that insertion may rearrange the table on a resize or rehash, * so previously found hash_entries are no longer valid after this function.
*/ staticstruct set_entry *
set_search_or_add(struct set *ht, uint32_t hash, constvoid *key, bool *found)
{ struct set_entry *available_entry = NULL;
if (!entry_is_present(entry)) { /* Stash the first available entry we find */ if (available_entry == NULL)
available_entry = entry; if (entry_is_free(entry)) break;
}
if (!entry_is_deleted(entry) &&
entry->hash == hash &&
ht->key_equals_function(key, entry->key)) { if (found)
*found = true; return entry;
}
hash_address = hash_address + double_hash; if (hash_address >= size)
hash_address -= size;
} while (hash_address != start_address);
if (available_entry) { /* There is no matching entry, create it. */ if (entry_is_deleted(available_entry))
ht->deleted_entries--;
available_entry->hash = hash;
available_entry->key = key;
ht->entries++; if (found)
*found = false; return available_entry;
}
/* We could hit here if a required resize failed. An unchecked-malloc * application could ignore this result.
*/ return NULL;
}
/** * Inserts the key with the given hash into the table. * * Note that insertion may rearrange the table on a resize or rehash, * so previously found hash_entries are no longer valid after this function.
*/ staticstruct set_entry *
set_add(struct set *ht, uint32_t hash, constvoid *key)
{ struct set_entry *entry = set_search_or_add(ht, hash, key, NULL);
if (unlikely(!entry)) return NULL;
/* Note: If a matching entry already exists, this will replace it. 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". * * Note that the hash table doesn't have a delete callback. If freeing of * old keys is required to avoid memory leaks, use the alternative * _mesa_set_search_or_add function and implement the replacement yourself.
*/
entry->key = key; return entry;
}
/* This implements the replacement, same as _mesa_set_add(). The user will * be notified if we're overwriting a found entry.
*/
entry->key = key; return entry;
}
/** * This function deletes the given hash table entry. * * Note that deletion doesn't otherwise modify the table, so an iteration over * the table deleting entries is safe.
*/ void
_mesa_set_remove(struct set *ht, struct set_entry *entry)
{ if (!entry) return;
/** * Removes the entry with the corresponding key, if exists.
*/ void
_mesa_set_remove_key(struct set *set, constvoid *key)
{
_mesa_set_remove(set, _mesa_set_search(set, key));
}
/** * This function is an iterator over the hash table. * * Pass in NULL for the first entry, as in the start of a for loop. Note that * an iteration over the table is O(table_size) not O(entries).
*/ struct set_entry *
_mesa_set_next_entry(conststruct set *ht, struct set_entry *entry)
{ if (entry == NULL)
entry = ht->table; else
entry = entry + 1;
for (; entry != ht->table + ht->size; entry++) { if (entry_is_present(entry)) { return entry;
}
}
return NULL;
}
struct set_entry *
_mesa_set_random_entry(struct set *ht, int (*predicate)(struct set_entry *entry))
{ struct set_entry *entry;
uint32_t i = rand() % ht->size;
/** * Helper to create a set with pointer keys.
*/ struct set *
_mesa_pointer_set_create(void *mem_ctx)
{ return _mesa_set_create(mem_ctx, _mesa_hash_pointer,
_mesa_key_pointer_equal);
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.