Properly handle deleting everything out of a hash table.

This commit is contained in:
Dianne Skoll
2024-12-09 13:59:41 -05:00
parent fd2a61928c
commit 4a2d707654
9 changed files with 200055 additions and 13 deletions

View File

@@ -146,10 +146,12 @@ ClearDedupeTable(void)
e = hash_table_next(&DedupeTable, NULL);
while(e) {
next = hash_table_next(&DedupeTable, e);
hash_table_delete(&DedupeTable, e);
hash_table_delete_no_resize(&DedupeTable, e);
FreeDedupeEntry(e);
e = next;
}
hash_table_free(&DedupeTable);
InitDedupeTable();
}
/***************************************************************/

View File

@@ -339,11 +339,12 @@ hash_table_find_next(hash_table *t, void *obj)
*
* \param t Pointer to a hash_table object
* \param candidate Pointer to an object that is in the table and must be removed from it
* \param resize_ok If non-zero, then it's OK to resize the hash table.
*
* \return 0 on success, -1 on failure
*/
int
hash_table_delete(hash_table *t, void *item)
hash_table_delete_helper(hash_table *t, void *item, int resize_ok)
{
if (!item) {
errno = EINVAL;
@@ -358,10 +359,12 @@ hash_table_delete(hash_table *t, void *item)
if (t->buckets[v] == item) {
t->buckets[v] = l->next;
t->num_entries--;
/* Shrink table for load factor < 1 */
if (t->bucket_choice_index > 0 &&
t->num_entries < NUM_BUCKETS(t) / 2) {
return hash_table_resize(t, -1);
if (resize_ok) {
/* Shrink table for load factor < 1 */
if (t->bucket_choice_index > 0 &&
t->num_entries < NUM_BUCKETS(t) / 2) {
return hash_table_resize(t, -1);
}
}
return 0;
}
@@ -373,9 +376,11 @@ hash_table_delete(hash_table *t, void *item)
l2->next = l->next;
t->num_entries--;
/* Shrink table for load factor < 1 */
if (t->bucket_choice_index > 0 &&
t->num_entries < NUM_BUCKETS(t) / 2) {
return hash_table_resize(t, -1);
if (resize_ok) {
if (t->bucket_choice_index > 0 &&
t->num_entries < NUM_BUCKETS(t) / 2) {
return hash_table_resize(t, -1);
}
}
return 0;
}
@@ -387,6 +392,18 @@ hash_table_delete(hash_table *t, void *item)
return -1;
}
int
hash_table_delete(hash_table *t, void *item)
{
return hash_table_delete_helper(t, item, 1);
}
int
hash_table_delete_no_resize(hash_table *t, void *item)
{
return hash_table_delete_helper(t, item, 0);
}
/**
* \brief Iterate to the next item in a hash table
*

View File

@@ -62,6 +62,7 @@ int hash_table_insert(hash_table *t, void *item);
void *hash_table_find(hash_table *t, void *candidate);
void *hash_table_find_next(hash_table *t, void *obj);
int hash_table_delete(hash_table *t, void *item);
int hash_table_delete_no_resize(hash_table *t, void *item);
void *hash_table_next(hash_table *t, void *cur);
void hash_table_dump_stats(hash_table *t, FILE *fp);
void hash_table_get_stats(hash_table *t, struct hash_table_stats *stat);

View File

@@ -80,7 +80,7 @@ FreeXlateItem(XlateItem *item)
static void
RemoveTranslation(XlateItem *item)
{
hash_table_delete(&TranslationTable, item);
hash_table_delete_no_resize(&TranslationTable, item);
FreeXlateItem(item);
}
@@ -101,6 +101,8 @@ ClearTranslationTable(void)
RemoveTranslation(item);
item = next;
}
hash_table_free(&TranslationTable);
InitTranslationTable();
}
static void

View File

@@ -458,10 +458,12 @@ UnsetAllUserFuncs(void)
f = hash_table_next(&FuncHash, NULL);
while(f) {
next = hash_table_next(&FuncHash, f);
hash_table_delete(&FuncHash, f);
hash_table_delete_no_resize(&FuncHash, f);
DestroyUserFunc(f);
f = next;
}
hash_table_free(&FuncHash);
InitUserFunctions();
}
/***************************************************************/

View File

@@ -753,11 +753,15 @@ void DestroyVars(int all)
next = hash_table_next(&VHashTbl, v);
if (all || !v->preserve) {
DestroyValue(v->v);
hash_table_delete(&VHashTbl, v);
hash_table_delete_no_resize(&VHashTbl, v);
free(v);
}
v = next;
}
if (all) {
hash_table_free(&VHashTbl);
InitVars();
}
}
/***************************************************************/

File diff suppressed because it is too large Load Diff

View File

@@ -1246,6 +1246,8 @@ TRANSLATE DUMP
# Output expression-node stats
DEBUG +s
DO xlat-torture-test.rem
# Don't want Remind to queue reminders
EXIT

100004
tests/xlat-torture-test.rem Normal file

File diff suppressed because it is too large Load Diff