wmem: Add a wmem_map_foreach_remove function

Like wmem_map_remove(), this frees the key/value pair item
in the map but not the key or the value itself (which may
in fact be the same object.) Not generally a problem, as
they'll get freed by the pool. (If someone wants to manage
memory themselves, they should probably be using a GHashTable.)
This commit is contained in:
John Thacker 2022-09-15 23:48:51 -04:00
parent c949c99ad1
commit 819d392aff
4 changed files with 57 additions and 0 deletions

View File

@ -283,6 +283,7 @@ libwsutil.so.0 libwsutil0 #MINVER#
wmem_list_tail@Base 3.5.0
wmem_map_contains@Base 3.5.0
wmem_map_foreach@Base 3.5.0
wmem_map_foreach_remove@Base 4.1.0
wmem_map_get_keys@Base 3.5.0
wmem_map_insert@Base 3.5.0
wmem_map_lookup@Base 3.5.0

View File

@ -408,6 +408,34 @@ wmem_map_foreach(wmem_map_t *map, GHFunc foreach_func, gpointer user_data)
}
}
guint
wmem_map_foreach_remove(wmem_map_t *map, GHRFunc foreach_func, gpointer user_data)
{
wmem_map_item_t **item, *tmp;
unsigned i, deleted = 0;
/* Make sure we have a table */
if (map->table == NULL) {
return 0;
}
for (i = 0; i < CAPACITY(map); i++) {
item = &(map->table[i]);
while (*item) {
if (foreach_func((gpointer)(*item)->key, (gpointer)(*item)->value, user_data)) {
tmp = *item;
*item = tmp->next;
wmem_free(map->data_allocator, tmp);
map->count--;
deleted++;
} else {
item = &((*item)->next);
}
}
}
return deleted;
}
guint
wmem_map_size(wmem_map_t *map)
{

View File

@ -164,6 +164,20 @@ WS_DLL_PUBLIC
void
wmem_map_foreach(wmem_map_t *map, GHFunc foreach_func, gpointer user_data);
/** Run a function against all key/value pairs in the map. If the
* function returns TRUE, then the key/value pair is removed from
* the map. The order of the calls is unpredictable, since it is
* based on the internal storage of data.
*
* @param map The map to use
* @param foreach_func the function to call for each key/value pair
* @param user_data user data to pass to the function
* @return The number of items removed
*/
WS_DLL_PUBLIC
guint
wmem_map_foreach_remove(wmem_map_t *map, GHRFunc foreach_func, gpointer user_data);
/** Return the number of elements of the map.
*
* @param map The map to use

View File

@ -894,6 +894,12 @@ check_val_map(gpointer key _U_, gpointer val, gpointer user_data)
g_assert_true(val == user_data);
}
static gboolean
equal_val_map(gpointer key _U_, gpointer val, gpointer user_data)
{
return val == user_data;
}
static void
wmem_test_map(void)
{
@ -990,6 +996,9 @@ wmem_test_map(void)
}
wmem_map_foreach(map, check_val_map, GINT_TO_POINTER(2));
wmem_map_foreach_remove(map, equal_val_map, GINT_TO_POINTER(2));
g_assert_true(wmem_map_size(map) == 0);
/* test size */
map = wmem_map_new(allocator, g_direct_hash, g_direct_equal);
g_assert_true(map);
@ -998,6 +1007,11 @@ wmem_test_map(void)
}
g_assert_true(wmem_map_size(map) == CONTAINER_ITERS);
for (i=0; i<CONTAINER_ITERS; i+=2) {
wmem_map_foreach_remove(map, equal_val_map, GINT_TO_POINTER(i));
}
g_assert_true(wmem_map_size(map) == CONTAINER_ITERS/2);
wmem_destroy_allocator(extra_allocator);
wmem_destroy_allocator(allocator);
}