[Spice-devel] [PATCH v4 1/6] tests: use glib main loop

Frediano Ziglio fziglio at redhat.com
Wed Aug 19 07:39:02 PDT 2015


From: Marc-André Lureau <marcandre.lureau at redhat.com>

---
 server/tests/Makefile.am        |   2 +
 server/tests/basic_event_loop.c | 285 ++++++++++++++--------------------------
 2 files changed, 97 insertions(+), 190 deletions(-)

diff --git a/server/tests/Makefile.am b/server/tests/Makefile.am
index 32c97ce..926b3e9 100644
--- a/server/tests/Makefile.am
+++ b/server/tests/Makefile.am
@@ -1,6 +1,7 @@
 NULL =
 
 AM_CPPFLAGS =					\
+	$(GLIB2_CFLAGS)				\
 	-I$(top_srcdir)				\
 	-I$(top_srcdir)/common			\
 	-I$(top_srcdir)/server			\
@@ -17,6 +18,7 @@ AM_CPPFLAGS += -DAUTOMATED_TESTS
 endif
 
 LDADD =								\
+	$(GLIB2_LIBS)						\
 	$(top_builddir)/spice-common/common/libspice-common.la	\
 	$(top_builddir)/server/libspice-server.la		\
 	$(GLIB2_LIBS)						\
diff --git a/server/tests/basic_event_loop.c b/server/tests/basic_event_loop.c
index 79a4523..e692f3a 100644
--- a/server/tests/basic_event_loop.c
+++ b/server/tests/basic_event_loop.c
@@ -4,6 +4,7 @@
 #include <sys/time.h>
 #include <signal.h>
 #include <string.h>
+#include <glib.h>
 
 #include "spice/macros.h"
 #include "common/ring.h"
@@ -20,17 +21,12 @@ int debug = 0;
 
 #define NOT_IMPLEMENTED printf("%s not implemented\n", __func__);
 
-static SpiceCoreInterface core;
 
 typedef struct SpiceTimer {
-    RingItem link;
     SpiceTimerFunc func;
-    struct timeval tv_start;
-    int ms;
     void *opaque;
-} Timer;
-
-Ring timers;
+    guint source_id;
+} SpiceTimer;
 
 static SpiceTimer* timer_add(SpiceTimerFunc func, void *opaque)
 {
@@ -38,79 +34,113 @@ static SpiceTimer* timer_add(SpiceTimerFunc func, void *opaque)
 
     timer->func = func;
     timer->opaque = opaque;
-    ring_add(&timers, &timer->link);
+
     return timer;
 }
 
-static void add_ms_to_timeval(struct timeval *tv, int ms)
+static gboolean timer_func(gpointer user_data)
 {
-    tv->tv_usec += 1000 * ms;
-    while (tv->tv_usec >= 1000000) {
-        tv->tv_sec++;
-        tv->tv_usec -= 1000000;
-    }
+    SpiceTimer *timer = user_data;
+
+    timer->source_id = 0;
+    timer->func(timer->opaque);
+    /* timer might be free after func(), don't touch */
+
+    return FALSE;
 }
 
-static void timer_start(SpiceTimer *timer, uint32_t ms)
+static void timer_cancel(SpiceTimer *timer)
 {
-    ASSERT(ms);
-    gettimeofday(&timer->tv_start, NULL);
-    timer->ms = ms;
-    // already add ms to timer value
-    add_ms_to_timeval(&timer->tv_start, ms);
+    if (timer->source_id == 0)
+        return;
+
+    g_source_remove(timer->source_id);
+    timer->source_id = 0;
 }
 
-static void timer_cancel(SpiceTimer *timer)
+static void timer_start(SpiceTimer *timer, uint32_t ms)
 {
-    timer->ms = 0;
+    timer_cancel(timer);
+
+    timer->source_id = g_timeout_add(ms, timer_func, timer);
 }
 
 static void timer_remove(SpiceTimer *timer)
 {
-    ring_remove(&timer->link);
+    timer_cancel(timer);
+    g_free(timer);
 }
 
-struct SpiceWatch {
-    RingItem link;
-    int fd;
-    int event_mask;
-    SpiceWatchFunc func;
-    int removed;
+typedef struct SpiceWatch {
     void *opaque;
-};
+    guint source_id;
+    GIOChannel *channel;
+    SpiceWatchFunc func;
+} SpiceWatch;
+
+static GIOCondition spice_event_to_condition(int event_mask)
+{
+    GIOCondition condition = 0;
+
+    if (event_mask & SPICE_WATCH_EVENT_READ)
+        condition |= G_IO_IN;
+    if (event_mask & SPICE_WATCH_EVENT_WRITE)
+        condition |= G_IO_OUT;
+
+    return condition;
+}
+
+static int condition_to_spice_event(GIOCondition condition)
+{
+    int event = 0;
+
+    if (condition & G_IO_IN)
+        event |= SPICE_WATCH_EVENT_READ;
+    if (condition & G_IO_OUT)
+        event |= SPICE_WATCH_EVENT_WRITE;
+
+    return event;
+}
 
