]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added io_loop_add/remove_switch_callback() to call a callback when ioloop is changed.
authorTimo Sirainen <tss@iki.fi>
Sat, 16 Nov 2013 23:04:50 +0000 (01:04 +0200)
committerTimo Sirainen <tss@iki.fi>
Sat, 16 Nov 2013 23:04:50 +0000 (01:04 +0200)
src/lib/ioloop.c
src/lib/ioloop.h

index 90666b2dfcac6409c073f2bb6250b5a83e87c175..d7b82f78473fda21acbe4eff9ba68a2211666e5f 100644 (file)
@@ -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)
index dfaec8a1b901db12c2434619ec63a397e17a5830..37ecf7d517dc3eb5763ef321766ad486cc58a6d7 100644 (file)
@@ -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