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 <mmann78@netscape.net>
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Evan Huus <eapache@gmail.com>
This commit is contained in:
Michael Mann 2017-01-25 23:07:23 -05:00 committed by Evan Huus
parent 618df2460a
commit 6cff5c6776
4 changed files with 123 additions and 4 deletions

View File

@ -1770,6 +1770,7 @@ libwireshark.so.0 libwireshark0 #MINVER#
wmem_map_insert@Base 1.12.0~rc1
wmem_map_lookup@Base 1.12.0~rc1
wmem_map_new@Base 1.12.0~rc1
wmem_map_new_autoreset@Base 2.3.0
wmem_map_remove@Base 1.12.0~rc1
wmem_map_size@Base 2.1.0
wmem_memdup@Base 1.12.0~rc1

View File

@ -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 <glib.h>
#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) {

View File

@ -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.

View File

@ -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<CONTAINER_ITERS; i++) {
ret = wmem_map_insert(map, GINT_TO_POINTER(i), GINT_TO_POINTER(777777));
g_assert(ret == NULL);
ret = wmem_map_insert(map, GINT_TO_POINTER(i), GINT_TO_POINTER(i));
g_assert(ret == GINT_TO_POINTER(777777));
ret = wmem_map_insert(map, GINT_TO_POINTER(i), GINT_TO_POINTER(i));
g_assert(ret == GINT_TO_POINTER(i));
}
wmem_free_all(extra_allocator);
for (i=0; i<CONTAINER_ITERS; i++) {
g_assert(wmem_map_lookup(map, GINT_TO_POINTER(i)) == NULL);
}
wmem_free_all(allocator);
map = wmem_map_new(allocator, wmem_str_hash, g_str_equal);
g_assert(map);
@ -876,6 +894,7 @@ wmem_test_map(void)
}
g_assert(wmem_map_size(map) == CONTAINER_ITERS);
wmem_destroy_allocator(extra_allocator);
wmem_destroy_allocator(allocator);
}