summaryrefslogtreecommitdiff
path: root/epan/wmem
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2017-01-25 23:07:23 -0500
committerEvan Huus <eapache@gmail.com>2017-01-28 12:59:52 +0000
commit6cff5c6776f08eb3d580eba9c9441c64f267923b (patch)
treeaccf362e44c9aa556243bd0f8549a1dea6ee38f2 /epan/wmem
parent618df2460abdb0ee2d3e934f63de6b6a526e5800 (diff)
downloadwireshark-6cff5c6776f08eb3d580eba9c9441c64f267923b.tar.gz
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>
Diffstat (limited to 'epan/wmem')
-rw-r--r--epan/wmem/wmem_map.c87
-rw-r--r--epan/wmem/wmem_map.h18
-rw-r--r--epan/wmem/wmem_test.c21
3 files changed, 122 insertions, 4 deletions
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 <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) {
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<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);
}