-Ring watches;
+static gboolean watch_func(GIOChannel *source, GIOCondition condition,
+                           gpointer data)
+{
+    SpiceWatch *watch = data;
+    int fd = g_io_channel_unix_get_fd(source);
+
+    watch->func(fd, condition_to_spice_event(condition), watch->opaque);
 
-int watch_count = 0;
+    return TRUE;
+}
 
 static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque)
 {
-    SpiceWatch *watch = malloc(sizeof(SpiceWatch));
+    SpiceWatch *watch;
+    GIOCondition condition = spice_event_to_condition(event_mask);
 
-    DPRINTF(0, "adding %p, fd=%d at %d", watch,
-        fd, watch_count);
-    watch->fd = fd;
-    watch->event_mask = event_mask;
+    watch = g_new(SpiceWatch, 1);
+    watch->channel = g_io_channel_unix_new(fd);
+    watch->source_id = g_io_add_watch(watch->channel, condition, watch_func, watch);
     watch->func = func;
     watch->opaque = opaque;
-    watch->removed = FALSE;
-    ring_item_init(&watch->link);
-    ring_add(&watches, &watch->link);
-    watch_count++;
+
     return watch;
 }
 
 static void watch_update_mask(SpiceWatch *watch, int event_mask)
 {
-    DPRINTF(0, "fd %d to %d", watch->fd, event_mask);
-    watch->event_mask = event_mask;
+    GIOCondition condition = spice_event_to_condition(event_mask);
+
+    g_source_remove(watch->source_id);
+    if (condition != 0)
+        watch->source_id = g_io_add_watch(watch->channel, condition, watch_func, watch);
 }
 
 static void watch_remove(SpiceWatch *watch)
 {
-    DPRINTF(0, "remove %p (fd %d)", watch, watch->fd);
-    watch_count--;
-    watch->removed = TRUE;
+    g_source_remove(watch->source_id);
+    g_io_channel_unref(watch->channel);
+    g_free(watch);
 }
 
 static void channel_event(int event, SpiceChannelEventInfo *info)
@@ -119,139 +149,12 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
             info->connection_id, info->type, info->id, event);
 }
 
