]> git.proxmox.com Git - spiceterm.git/commitdiff
use glib event loop
authorDietmar Maurer <dietmar@proxmox.com>
Tue, 10 Sep 2013 09:57:19 +0000 (11:57 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Tue, 10 Sep 2013 09:57:19 +0000 (11:57 +0200)
Makefile
basic_event_loop.c
ring.h [deleted file]

index 2a986d4a6b6806316eca3bcc130a4bcb1b4177ae..2a27efd5e8845f9bf38481620b9a531c5fe6dba8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 
 PROGRAMS=test_display_no_ssl spiceterm
 
-HEADERS=test_display_base.h basic_event_loop.h ring.h glyphs.h spiceterm.h
+HEADERS=test_display_base.h basic_event_loop.h glyphs.h spiceterm.h
 SOURCES=test_display_base.c basic_event_loop.c
 
 all: ${PROGRAMS}
index 4452b5af1da24bf3a05f37c4ec00ea4112b2c58b..39e42702f28f753dfe5e173868f1146919f59cb6 100644 (file)
 #include <glib.h>
 
 #include <spice/macros.h>
-#include "ring.h"
 #include "basic_event_loop.h"
 
-int debug = 0;
-
+int debug = 1;
+    
 #define DPRINTF(x, format, ...) { \
     if (x <= debug) { \
         printf("%s: " format "\n" , __FUNCTION__, ## __VA_ARGS__); \
     } \
 }
 
-#define NOT_IMPLEMENTED printf("%s not implemented\n", __func__);
+static GMainLoop *main_loop;
 
 static SpiceCoreInterface core;
 
 typedef struct SpiceTimer {
-    RingItem link;
+    GSource *source;
     SpiceTimerFunc func;
-    struct timeval tv_start;
     int ms;
     void *opaque;
 } Timer;
 
-Ring timers;
-
 static SpiceTimer* timer_add(SpiceTimerFunc func, void *opaque)
 {
+    g_return_val_if_fail(func != NULL, NULL);
+
     SpiceTimer *timer = g_new0(SpiceTimer, 1);
 
     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_callback(gpointer data)
 {
-    tv->tv_usec += 1000 * ms;
-    while (tv->tv_usec >= 1000000) {
-        tv->tv_sec++;
-        tv->tv_usec -= 1000000;
-    }
+    SpiceTimer *timer = (SpiceTimer *)data;
+    g_assert(timer != NULL);
+    g_assert(timer->func != NULL);
+
+    timer->func(timer->opaque);
+
+    return FALSE;
 }
 
 static void timer_start(SpiceTimer *timer, uint32_t ms)
 {
-    g_assert(ms != 0);
-    gettimeofday(&timer->tv_start, NULL);
-    timer->ms = ms;
-    // already add ms to timer value
-    add_ms_to_timeval(&timer->tv_start, ms);
+    g_return_if_fail(timer != NULL);
+    g_return_if_fail(ms != 0);
+
+    if (timer->source != NULL) {
+        g_source_destroy(timer->source);
+    }
+    
+    timer->source = g_timeout_source_new(ms);
+    g_assert(timer->source != NULL);
+
+    g_source_set_callback(timer->source, timer_callback, timer, NULL);
+
+    g_source_attach(timer->source, NULL);
 }
 
 static void timer_cancel(SpiceTimer *timer)
 {
+    g_return_if_fail(timer != NULL);
+
+    if (timer->source != NULL) {
+        g_source_destroy(timer->source);
+        timer->source = NULL;
+    }
+
     timer->ms = 0;
 }
 
 static void timer_remove(SpiceTimer *timer)
 {
-    ring_remove(&timer->link);
+    g_return_if_fail(timer != NULL);
+
+    timer_cancel(timer);
+    g_free(timer);
 }
 
 struct SpiceWatch {
-    RingItem link;
+    GIOChannel *channel;
+    guint evid;
     int fd;
     int event_mask;
     SpiceWatchFunc func;
-    int removed;
     void *opaque;
 };
 
-Ring watches;
+static gboolean watch_callback(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+    SpiceWatch *watch = (SpiceWatch *)data;
+
+    g_assert(watch != NULL);
+    g_assert(watch->func != NULL);
+
+    if (condition & G_IO_OUT) {
+        watch->func(watch->fd, SPICE_WATCH_EVENT_WRITE, watch->opaque);
+    }
+
+    if (condition & G_IO_IN) {
+        watch->func(watch->fd, SPICE_WATCH_EVENT_READ, watch->opaque);
+    }
+
+    return TRUE;
+}
+
+static GIOCondition event_mask_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;
+    }
 
-int watch_count = 0;
+    return condition;
+}
 
 static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque)
 {
     SpiceWatch *watch = g_new0(SpiceWatch, 1);
 
-    DPRINTF(0, "adding %p, fd=%d at %d", watch,
-        fd, watch_count);
+    DPRINTF(0, "adding %p, fd=%d", watch, fd);
+
     watch->fd = fd;
     watch->event_mask = event_mask;
     watch->func = func;
     watch->opaque = opaque;
-    watch->removed = FALSE;
-    ring_item_init(&watch->link);
-    ring_add(&watches, &watch->link);
-    watch_count++;
+    watch->channel = g_io_channel_unix_new(fd);
+
+    g_assert(watch->channel != NULL);
+    g_io_channel_set_encoding(watch->channel, NULL, NULL);
+
+    GIOCondition condition = event_mask_to_condition(event_mask);
+    watch->evid = g_io_add_watch(watch->channel, condition, watch_callback, watch);
+
     return watch;
 }
 
 static void watch_update_mask(SpiceWatch *watch, int event_mask)
 {
+    g_assert(watch != NULL);
+
     DPRINTF(0, "fd %d to %d", watch->fd, event_mask);
     watch->event_mask = event_mask;
-}
 
