summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2007-06-07 14:51:27 -0400
committerRay Strode <rstrode@redhat.com>2007-06-07 14:51:27 -0400
commita3d18a2cd2bc6d43f57cd962c88ad25604ff7513 (patch)
treea9ec72c16214f3e83f462f7ffcf24e9e722f6e17 /src
parent87fb3dcb26a86f3b26545694fc84cd20f030e545 (diff)
downloadplymouth-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.c185
-rw-r--r--src/libply/ply-event-loop.h6
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,