More callback tweaks, to permit unregistering a callback from the same place

it was originally registered.

svn path=/trunk/; revision=49969
This commit is contained in:
Evan Huus 2013-06-16 22:37:55 +00:00
parent ffee3af207
commit 55264582be
6 changed files with 63 additions and 24 deletions

View File

@ -113,7 +113,7 @@ 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,
wmem_call_callbacks(allocator,
final ? WMEM_CB_DESTROY_EVENT : WMEM_CB_FREE_EVENT);
allocator->free_all(allocator->private_data);
}

View File

@ -113,21 +113,17 @@ wmem_test_allocator_callbacks(void)
wmem_allocator_t *allocator;
gboolean t = TRUE;
gboolean f = FALSE;
guint cb_id;
allocator = wmem_allocator_force_new(WMEM_ALLOCATOR_STRICT);
expected_allocator = allocator;
#define REG_TEST_CB(UDATA) do { \
wmem_register_cleanup_callback(expected_allocator, \
&wmem_test_cb, (UDATA)); \
} while (0);
REG_TEST_CB(&f);
REG_TEST_CB(&f);
REG_TEST_CB(&t);
REG_TEST_CB(&t);
REG_TEST_CB(&f);
wmem_register_callback(expected_allocator, &wmem_test_cb, &f);
wmem_register_callback(expected_allocator, &wmem_test_cb, &f);
cb_id = wmem_register_callback(expected_allocator, &wmem_test_cb, &t);
wmem_register_callback(expected_allocator, &wmem_test_cb, &t);
wmem_register_callback(expected_allocator, &wmem_test_cb, &f);
expected_event = WMEM_CB_FREE_EVENT;
@ -143,23 +139,29 @@ wmem_test_allocator_callbacks(void)
wmem_free_all(allocator);
g_assert(cb_called_count == 2);
REG_TEST_CB(&f);
REG_TEST_CB(&t);
wmem_unregister_callback(allocator, cb_id);
cb_called_count = 0;
wmem_free_all(allocator);
g_assert(cb_called_count == 4);
g_assert(cb_called_count == 1);
cb_id = wmem_register_callback(expected_allocator, &wmem_test_cb, &f);
wmem_register_callback(expected_allocator, &wmem_test_cb, &t);
cb_called_count = 0;
wmem_free_all(allocator);
g_assert(cb_called_count == 3);
REG_TEST_CB(&t);
wmem_unregister_callback(allocator, cb_id);
cb_called_count = 0;
wmem_free_all(allocator);
g_assert(cb_called_count == 2);
wmem_register_callback(expected_allocator, &wmem_test_cb, &t);
expected_event = WMEM_CB_DESTROY_EVENT;
cb_called_count = 0;
wmem_destroy_allocator(allocator);
g_assert(cb_called_count == 4);
g_assert(cb_called_count == 3);
}
static void

View File

@ -251,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, wmem_tree_reset, tree);
wmem_register_callback(slave, wmem_tree_reset, tree);
return tree;
}

View File

@ -33,10 +33,11 @@ typedef struct _wmem_user_cb_container_t {
wmem_user_cb_t cb;
void *user_data;
struct _wmem_user_cb_container_t *next;
guint id;
} wmem_user_cb_container_t;
void
wmem_call_cleanup_callbacks(wmem_allocator_t *allocator, wmem_cb_event_t event)
wmem_call_callbacks(wmem_allocator_t *allocator, wmem_cb_event_t event)
{
wmem_user_cb_container_t **prev, *cur;
gboolean again;
@ -63,19 +64,44 @@ wmem_call_cleanup_callbacks(wmem_allocator_t *allocator, wmem_cb_event_t event)
}
}
void
wmem_register_cleanup_callback(wmem_allocator_t *allocator,
guint
wmem_register_callback(wmem_allocator_t *allocator,
wmem_user_cb_t callback, void *user_data)
{
wmem_user_cb_container_t *container;
static guint next_id = 0;
container = g_slice_new(wmem_user_cb_container_t);
container->cb = callback;
container->user_data = user_data;
container->next = allocator->callbacks;
container->id = next_id++;
allocator->callbacks = container;
return container->id;
}
void
wmem_unregister_callback(wmem_allocator_t *allocator, guint id)
{
wmem_user_cb_container_t **prev, *cur;
prev = &(allocator->callbacks);
cur = allocator->callbacks;
while (cur) {
if (cur->id == id) {
*prev = cur->next;
g_slice_free(wmem_user_cb_container_t, cur);
return;
}
prev = &(cur->next);
cur = cur->next;
}
}
/*

View File

@ -70,11 +70,22 @@ typedef gboolean (*wmem_user_cb_t) (wmem_allocator_t*, wmem_cb_event_t, void*);
* that this pointer is not freed when a callback is finished,
* you have to do that yourself in the callback, or just
* allocate it in the appropriate wmem pool.
* @return ID of this callback that can be passed back to
* wmem_unregister_callback().
*/
WS_DLL_PUBLIC
guint
wmem_register_callback(wmem_allocator_t *allocator, wmem_user_cb_t callback,
void *user_data);
/** Unregister the callback function with the given ID.
*
* @param allocator The allocator from which to unregister the callback.
* @param id The callback id as returned from wmem_register_callback().
*/
WS_DLL_PUBLIC
void
wmem_register_cleanup_callback(wmem_allocator_t *allocator,
wmem_user_cb_t callback, void *user_data);
wmem_unregister_callback(wmem_allocator_t *allocator, guint id);
/** @}
* @} */

View File

@ -35,7 +35,7 @@ extern "C" {
WS_DLL_LOCAL
void
wmem_call_cleanup_callbacks(wmem_allocator_t *allocator, wmem_cb_event_t event);
wmem_call_callbacks(wmem_allocator_t *allocator, wmem_cb_event_t event);
#ifdef __cplusplus
}