-static void watch_remove(SpiceWatch *watch)
-{
-    DPRINTF(0, "remove %p (fd %d)", watch, watch->fd);
-    watch_count--;
-    watch->removed = TRUE;
-}
+    g_source_remove(watch->evid);
 
-static void channel_event(int event, SpiceChannelEventInfo *info)
-{
-    DPRINTF(0, "channel event con, type, id, event: %ld, %d, %d, %d",
-            info->connection_id, info->type, info->id, event);
+    GIOCondition condition = event_mask_to_condition(event_mask);
+    watch->evid = g_io_add_watch(watch->channel, condition, watch_callback, watch);    
 }
 
-SpiceTimer *get_next_timer(void)
+static void watch_remove(SpiceWatch *watch)
 {
-    SpiceTimer *next, *min;
+    g_assert(watch != NULL);
 
-    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;
+    DPRINTF(0, "remove %p (fd %d)", watch, watch->fd);
 
-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;
-    }
-}
+    g_source_remove(watch->evid);
+    g_io_channel_unref(watch->channel);
 
-void calc_next_timeout(SpiceTimer *next, struct timeval *timeout)
-{
-    gettimeofday(&now, NULL);
-    tv_b_minus_a_return_le_zero(&now, &next->tv_start, timeout);
+    g_free(watch);
 }
 
-void timeout_timers(void)
+static void channel_event(int event, SpiceChannelEventInfo *info)
 {
-    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);
+    DPRINTF(0, "channel event con, type, id, event: %ld, %d, %d, %d",
+            info->connection_id, info->type, info->id, event);
 }
 
 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);
-                    g_free(watch);
-                }
-            }
-        }
-    }
+    g_main_loop_run(main_loop);
 }
 
 static void ignore_sigpipe(void)
@@ -266,11 +200,11 @@ static void ignore_sigpipe(void)
 
 SpiceCoreInterface *basic_event_loop_init(void)
 {
-    ring_init(&watches);
-    ring_init(&timers);
+    main_loop = g_main_loop_new(NULL, FALSE);
+
     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.base.minor_version = SPICE_INTERFACE_CORE_MINOR;
     core.timer_add = timer_add;
     core.timer_start = timer_start;
     core.timer_cancel = timer_cancel;
@@ -279,6 +213,8 @@ SpiceCoreInterface *basic_event_loop_init(void)
     core.watch_update_mask = watch_update_mask;
     core.watch_remove = watch_remove;
     core.channel_event = channel_event;
+
     ignore_sigpipe();
+
     return &core;
 }
