summaryrefslogtreecommitdiff
path: root/epan/wmem/wmem_core.c
diff options
context:
space:
mode:
authorEvan Huus <eapache@gmail.com>2013-05-07 19:23:10 +0000
committerEvan Huus <eapache@gmail.com>2013-05-07 19:23:10 +0000
commit2e92c6dfdec952484ebe96ea1718467c2fa5de6b (patch)
tree021f78948c075de21a76e60d05672ad929b4e11e /epan/wmem/wmem_core.c
parent572d68a33bc1fadcd0ff7b0de8b718fb98fc259c (diff)
downloadwireshark-2e92c6dfdec952484ebe96ea1718467c2fa5de6b.tar.gz
Add user callbacks to wmem. This feature is a generic way to transparently mimic
the behaviour emem has for seasonal trees, which is that the master tree structure is not actually seasonal - it is permanent. When the seasonal memory pool is cleared, the root node pointer in all of these permanent trees is set to NULL, and the pool takes care of actually freeing the nodes. Wmem can now mimic this by allocating the tree header struct in epan_scope(), allocating any node structs in file_scope(), and registering a callback on file_scope() that NULLs the pointer in the epan_scope() header. Yes, this is confusing, but it seemed simpler than adding manual callback registrations to every single dissector that currently uses seasonal trees. The callbacks may also be useful for other things that need cleanup (I'm thinking resource handles stored in wmem memory that need to be fclosed or what-have-you before they the handle is lost). As indicated by the number of caveats in README.wmem, the implementation probably needs a bit of work to make it safer/saner/more-useful. Thoughts (or patches!) in this direction are more than welcome. svn path=/trunk/; revision=49205
Diffstat (limited to 'epan/wmem/wmem_core.c')
-rw-r--r--epan/wmem/wmem_core.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/epan/wmem/wmem_core.c b/epan/wmem/wmem_core.c
index 415826005a..8e0b0b1938 100644
--- a/epan/wmem/wmem_core.c
+++ b/epan/wmem/wmem_core.c
@@ -29,6 +29,7 @@
#include "wmem_core.h"
#include "wmem_scopes.h"
+#include "wmem_user_cb.h"
#include "wmem_allocator.h"
#include "wmem_allocator_simple.h"
#include "wmem_allocator_block.h"
@@ -101,6 +102,18 @@ wmem_realloc(wmem_allocator_t *allocator, void *ptr, const size_t size)
void
wmem_free_all(wmem_allocator_t *allocator)
{
+ GSList *tmp;
+ wmem_user_cb_container_t *cb;
+
+ /* Call all the user-registered callbacks */
+ tmp = allocator->callbacks;
+ while (tmp) {
+ cb = (wmem_user_cb_container_t*) tmp->data;
+ cb->cb(allocator, cb->user_data);
+ tmp = tmp->next;
+ }
+
+ /* Actually free-all */
allocator->free_all(allocator->private_data);
}
@@ -111,9 +124,38 @@ wmem_gc(wmem_allocator_t *allocator)
}
void
+wmem_register_cleanup_callback(wmem_allocator_t *allocator,
+ wmem_user_cb_t callback, void *user_data)
+{
+ wmem_user_cb_container_t *container;
+
+ container = g_slice_new(wmem_user_cb_container_t);
+
+ container->cb = callback;
+ container->user_data = user_data;
+
+ allocator->callbacks = g_slist_prepend(allocator->callbacks,
+ container);
+}
+
+void
wmem_destroy_allocator(wmem_allocator_t *allocator)
{
+ GSList *tmp;
+
+ /* Free-all first (this calls all the user-registered callbacks) */
wmem_free_all(allocator);
+
+ /* Destroy all user-registered callbacks
+ * (they were called in wmem_free_all) */
+ tmp = allocator->callbacks;
+ while (tmp) {
+ g_slice_free(wmem_user_cb_container_t, tmp->data);
+ tmp = tmp->next;
+ }
+ g_slist_free(allocator->callbacks);
+
+ /* Tell the allocator to destroy itself */
allocator->destroy(allocator);
}
@@ -166,6 +208,7 @@ wmem_allocator_new(const wmem_allocator_type_t type)
};
allocator->type = real_type;
+ allocator->callbacks = NULL;
return allocator;
}