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)
{
*_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);
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);
}
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)
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). */
/* 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