diff --git a/ring.h b/ring.h
deleted file mode 100644 (file)
index dbc39dc..0000000
--- a/ring.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_RING2
-#define _H_RING2
-
-#include <glib.h>
-#include <spice/macros.h>
-//#include "spice_common.h"
-
-SPICE_BEGIN_DECLS
-
-typedef struct Ring RingItem;
-typedef struct Ring {
-    RingItem *prev;
-    RingItem *next;
-} Ring;
-
-static inline void ring_init(Ring *ring)
-{
-    ring->next = ring->prev = ring;
-}
-
-static inline void ring_item_init(RingItem *item)
-{
-    item->next = item->prev = NULL;
-}
-
-static inline int ring_item_is_linked(RingItem *item)
-{
-    return !!item->next;
-}
-
-static inline int ring_is_empty(Ring *ring)
-{
-    g_assert(ring->next != NULL && ring->prev != NULL);
-    return ring == ring->next;
-}
-
-static inline void ring_add(Ring *ring, RingItem *item)
-{
-    g_assert(ring->next != NULL && ring->prev != NULL);
-    g_assert(item->next == NULL && item->prev == NULL);
-
-    item->next = ring->next;
-    item->prev = ring;
-    ring->next = item->next->prev = item;
-}
-
-static inline void ring_add_after(RingItem *item, RingItem *pos)
-{
-    ring_add(pos, item);
-}
-
-static inline void ring_add_before(RingItem *item, RingItem *pos)
-{
-    ring_add(pos->prev, item);
-}
-
-static inline void __ring_remove(RingItem *item)
-{
-    item->next->prev = item->prev;
-    item->prev->next = item->next;
-    item->prev = item->next = 0;
-}
-
-static inline void ring_remove(RingItem *item)
-{
-    g_assert(item->next != NULL && item->prev != NULL);
-    g_assert(item->next != item);
-
-    __ring_remove(item);
-}
-
-static inline RingItem *ring_get_head(Ring *ring)
-{
-    RingItem *ret;
-
-    g_assert(ring->next != NULL && ring->prev != NULL);
-
-    if (ring_is_empty(ring)) {
-        return NULL;
-    }
-    ret = ring->next;
-    return ret;
-}
-
-static inline RingItem *ring_get_tail(Ring *ring)
-{
-    RingItem *ret;
-
-    g_assert(ring->next != NULL && ring->prev != NULL);
-
-    if (ring_is_empty(ring)) {
-        return NULL;
-    }
-    ret = ring->prev;
-    return ret;
-}
-
-static inline RingItem *ring_next(Ring *ring, RingItem *pos)
-{
-    RingItem *ret;
-
-    g_assert(ring->next != NULL && ring->prev != NULL);
-    g_assert(pos);
-    g_assert(pos->next != NULL && pos->prev != NULL);
-    ret = pos->next;
-    return (ret == ring) ? NULL : ret;
-}
-
-static inline RingItem *ring_prev(Ring *ring, RingItem *pos)
-{
-    RingItem *ret;
-
-    g_assert(ring->next != NULL && ring->prev != NULL);
-    g_assert(pos);
-    g_assert(pos->next != NULL && pos->prev != NULL);
-    ret = pos->prev;
-    return (ret == ring) ? NULL : ret;
-}
-
-#define RING_FOREACH_SAFE(var, next, ring)                    \
-    for ((var) = ring_get_head(ring);                         \
-            (var) && ((next) = ring_next(ring, (var)), 1);    \
-            (var) = (next))
-
-
-#define RING_FOREACH(var, ring)                 \
-    for ((var) = ring_get_head(ring);           \
-            (var);                              \
-            (var) = ring_next(ring, var))
-
-#define RING_FOREACH_REVERSED(var, ring)        \
-    for ((var) = ring_get_tail(ring);           \
-            (var);                              \
-            (var) = ring_prev(ring, var))
-
-
-static inline unsigned int ring_get_length(Ring *ring)
-{
-    RingItem *i;
-    unsigned int ret = 0;
-
-    for (i = ring_get_head(ring);
-         i != NULL;
-         i = ring_next(ring, i))
-        ret++;
-
-    return ret;
-}
-
-SPICE_END_DECLS
-
-#endif