Rework the user callback code a bit to make it saner to use with the auto-reset

trees.

svn path=/trunk/; revision=49966
This commit is contained in:
Evan Huus 2013-06-16 22:07:24 +00:00
parent 3924ed9020
commit 88c5b2e892
6 changed files with 50 additions and 37 deletions

View File

@ -113,7 +113,8 @@ wmem_memdup(wmem_allocator_t *allocator, const void *source, const size_t size)
static void
wmem_free_all_real(wmem_allocator_t *allocator, gboolean final)
{
wmem_call_cleanup_callbacks(allocator, final);
wmem_call_cleanup_callbacks(allocator,
final ? WMEM_CB_DESTROY_EVENT : WMEM_CB_FREE_EVENT);
allocator->free_all(allocator->private_data);
}

View File

@ -74,19 +74,21 @@ wmem_allocator_force_new(const wmem_allocator_type_t type)
/* Some helpers for properly testing callback functionality */
wmem_allocator_t *expected_allocator;
void *expected_user_data;
gboolean expected_final;
wmem_cb_event_t expected_event;
int cb_called_count;
int cb_continue_count;
gboolean value_seen[CONTAINER_ITERS];
static void
wmem_test_cb(wmem_allocator_t *allocator, gboolean final, void *user_data)
static gboolean
wmem_test_cb(wmem_allocator_t *allocator, wmem_cb_event_t event,
void *user_data)
{
g_assert(allocator == expected_allocator);
g_assert(final == expected_final);
g_assert(user_data == expected_user_data);
g_assert(event == expected_event);
cb_called_count++;
return *(gboolean*)user_data;
}
static gboolean
@ -109,24 +111,25 @@ static void
wmem_test_allocator_callbacks(void)
{
wmem_allocator_t *allocator;
gboolean t = TRUE;
gboolean f = FALSE;
allocator = wmem_allocator_force_new(WMEM_ALLOCATOR_STRICT);
expected_allocator = allocator;
expected_user_data = GINT_TO_POINTER(42);
#define REG_TEST_CB(RECUR) do { \
wmem_register_cleanup_callback(expected_allocator, (RECUR), \
&wmem_test_cb, GINT_TO_POINTER(42)); \
#define REG_TEST_CB(UDATA) do { \
wmem_register_cleanup_callback(expected_allocator, \
&wmem_test_cb, (UDATA)); \
} while (0);
REG_TEST_CB(FALSE);
REG_TEST_CB(TRUE);
REG_TEST_CB(FALSE);
REG_TEST_CB(FALSE);
REG_TEST_CB(TRUE);
REG_TEST_CB(&f);
REG_TEST_CB(&f);
REG_TEST_CB(&t);
REG_TEST_CB(&t);
REG_TEST_CB(&f);
expected_final = FALSE;
expected_event = WMEM_CB_FREE_EVENT;
cb_called_count = 0;
wmem_free_all(allocator);
@ -140,8 +143,8 @@ wmem_test_allocator_callbacks(void)
wmem_free_all(allocator);
g_assert(cb_called_count == 2);
REG_TEST_CB(TRUE);
REG_TEST_CB(FALSE);
REG_TEST_CB(&f);
REG_TEST_CB(&t);
cb_called_count = 0;
wmem_free_all(allocator);
@ -151,9 +154,9 @@ wmem_test_allocator_callbacks(void)
wmem_free_all(allocator);
g_assert(cb_called_count == 3);
REG_TEST_CB(FALSE);
REG_TEST_CB(&t);
expected_final = TRUE;
expected_event = WMEM_CB_DESTROY_EVENT;
cb_called_count = 0;
wmem_destroy_allocator(allocator);
g_assert(cb_called_count == 4);

View File

@ -230,13 +230,15 @@ wmem_tree_new(wmem_allocator_t *allocator)
return tree;
}
static void
wmem_tree_reset(wmem_allocator_t *allocator _U_, gboolean final _U_,
static gboolean
wmem_tree_reset(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_,
void *user_data)
{
wmem_tree_t *tree = (wmem_tree_t *)user_data;
tree->root = NULL;
return TRUE;
}
wmem_tree_t *
@ -249,7 +251,7 @@ wmem_tree_new_autoreset(wmem_allocator_t *master, wmem_allocator_t *slave)
tree->allocator = slave;
tree->root = NULL;
wmem_register_cleanup_callback(slave, TRUE, wmem_tree_reset, tree);
wmem_register_cleanup_callback(slave, wmem_tree_reset, tree);
return tree;
}

