From 6cff5c6776f08eb3d580eba9c9441c64f267923b Mon Sep 17 00:00:00 2001 From: Michael Mann Date: Wed, 25 Jan 2017 23:07:23 -0500 Subject: Add wmem_map_new_autoreset This can be used similarly to wmem_tree_new_autoreset for hash tables that need reset after capture file change. Change-Id: I3a2f0b0a0cad3eca46266523c594d3d7aac17489 Reviewed-on: https://code.wireshark.org/review/19794 Reviewed-by: Michael Mann Petri-Dish: Michael Mann Tested-by: Petri Dish Buildbot Reviewed-by: Evan Huus --- epan/wmem/wmem_map.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++-- epan/wmem/wmem_map.h | 18 +++++++++++ epan/wmem/wmem_test.c | 21 ++++++++++++- 3 files changed, 122 insertions(+), 4 deletions(-) (limited to 'epan/wmem') diff --git a/epan/wmem/wmem_map.c b/epan/wmem/wmem_map.c index 4355ce5c50..c91d062ba9 100644 --- a/epan/wmem/wmem_map.c +++ b/epan/wmem/wmem_map.c @@ -20,12 +20,14 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "config.h" #include #include "wmem_core.h" #include "wmem_map.h" #include "wmem_map_int.h" +#include "wmem_user_cb.h" static guint32 x; /* Used for universal integer hashing (see the HASH macro) */ @@ -64,6 +66,10 @@ struct _wmem_map_t { GHashFunc hash_func; GEqualFunc eql_func; + guint master_cb_id; + guint slave_cb_id; + + wmem_allocator_t *master; wmem_allocator_t *allocator; }; @@ -81,6 +87,14 @@ struct _wmem_map_t { #define HASH(MAP, KEY) \ ((guint32)(((MAP)->hash_func(KEY) * x) >> (32 - (MAP)->capacity))) +static void +wmem_map_init_table(wmem_map_t *map) +{ + map->count = 0; + map->capacity = WMEM_MAP_DEFAULT_CAPACITY; + map->table = wmem_alloc0_array(map->allocator, wmem_map_item_t*, CAPACITY(map)); +} + wmem_map_t * wmem_map_new(wmem_allocator_t *allocator, GHashFunc hash_func, GEqualFunc eql_func) @@ -89,12 +103,59 @@ wmem_map_new(wmem_allocator_t *allocator, map = wmem_new(allocator, wmem_map_t); - map->count = 0; - map->capacity = WMEM_MAP_DEFAULT_CAPACITY; - map->table = wmem_alloc0_array(allocator, wmem_map_item_t*, CAPACITY(map)); map->hash_func = hash_func; map->eql_func = eql_func; + map->master = allocator; map->allocator = allocator; + wmem_map_init_table(map); + + return map; +} + +static gboolean +wmem_map_reset_cb(wmem_allocator_t *allocator _U_, wmem_cb_event_t event, + void *user_data) +{ + wmem_map_t *map = (wmem_map_t*)user_data; + + map->count = 0; + map->table = NULL; + + if (event == WMEM_CB_DESTROY_EVENT) { + wmem_unregister_callback(map->master, map->master_cb_id); + wmem_free(map->master, map); + } + + return TRUE; +} + +static gboolean +wmem_map_destroy_cb(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_, + void *user_data) +{ + wmem_map_t *map = (wmem_map_t*)user_data; + + wmem_unregister_callback(map->allocator, map->slave_cb_id); + + return FALSE; +} + +wmem_map_t * +wmem_map_new_autoreset(wmem_allocator_t *master, wmem_allocator_t *slave, + GHashFunc hash_func, GEqualFunc eql_func) +{ + wmem_map_t *map; + + map = wmem_new(master, wmem_map_t); + + map->hash_func = hash_func; + map->eql_func = eql_func; + map->master = master; + map->allocator = slave; + wmem_map_init_table(map); + + map->master_cb_id = wmem_register_callback(master, wmem_map_destroy_cb, map); + map->slave_cb_id = wmem_register_callback(slave, wmem_map_reset_cb, map); return map; } @@ -137,6 +198,11 @@ wmem_map_insert(wmem_map_t *map, const void *key, void *value) wmem_map_item_t **item; void *old_val; + /* Make sure we have a table */ + if (map->table == NULL) { + wmem_map_init_table(map); + } + /* get a pointer to the slot */ item = &(map->table[HASH(map, key)]); @@ -174,6 +240,11 @@ wmem_map_lookup(wmem_map_t *map, const void *key) { wmem_map_item_t *item; + /* Make sure we have a table */ + if (map->table == NULL) { + return NULL; + } + /* find correct slot */ item = map->table[HASH(map, key)]; @@ -194,6 +265,11 @@ wmem_map_remove(wmem_map_t *map, const void *key) wmem_map_item_t **item, *tmp; void *value; + /* Make sure we have a table */ + if (map->table == NULL) { + return NULL; + } + /* get a pointer to the slot */ item = &(map->table[HASH(map, key)]); @@ -221,6 +297,11 @@ wmem_map_foreach(wmem_map_t *map, GHFunc foreach_func, gpointer user_data) wmem_map_item_t *cur; unsigned i; + /* Make sure we have a table */ + if (map->table == NULL) { + return; + } + for (i = 0; i < CAPACITY(map); i++) { cur = map->table[i]; while (cur) { diff --git a/epan/wmem/wmem_map.h b/epan/wmem/wmem_map.h index 3e10c9a6dc..1ea4cf3350 100644 --- a/epan/wmem/wmem_map.h +++ b/epan/wmem/wmem_map.h @@ -70,6 +70,24 @@ wmem_map_new(wmem_allocator_t *allocator, GHashFunc hash_func, GEqualFunc eql_func) G_GNUC_MALLOC; +/** Creates a map with two allocator scopes. The base structure lives in the + * master scope, however the data lives in the slave scope. Every time free_all + * occurs in the slave scope the map is transparently emptied without affecting + * the location of the master structure. + * + * WARNING: None of the map (even the part in the master scope) can be used + * after the slave scope has been *destroyed*. + * + * The primary use for this function is to create maps that reset for each new + * capture file that is loaded. This can be done by specifying wmem_epan_scope() + * as the master and wmem_file_scope() as the slave. + */ +WS_DLL_PUBLIC +wmem_map_t * +wmem_map_new_autoreset(wmem_allocator_t *master, wmem_allocator_t *slave, + GHashFunc hash_func, GEqualFunc eql_func) +G_GNUC_MALLOC; + /** Inserts a value into the map. * * @param map The map to insert into. diff --git a/epan/wmem/wmem_test.c b/epan/wmem/wmem_test.c index ecbae8973b..96338946c5 100644 --- a/epan/wmem/wmem_test.c +++ b/epan/wmem/wmem_test.c @@ -816,13 +816,14 @@ check_val_map(gpointer key _U_, gpointer val, gpointer user_data) static void wmem_test_map(void) { - wmem_allocator_t *allocator; + wmem_allocator_t *allocator, *extra_allocator; wmem_map_t *map; gchar *str_key; unsigned int i; void *ret; allocator = wmem_allocator_new(WMEM_ALLOCATOR_STRICT); + extra_allocator = wmem_allocator_new(WMEM_ALLOCATOR_STRICT); /* insertion, lookup and removal of simple integer keys */ map = wmem_map_new(allocator, g_direct_hash, g_direct_equal); @@ -848,6 +849,23 @@ wmem_test_map(void) } wmem_free_all(allocator); + /* test auto-reset functionality */ + map = wmem_map_new_autoreset(allocator, extra_allocator, g_direct_hash, g_direct_equal); + g_assert(map); + for (i=0; i