From: Timo Sirainen Date: Sat, 16 Nov 2013 23:04:50 +0000 (+0200) Subject: Added io_loop_add/remove_switch_callback() to call a callback when ioloop is changed. X-Git-Tag: 2.2.8~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=888e0f4be6b8085fa42b6bd7f7ce67f14e88c73f;p=thirdparty%2Fdovecot%2Fcore.git Added io_loop_add/remove_switch_callback() to call a callback when ioloop is changed. --- diff --git a/src/lib/ioloop.c b/src/lib/ioloop.c index 90666b2dfc..d7b82f7847 100644 --- a/src/lib/ioloop.c +++ b/src/lib/ioloop.c @@ -16,6 +16,7 @@ time_t ioloop_time = 0; struct timeval ioloop_timeval; struct ioloop *current_ioloop = NULL; +static ARRAY(io_switch_callback_t *) io_switch_callbacks = ARRAY_INIT; static void io_loop_initialize_handler(struct ioloop *ioloop) { @@ -467,6 +468,10 @@ void io_loop_destroy(struct ioloop **_ioloop) *_ioloop = NULL; + /* ->prev won't work unless loops are destroyed in create order */ + i_assert(ioloop == current_ioloop); + io_loop_set_current(current_ioloop->prev); + if (ioloop->notify_handler_context != NULL) io_loop_notify_handler_deinit(ioloop); @@ -495,10 +500,6 @@ void io_loop_destroy(struct ioloop **_ioloop) if (ioloop->cur_ctx != NULL) io_loop_context_deactivate(ioloop->cur_ctx); - /* ->prev won't work unless loops are destroyed in create order */ - i_assert(ioloop == current_ioloop); - io_loop_set_current(current_ioloop->prev); - i_free(ioloop); } @@ -508,9 +509,45 @@ void io_loop_set_time_moved_callback(struct ioloop *ioloop, ioloop->time_moved_callback = callback; } +static void io_switch_callbacks_free(void) +{ + array_free(&io_switch_callbacks); +} + void io_loop_set_current(struct ioloop *ioloop) { + io_switch_callback_t *const *callbackp; + struct ioloop *prev_ioloop = current_ioloop; + current_ioloop = ioloop; + if (array_is_created(&io_switch_callbacks)) { + array_foreach(&io_switch_callbacks, callbackp) + (*callbackp)(prev_ioloop); + } +} + +void io_loop_add_switch_callback(io_switch_callback_t *callback) +{ + if (!array_is_created(&io_switch_callbacks)) { + i_array_init(&io_switch_callbacks, 4); + lib_atexit(io_switch_callbacks_free); + } + array_append(&io_switch_callbacks, &callback, 1); +} + +void io_loop_remove_switch_callback(io_switch_callback_t *callback) +{ + io_switch_callback_t *const *callbackp; + unsigned int idx; + + array_foreach(&io_switch_callbacks, callbackp) { + if (*callbackp == callback) { + idx = array_foreach_idx(&io_switch_callbacks, callbackp); + array_delete(&io_switch_callbacks, idx, 1); + return; + } + } + i_unreached(); } struct ioloop_context *io_loop_context_new(struct ioloop *ioloop) diff --git a/src/lib/ioloop.h b/src/lib/ioloop.h index dfaec8a1b9..37ecf7d517 100644 --- a/src/lib/ioloop.h +++ b/src/lib/ioloop.h @@ -32,6 +32,7 @@ enum io_notify_result { typedef void io_callback_t(void *context); typedef void timeout_callback_t(void *context); typedef void io_loop_time_moved_callback_t(time_t old_time, time_t new_time); +typedef void io_switch_callback_t(struct ioloop *prev_ioloop); /* Time when the I/O loop started calling handlers. Can be used instead of time(NULL). */ @@ -112,6 +113,9 @@ void io_loop_set_time_moved_callback(struct ioloop *ioloop, /* Change the current_ioloop. */ void io_loop_set_current(struct ioloop *ioloop); +/* Call the callback whenever ioloop is changed. */ +void io_loop_add_switch_callback(io_switch_callback_t *callback); +void io_loop_remove_switch_callback(io_switch_callback_t *callback); /* This context is used for all further I/O and timeout callbacks that are added until returning to ioloop. When a callback is called, this context is