View File

@ -33,13 +33,13 @@ typedef struct _wmem_user_cb_container_t {
wmem_user_cb_t cb;
void *user_data;
struct _wmem_user_cb_container_t *next;
gboolean recurring;
} wmem_user_cb_container_t;
void
wmem_call_cleanup_callbacks(wmem_allocator_t *allocator, gboolean final)
wmem_call_cleanup_callbacks(wmem_allocator_t *allocator, wmem_cb_event_t event)
{
wmem_user_cb_container_t **prev, *cur;
gboolean again;
prev = &(allocator->callbacks);
cur = allocator->callbacks;
@ -47,11 +47,11 @@ wmem_call_cleanup_callbacks(wmem_allocator_t *allocator, gboolean final)
while (cur) {
/* call it */
cur->cb(allocator, final, cur->user_data);
again = cur->cb(allocator, event, cur->user_data);
/* if it was a one-time callback, or this is being triggered by
* the final destruction of the allocator, remove the callback */
if (! cur->recurring || final) {
/* if the callback requested deregistration, or this is being triggered
* by the final destruction of the allocator, remove the callback */
if (! again || event == WMEM_CB_DESTROY_EVENT) {
*prev = cur->next;
g_slice_free(wmem_user_cb_container_t, cur);
cur = *prev;
@ -64,7 +64,7 @@ wmem_call_cleanup_callbacks(wmem_allocator_t *allocator, gboolean final)
}
void
wmem_register_cleanup_callback(wmem_allocator_t *allocator, gboolean recurring,
wmem_register_cleanup_callback(wmem_allocator_t *allocator,
wmem_user_cb_t callback, void *user_data)
{
wmem_user_cb_container_t *container;
@ -73,7 +73,6 @@ wmem_register_cleanup_callback(wmem_allocator_t *allocator, gboolean recurring,
container->cb = callback;
container->user_data = user_data;
container->recurring = recurring;
container->next = allocator->callbacks;
allocator->callbacks = container;

View File

@ -41,15 +41,21 @@ extern "C" {
* @{
*/
/** The events that can trigger a callback. */
typedef enum _wmem_cb_event_t {
WMEM_CB_FREE_EVENT, /**< wmem_free_all() */
WMEM_CB_DESTROY_EVENT /**< wmem_destroy_allocator() */
} wmem_cb_event_t;
/** Function signature for registered user callbacks.
*
* @param allocator The allocator that triggered this callback.
* @param final Whether this is was triggered due to the allocator being
* destroyed (TRUE) or simply a call to wmem_free_all() (FALSE).
* @param event The event type that triggered this callback.
* @param user_data Whatever user_data was originally passed to the call to
* wmem_register_cleanup_callback().
* wmem_register_cleanup_callback().
* @return FALSE to unregister the callback, TRUE otherwise.
*/
typedef void (*wmem_user_cb_t) (wmem_allocator_t *, gboolean, void *);
typedef gboolean (*wmem_user_cb_t) (wmem_allocator_t*, wmem_cb_event_t, void*);
/** Register a callback function with the given allocator pool.
*
@ -67,7 +73,7 @@ typedef void (*wmem_user_cb_t) (wmem_allocator_t *, gboolean, void *);
*/
WS_DLL_PUBLIC
void
wmem_register_cleanup_callback(wmem_allocator_t *allocator, gboolean recurring,
wmem_register_cleanup_callback(wmem_allocator_t *allocator,
wmem_user_cb_t callback, void *user_data);
/** @}

View File

@ -31,9 +31,11 @@ extern "C" {
#endif /* __cplusplus */
#include <glib.h>
#include <wmem_user_cb.h>
WS_DLL_LOCAL
void
wmem_call_cleanup_callbacks(wmem_allocator_t *allocator, gboolean final);
wmem_call_cleanup_callbacks(wmem_allocator_t *allocator, wmem_cb_event_t event);
#ifdef __cplusplus
}