From: Marc-André Lureau <marcandre.lureau@xxxxxxxxxx> --- 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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel