diff options
| author | Ray Strode <rstrode@redhat.com> | 2007-06-07 14:51:27 -0400 |
|---|---|---|
| committer | Ray Strode <rstrode@redhat.com> | 2007-06-07 14:51:27 -0400 |
| commit | a3d18a2cd2bc6d43f57cd962c88ad25604ff7513 (patch) | |
| tree | a9ec72c16214f3e83f462f7ffcf24e9e722f6e17 /src | |
| parent | 87fb3dcb26a86f3b26545694fc84cd20f030e545 (diff) | |
| download | plymouth-a3d18a2cd2bc6d43f57cd962c88ad25604ff7513.tar.gz plymouth-a3d18a2cd2bc6d43f57cd962c88ad25604ff7513.tar.xz plymouth-a3d18a2cd2bc6d43f57cd962c88ad25604ff7513.zip | |
add support for timeouts to the event loop
Diffstat (limited to 'src')
| -rw-r--r-- | src/libply/ply-event-loop.c | 185 | ||||
| -rw-r--r-- | src/libply/ply-event-loop.h | 6 |
2 files changed, 170 insertions, 21 deletions
diff --git a/src/libply/ply-event-loop.c b/src/libply/ply-event-loop.c index d8c85b1..d805a9d 100644 --- a/src/libply/ply-event-loop.c +++ b/src/libply/ply-event-loop.c @@ -25,6 +25,7 @@ #include <assert.h> #include <errno.h> #include <fcntl.h> +#include <math.h> #include <signal.h> #include <stdlib.h> #include <stdbool.h> @@ -44,6 +45,10 @@ #define PLY_EVENT_LOOP_NUM_EVENT_HANDLERS 64 #endif +#ifndef PLY_EVENT_LOOP_NO_TIMED_WAKEUP +#define PLY_EVENT_LOOP_NO_TIMED_WAKEUP 0.0 +#endif + typedef struct { int fd; @@ -89,15 +94,24 @@ typedef struct { ply_event_loop_exit_handler_t handler; void *user_data; -} ply_event_loop_closure_t; +} ply_event_loop_exit_closure_t; + +typedef struct +{ + double timeout; + ply_event_loop_timeout_handler_t handler; + void *user_data; +} ply_event_loop_timeout_watch_t; struct _ply_event_loop { int epoll_fd; int exit_code; + double wakeup_time; ply_list_t *sources; - ply_list_t *closures; + ply_list_t *exit_closures; + ply_list_t *timeout_watches; ply_signal_dispatcher_t *signal_dispatcher; @@ -448,6 +462,7 @@ ply_event_loop_new (void) loop = calloc (1, sizeof (ply_event_loop_t)); loop->epoll_fd = epoll_create (PLY_EVENT_LOOP_NUM_EVENT_HANDLERS); + loop->wakeup_time = PLY_EVENT_LOOP_NO_TIMED_WAKEUP; assert (loop->epoll_fd >= 0); @@ -455,7 +470,8 @@ ply_event_loop_new (void) loop->exit_code = 0; loop->sources = ply_list_new (); - loop->closures = ply_list_new (); + loop->exit_closures = ply_list_new (); + loop->timeout_watches = ply_list_new (); loop->signal_dispatcher = ply_signal_dispatcher_new (); @@ -479,19 +495,19 @@ ply_event_loop_free_exit_closures (ply_event_loop_t *loop) { ply_list_node_t *node; - node = ply_list_get_first_node (loop->closures); + node = ply_list_get_first_node (loop->exit_closures); while (node != NULL) { ply_list_node_t *next_node; - ply_event_loop_closure_t *closure; + ply_event_loop_exit_closure_t *closure; - closure = (ply_event_loop_closure_t *) ply_list_node_get_data (node); - next_node = ply_list_get_next_node (loop->closures, node); + closure = (ply_event_loop_exit_closure_t *) ply_list_node_get_data (node); + next_node = ply_list_get_next_node (loop->exit_closures, node); free (closure); node = next_node; } - ply_list_free (loop->closures); + ply_list_free (loop->exit_closures); } static void @@ -499,16 +515,16 @@ ply_event_loop_run_exit_closures (ply_event_loop_t *loop) { ply_list_node_t *node; - node = ply_list_get_first_node (loop->closures); + node = ply_list_get_first_node (loop->exit_closures); while (node != NULL) { ply_list_node_t *next_node; - ply_event_loop_closure_t *closure; + ply_event_loop_exit_closure_t *closure; - closure = (ply_event_loop_closure_t *) ply_list_node_get_data (node); + closure = (ply_event_loop_exit_closure_t *) ply_list_node_get_data (node); assert (closure->handler != NULL); - next_node = ply_list_get_next_node (loop->closures, node); + next_node = ply_list_get_next_node (loop->exit_closures, node); closure->handler (closure->user_data, loop->exit_code, loop); @@ -523,10 +539,14 @@ ply_event_loop_free (ply_event_loop_t *loop) return; assert (ply_list_get_length (loop->sources) == 0); + assert (ply_list_get_length (loop->timeout_watches) == 0); ply_signal_dispatcher_free (loop->signal_dispatcher); ply_event_loop_free_exit_closures (loop); + ply_list_free (loop->sources); + ply_list_free (loop->timeout_watches); + close (loop->epoll_fd); free (loop); } @@ -608,6 +628,24 @@ ply_event_loop_remove_source (ply_event_loop_t *loop, ply_event_loop_remove_source_node (loop, source_node); } +void +ply_event_loop_free_sources (ply_event_loop_t *loop) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (loop->sources); + while (node != NULL) + { + ply_list_node_t *next_node; + ply_event_source_t *source; + + source = (ply_event_source_t *) ply_list_node_get_data (node); + next_node = ply_list_get_next_node (loop->sources, node); + ply_event_loop_remove_source_node (loop, node); + node = next_node; + } +} + static bool ply_event_loop_fd_status_is_valid (ply_event_loop_fd_status_t status) { @@ -782,16 +820,41 @@ ply_event_loop_watch_for_exit (ply_event_loop_t *loop, ply_event_loop_exit_handler_t exit_handler, void *user_data) { - ply_event_loop_closure_t *closure; + ply_event_loop_exit_closure_t *closure; assert (loop != NULL); assert (exit_handler != NULL); - closure = calloc (1, sizeof (ply_event_loop_closure_t)); + closure = calloc (1, sizeof (ply_event_loop_exit_closure_t)); closure->handler = exit_handler; closure->user_data = user_data; - ply_list_append_data (loop->closures, closure); + ply_list_append_data (loop->exit_closures, closure); +} + +void +ply_event_loop_watch_for_timeout (ply_event_loop_t *loop, + double seconds, + ply_event_loop_timeout_handler_t timeout_handler, + void *user_data) +{ + ply_event_loop_timeout_watch_t *timeout_watch; + + assert (loop != NULL); + assert (timeout_handler != NULL); + assert (seconds > 0.0); + + timeout_watch = calloc (1, sizeof (ply_event_loop_timeout_watch_t)); + timeout_watch->timeout = ply_get_timestamp () + seconds; + timeout_watch->handler = timeout_handler; + timeout_watch->user_data = user_data; + + if (fabs (loop->wakeup_time - PLY_EVENT_LOOP_NO_TIMED_WAKEUP) <= 0) + loop->wakeup_time = timeout_watch->timeout; + else + loop->wakeup_time = MIN (loop->wakeup_time, timeout_watch->timeout); + + ply_list_append_data (loop->timeout_watches, timeout_watch); } static ply_event_loop_fd_status_t @@ -921,6 +984,34 @@ ply_event_loop_free_watches_for_source (ply_event_loop_t *loop, } static void +ply_event_loop_free_timeout_watches (ply_event_loop_t *loop) +{ + ply_list_node_t *node; + double now; + + assert (loop != NULL); + + now = ply_get_timestamp (); + node = ply_list_get_first_node (loop->timeout_watches); + while (node != NULL) + { + ply_list_node_t *next_node; + ply_event_loop_timeout_watch_t *watch; + + watch = (ply_event_loop_timeout_watch_t *) ply_list_node_get_data (node); + next_node = ply_list_get_next_node (loop->timeout_watches, node); + + free (watch); + ply_list_remove_node (loop->timeout_watches, node); + + node = next_node; + } + + assert (ply_list_get_length (loop->timeout_watches) == 0); + loop->wakeup_time = PLY_EVENT_LOOP_NO_TIMED_WAKEUP; +} + +static void ply_event_loop_free_destinations_for_source (ply_event_loop_t *loop, ply_event_source_t *source) { @@ -966,11 +1057,45 @@ ply_event_loop_disconnect_source (ply_event_loop_t *loop, } static void +ply_event_loop_handle_timeouts (ply_event_loop_t *loop) +{ + ply_list_node_t *node; + double now; + + assert (loop != NULL); + + now = ply_get_timestamp (); + node = ply_list_get_first_node (loop->timeout_watches); + while (node != NULL) + { + ply_list_node_t *next_node; + ply_event_loop_timeout_watch_t *watch; + + watch = (ply_event_loop_timeout_watch_t *) ply_list_node_get_data (node); + next_node = ply_list_get_next_node (loop->timeout_watches, node); + + if (watch->timeout <= now) + { + assert (watch->handler != NULL); + watch->handler (watch->user_data, loop); + free (watch); + ply_list_remove_node (loop->timeout_watches, node); + } + + node = next_node; + } + + if (ply_list_get_length (loop->timeout_watches) == 0) + loop->wakeup_time = PLY_EVENT_LOOP_NO_TIMED_WAKEUP; +} + +static void ply_event_loop_process_pending_events (ply_event_loop_t *loop) { int number_of_received_events, i; static struct epoll_event *events = NULL; - int saved_errno; + + assert (loop != NULL); if (events == NULL) events = @@ -981,21 +1106,28 @@ ply_event_loop_process_pending_events (ply_event_loop_t *loop) do { + int timeout; + + if (fabs (loop->wakeup_time - PLY_EVENT_LOOP_NO_TIMED_WAKEUP) <= 0) + timeout = -1; + else + timeout = (int) ((loop->wakeup_time - ply_get_timestamp ()) * 1000); + number_of_received_events = epoll_wait (loop->epoll_fd, events, - sizeof (events), -1); + sizeof (events), timeout); + + ply_event_loop_handle_timeouts (loop); if (number_of_received_events < 0) { - saved_errno = errno; - - if (saved_errno != EINTR) + if (errno != EINTR) { ply_event_loop_exit (loop, 255); return; } } } - while ((number_of_received_events < 0) && (saved_errno == EINTR)); + while ((number_of_received_events < 0) && (errno == EINTR)); for (i = 0; i < number_of_received_events; i++) { @@ -1049,6 +1181,8 @@ ply_event_loop_run (ply_event_loop_t *loop) ply_event_loop_process_pending_events (loop); ply_event_loop_run_exit_closures (loop); + ply_event_loop_free_sources (loop); + ply_event_loop_free_timeout_watches (loop); loop->should_exit = false; @@ -1096,6 +1230,12 @@ line_received_handler (void) printf ("%s", line); } +static void +on_timeout (ply_event_loop_t *loop) +{ + printf ("timeout elapsed\n"); +} + int main (int argc, char **argv) @@ -1117,6 +1257,9 @@ main (int argc, (ply_event_handler_t) alrm_signal_handler, NULL); + ply_event_loop_watch_for_timeout (loop, 2.0, + (ply_event_loop_timeout_handler_t) + on_timeout, loop); ply_event_loop_watch_fd (loop, 0, PLY_EVENT_LOOP_FD_STATUS_HAS_DATA, (ply_event_handler_t) line_received_handler, (ply_event_handler_t) line_received_handler, diff --git a/src/libply/ply-event-loop.h b/src/libply/ply-event-loop.h index 7a43d07..46ce294 100644 --- a/src/libply/ply-event-loop.h +++ b/src/libply/ply-event-loop.h @@ -42,6 +42,8 @@ typedef void (* ply_event_handler_t) (void *user_data, typedef void (* ply_event_loop_exit_handler_t) (void *user_data, int exit_code, ply_event_loop_t *loop); +typedef void (* ply_event_loop_timeout_handler_t) (void *user_data, + ply_event_loop_t *loop); #ifndef PLY_HIDE_FUNCTION_DECLARATIONS ply_event_loop_t *ply_event_loop_new (void); @@ -64,6 +66,10 @@ void ply_event_loop_stop_watching_signal (ply_event_loop_t *loop, void ply_event_loop_watch_for_exit (ply_event_loop_t *loop, ply_event_loop_exit_handler_t exit_handler, void *user_data); +void ply_event_loop_watch_for_timeout (ply_event_loop_t *loop, + double seconds, + ply_event_loop_timeout_handler_t timeout_handler, + void *user_data); int ply_event_loop_run (ply_event_loop_t *loop); void ply_event_loop_exit (ply_event_loop_t *loop, |