-SpiceTimer *get_next_timer(void)
-{
-    SpiceTimer *next, *min;
-
-    if (ring_is_empty(&timers)) {
-        return NULL;
-    }
-    min = next = (SpiceTimer*)ring_get_head(&timers);
-    while ((next=(SpiceTimer*)ring_next(&timers, &next->link)) != NULL) {
-        if (next->ms &&
-            (next->tv_start.tv_sec < min->tv_start.tv_sec ||
-             (next->tv_start.tv_sec == min->tv_start.tv_sec &&
-              next->tv_start.tv_usec < min->tv_start.tv_usec))) {
-             min = next;
-        }
-    }
-    return min;
-}
-
-struct timeval now;
-
-void tv_b_minus_a_return_le_zero(struct timeval *a, struct timeval *b, struct timeval *dest)
-{
-    dest->tv_usec = b->tv_usec - a->tv_usec;
-    dest->tv_sec = b->tv_sec - a->tv_sec;
-    while (dest->tv_usec < 0) {
-        dest->tv_usec += 1000000;
-        dest->tv_sec--;
-    }
-    if (dest->tv_sec < 0) {
-        dest->tv_sec = 0;
-        dest->tv_usec = 0;
-    }
-}
-
-void calc_next_timeout(SpiceTimer *next, struct timeval *timeout)
-{
-    gettimeofday(&now, NULL);
-    tv_b_minus_a_return_le_zero(&now, &next->tv_start, timeout);
-}
-
-void timeout_timers(void)
-{
-    SpiceTimer *next;
-    struct timeval left;
-    int count = 0;
-
-    next = (SpiceTimer*)ring_get_head(&timers);
-    while (next != NULL) {
-        tv_b_minus_a_return_le_zero(&now, &next->tv_start, &left);
-        if (next->ms && left.tv_usec == 0 && left.tv_sec == 0) {
-            count++;
-            DPRINTF(2, "calling timer");
-            next->ms = 0;
-            next->func(next->opaque);
-        }
-        next = (SpiceTimer*)ring_next(&timers, &next->link);
-    }
-    DPRINTF(2, "called %d timers", count);
-}
-
 void basic_event_loop_mainloop(void)
 {
-    fd_set rfds, wfds;
-    int max_fd = -1;
-    int i;
-    int retval;
-    SpiceWatch *watch;
-    SpiceTimer *next_timer;
-    RingItem *link;
-    RingItem *next;
-    struct timeval next_timer_timeout;
-    struct timeval *timeout;
-
-    while (1) {
-        FD_ZERO(&rfds);
-        FD_ZERO(&wfds);
-        i = 0;
-        RING_FOREACH_SAFE(link, next, &watches) {
-            watch = (SpiceWatch*)link;
-            if (watch->removed) {
-                continue;
-            }
-            if (watch->event_mask & SPICE_WATCH_EVENT_READ) {
-                FD_SET(watch->fd, &rfds);
-                max_fd = watch->fd > max_fd ? watch->fd : max_fd;
-            }
-            if (watch->event_mask & SPICE_WATCH_EVENT_WRITE) {
-                FD_SET(watch->fd, &wfds);
-                max_fd = watch->fd > max_fd ? watch->fd : max_fd;
-            }
-            i++;
-        }
-        if ((next_timer = get_next_timer()) != NULL) {
-            calc_next_timeout(next_timer, &next_timer_timeout);
-            timeout = &next_timer_timeout;
-            DPRINTF(2, "timeout of %zd.%06zd",
-                    timeout->tv_sec, timeout->tv_usec);
-        } else {
-            timeout = NULL;
-        }
-        DPRINTF(1, "watching %d fds", i);
-        retval = select(max_fd + 1, &rfds, &wfds, NULL, timeout);
-        if (timeout != NULL) {
-            calc_next_timeout(next_timer, &next_timer_timeout);
-            if (next_timer_timeout.tv_sec == 0 &&
-                next_timer_timeout.tv_usec == 0) {
-                timeout_timers();
-            }
-        }
-        if (retval == -1) {
-            printf("error in select - exiting\n");
-            abort();
-        }
-        if (retval) {
-            RING_FOREACH_SAFE(link, next, &watches) {
-                watch = SPICE_CONTAINEROF(link, SpiceWatch, link);
-                if (!watch->removed && (watch->event_mask & SPICE_WATCH_EVENT_READ)
-                     && FD_ISSET(watch->fd, &rfds)) {
-                    watch->func(watch->fd, SPICE_WATCH_EVENT_READ, watch->opaque);
-                }
-                if (!watch->removed && (watch->event_mask & SPICE_WATCH_EVENT_WRITE)
-                     && FD_ISSET(watch->fd, &wfds)) {
-                    watch->func(watch->fd, SPICE_WATCH_EVENT_WRITE, watch->opaque);
-                }
-                if (watch->removed) {
-                    printf("freeing watch %p\n", watch);
-                    ring_remove(&watch->link);
-                    free(watch);
-                }
-            }
-        }
-    }
+    GMainLoop *loop = g_main_loop_new(NULL, FALSE);
+
+    g_main_loop_run(loop);
+    g_main_loop_unref(loop);
 }
 
 static void ignore_sigpipe(void)
@@ -264,21 +167,23 @@ static void ignore_sigpipe(void)
     sigaction(SIGPIPE, &act, NULL);
 }
 
+static SpiceCoreInterface core = {
+    .base = {
+        .major_version = SPICE_INTERFACE_CORE_MAJOR,
+        .minor_version = SPICE_INTERFACE_CORE_MINOR,
+    },
+    .timer_add = timer_add,
+    .timer_start = timer_start,
+    .timer_cancel = timer_cancel,
+    .timer_remove = timer_remove,
+    .watch_add = watch_add,
+    .watch_update_mask = watch_update_mask,
+    .watch_remove = watch_remove,
+    .channel_event = channel_event,
+};
+
 SpiceCoreInterface *basic_event_loop_init(void)
 {
-    ring_init(&watches);
-    ring_init(&timers);
-    memset(&core, 0, sizeof(core));
-    core.base.major_version = SPICE_INTERFACE_CORE_MAJOR;
-    core.base.minor_version = SPICE_INTERFACE_CORE_MINOR; // anything less then 3 and channel_event isn't called
-    core.timer_add = timer_add;
-    core.timer_start = timer_start;
-    core.timer_cancel = timer_cancel;
-    core.timer_remove = timer_remove;
-    core.watch_add = watch_add;
-    core.watch_update_mask = watch_update_mask;
-    core.watch_remove = watch_remove;
-    core.channel_event = channel_event;
     ignore_sigpipe();
     return &core;
 }
-- 
2.4.3



More information about the Spice-devel mailing list