[Spice-devel] [PATCH 1/3] worker: use glib main loop

Frediano Ziglio fziglio at redhat.com
Wed Jan 20 08:42:20 PST 2016


> 
> Use the glib mainloop instead of writing our own. The glib loop is both
> cleaner to use and is more extensible. It is also very mature and
> reduces the maintenance burden on the spice server.
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau at gmail.com>
> Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
> Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
> ---
>  server/Makefile.am         |   2 -
>  server/red-worker.c        | 252 +++++++++++++++++-------------------------
>  server/red-worker.h        |   1 +
>  server/spice_timer_queue.c | 267
>  ---------------------------------------------
>  server/spice_timer_queue.h |  44 --------
>  5 files changed, 99 insertions(+), 467 deletions(-)
>  delete mode 100644 server/spice_timer_queue.c
>  delete mode 100644 server/spice_timer_queue.h
> 
> diff --git a/server/Makefile.am b/server/Makefile.am
> index bef999d..5d65526 100644
> --- a/server/Makefile.am
> +++ b/server/Makefile.am
> @@ -120,8 +120,6 @@ libserver_la_SOURCES =				\
>  	sound.h				\
>  	stat.h					\
>  	spicevmc.c				\
> -	spice_timer_queue.c			\
> -	spice_timer_queue.h			\
>  	zlib-encoder.c				\
>  	zlib-encoder.h				\
>  	image-cache.h			\
> diff --git a/server/red-worker.c b/server/red-worker.c
> index ad8ba1a..24bb435 100644
> --- a/server/red-worker.c
> +++ b/server/red-worker.c
> @@ -49,30 +49,22 @@
>  
>  #include "spice.h"
>  #include "red-worker.h"
> -#include "spice_timer_queue.h"
>  #include "cursor-channel.h"
>  #include "tree.h"
>  
>  #define CMD_RING_POLL_TIMEOUT 10 //milli
>  #define CMD_RING_POLL_RETRIES 200
>  
> -#define MAX_EVENT_SOURCES 20
>  #define INF_EVENT_WAIT ~0
>  
> -struct SpiceWatch {
> -    struct RedWorker *worker;
> -    SpiceWatchFunc watch_func;
> -    void *watch_func_opaque;
> -};
> -
>  struct RedWorker {
>      pthread_t thread;
>      QXLInstance *qxl;
>      RedDispatcher *red_dispatcher;
>      int running;
>      SpiceCoreInterfaceInternal core;
> -    struct pollfd poll_fds[MAX_EVENT_SOURCES];
> -    struct SpiceWatch watches[MAX_EVENT_SOURCES];
> +
> +    GMainContext *main_context;
>      unsigned int event_timeout;
>  
>      DisplayChannel *display_channel;
> @@ -99,6 +91,13 @@ struct RedWorker {
>      FILE *record_fd;
>  };
>  
> +GMainContext* red_worker_get_main_context(RedWorker *worker)
> +{
> +    spice_return_val_if_fail(worker, NULL);
> +
> +    return worker->main_context;
> +}
> +

This function is not used in all code.
Also is not used in all refactory branch.
Should be just removed.

>  QXLInstance* red_worker_get_qxl(RedWorker *worker)
>  {
>      spice_return_val_if_fail(worker != NULL, NULL);
> @@ -510,83 +509,18 @@ static int
> common_channel_config_socket(RedChannelClient *rcc)
>      return TRUE;
>  }
>  
> -static void worker_watch_update_mask(SpiceWatch *watch, int event_mask)
> -{
> -    struct RedWorker *worker;
> -    int i;
> -
> -    if (!watch) {
> -        return;
> -    }
> -
> -    worker = watch->worker;
> -    i = watch - worker->watches;
> -
> -    worker->poll_fds[i].events = 0;
> -    if (event_mask & SPICE_WATCH_EVENT_READ) {
> -        worker->poll_fds[i].events |= POLLIN;
> -    }
> -    if (event_mask & SPICE_WATCH_EVENT_WRITE) {
> -        worker->poll_fds[i].events |= POLLOUT;
> -    }
> -}
> -
> -static SpiceWatch *worker_watch_add(const SpiceCoreInterfaceInternal *iface,
> -                                    int fd, int event_mask, SpiceWatchFunc
> func, void *opaque)
> +static inline GMainContext *event_loop_context_from_iface(const
> SpiceCoreInterfaceInternal *iface)
>  {
>      RedWorker *worker = SPICE_CONTAINEROF(iface, RedWorker, core);
> -    int i;
>  
> -    /* Search for a free slot in our poll_fds & watches arrays */
> -    for (i = 0; i < MAX_EVENT_SOURCES; i++) {
> -        if (worker->poll_fds[i].fd == -1) {
> -            break;
> -        }
> -    }
> -    if (i == MAX_EVENT_SOURCES) {
> -        /* Since we are a channel core implementation, we always get called
> from
> -           red_channel_client_create(), so opaque always is our rcc */
> -        RedChannelClient *rcc = opaque;
> -        spice_warning("could not add a watch for channel type %u id %u",
> -                      rcc->channel->type, rcc->channel->id);
> -        return NULL;
> -    }
> -
> -    worker->poll_fds[i].fd = fd;
> -    worker->watches[i].worker = worker;
> -    worker->watches[i].watch_func = func;
> -    worker->watches[i].watch_func_opaque = opaque;
> -    worker_watch_update_mask(&worker->watches[i], event_mask);
> -
> -    return &worker->watches[i];
> +    return worker->main_context;
>  }
>  
> -static void worker_watch_remove(SpiceWatch *watch)
> +static void event_loop_channel_event(int event, SpiceChannelEventInfo *info)
>  {
> -    if (!watch) {
> -        return;
> -    }
> -
> -    /* Note we don't touch the poll_fd here, to avoid the
> -       poll_fds/watches table entry getting re-used in the same
> -       red_worker_main loop over the fds as it is removed.
> -
> -       This is done because re-using it while events were pending on
> -       the fd previously occupying the slot would lead to incorrectly
> -       calling the watch_func for the new fd. */
> -    memset(watch, 0, sizeof(SpiceWatch));
>  }
>  
> -static const SpiceCoreInterfaceInternal worker_core_initializer = {
> -    .timer_add = spice_timer_queue_add,
> -    .timer_start = spice_timer_set,
> -    .timer_cancel = spice_timer_cancel,
> -    .timer_remove = spice_timer_remove,
> -
> -    .watch_update_mask = worker_watch_update_mask,
> -    .watch_add = worker_watch_add,
> -    .watch_remove = worker_watch_remove,
> -};
> +#include "event-loop.tmpl.c"
>  
>  CommonChannelClient *common_channel_new_client(CommonChannel *common,
>                                                 int size,
> @@ -1524,25 +1458,91 @@ static void register_callbacks(Dispatcher
> *dispatcher)
>  
>  
>  
> -static void handle_dev_input(int fd, int event, void *opaque)
> +static gboolean worker_dispatcher_cb(GIOChannel *source, GIOCondition
> condition,
> +                                     gpointer data)
>  {
> -    RedWorker *worker = opaque;
> +    RedWorker *worker = data;
>  
>      dispatcher_handle_recv_read(red_dispatcher_get_dispatcher(worker->red_dispatcher));
> +
> +    return TRUE;
>  }
>  
> +typedef struct RedWorkerSource {
> +    GSource source;
> +    RedWorker *worker;
> +} RedWorkerSource;
> +
> +static gboolean worker_source_prepare(GSource *source, gint *p_timeout)
> +{
> +    RedWorkerSource *wsource = SPICE_CONTAINEROF(source, RedWorkerSource,
> source);
> +    RedWorker *worker = wsource->worker;
> +    unsigned int timeout;
> +
> +    timeout = MIN(worker->event_timeout,
> +
> display_channel_get_streams_timeout(worker->display_channel));
> +
> +    *p_timeout = (timeout == INF_EVENT_WAIT) ? -1 : timeout;
> +    if (*p_timeout == 0)
> +        return TRUE;
> +
> +    return FALSE;
> +}
> +
> +static gboolean worker_source_check(GSource *source)
> +{
> +    RedWorkerSource *wsource = SPICE_CONTAINEROF(source, RedWorkerSource,
> source);
> +    RedWorker *worker = wsource->worker;
> +
> +    return worker->running /* TODO && worker->pending_process */;
> +}
> +
> +static gboolean worker_source_dispatch(GSource *source, GSourceFunc
> callback,
> +                                       gpointer user_data)
> +{
> +    RedWorkerSource *wsource = SPICE_CONTAINEROF(source, RedWorkerSource,
> source);
> +    RedWorker *worker = wsource->worker;
> +    DisplayChannel *display = worker->display_channel;
> +    int ring_is_empty;
> +
> +    /* during migration, in the dest, the display channel can be initialized
> +       while the global lz data not since migrate data msg hasn't been
> +       received yet */
> +    /* FIXME: why is this here, and not in display_channel_create */

Good question, still is a TODO

> +    display_channel_free_glz_drawables_to_free(display);
> +
> +    /* FIXME: could use its own source */

This is more a TODO then a FIXME

> +    stream_timeout(display);
> +
> +    worker->event_timeout = INF_EVENT_WAIT;
> +    red_process_cursor(worker, MAX_PIPE_SIZE, &ring_is_empty);
> +    red_process_display(worker, MAX_PIPE_SIZE, &ring_is_empty);
> +
> +    /* FIXME: remove me? that should be handled by watch out condition */

Good idea too. I think is a TODO even this.
Is a good idea because would probably decrease the latency introduced with
this patch.
About latency, should be useful to use Jonathon patches to check how the loop
performs.

> +    red_push(worker);
> +
> +    return TRUE;
> +}
> +
> +/* cannot be const */
> +static GSourceFuncs worker_source_funcs = {
> +    .prepare = worker_source_prepare,
> +    .check = worker_source_check,
> +    .dispatch = worker_source_dispatch,
> +};
> +
>  RedWorker* red_worker_new(QXLInstance *qxl, RedDispatcher *red_dispatcher)
>  {
>      QXLDevInitInfo init_info;
>      RedWorker *worker;
>      Dispatcher *dispatcher;
> -    int i;
>      const char *record_filename;
>  
>      qxl->st->qif->get_init_info(qxl, &init_info);
>  
>      worker = spice_new0(RedWorker, 1);
> -    worker->core = worker_core_initializer;
> +    worker->core = event_loop_core;
> +    worker->main_context = g_main_context_new();
>  
>      record_filename = getenv("SPICE_WORKER_RECORD_FILENAME");
>      if (record_filename) {
> @@ -1576,15 +1576,17 @@ RedWorker* red_worker_new(QXLInstance *qxl,
> RedDispatcher *red_dispatcher)
>      worker->wakeup_counter = stat_add_counter(worker->stat, "wakeups",
>      TRUE);
>      worker->command_counter = stat_add_counter(worker->stat, "commands",
>      TRUE);
>  #endif
> -    for (i = 0; i < MAX_EVENT_SOURCES; i++) {
> -        worker->poll_fds[i].fd = -1;
> -    }
>  
> -    worker->poll_fds[0].fd = dispatcher_get_recv_fd(dispatcher);
> -    worker->poll_fds[0].events = POLLIN;
> -    worker->watches[0].worker = worker;
> -    worker->watches[0].watch_func = handle_dev_input;
> -    worker->watches[0].watch_func_opaque = worker;
> +    GIOChannel *channel =
> g_io_channel_unix_new(dispatcher_get_recv_fd(dispatcher));
> +    GSource *source = g_io_create_watch(channel, G_IO_IN);
> +    g_source_set_callback(source, (GSourceFunc)worker_dispatcher_cb, worker,
> NULL);
> +    g_source_attach(source, worker->main_context);
> +    g_source_unref(source);
> +

Why not using just a watch using our SpiceCoreInterface?

> +    source = g_source_new(&worker_source_funcs, sizeof(RedWorkerSource));
> +    SPICE_CONTAINEROF(source, RedWorkerSource, source)->worker = worker;
> +    g_source_attach(source, worker->main_context);
> +    g_source_unref(source);
>  
>      memslot_info_init(&worker->mem_slots,
>                        init_info.num_memslots_groups,
> @@ -1613,73 +1615,15 @@ SPICE_GNUC_NORETURN static void *red_worker_main(void
> *arg)
>      spice_assert(MAX_PIPE_SIZE > WIDE_CLIENT_ACK_WINDOW &&
>             MAX_PIPE_SIZE > NARROW_CLIENT_ACK_WINDOW); //ensure wakeup by ack
>             message
>  
> -    if (!spice_timer_queue_create()) {
> -        spice_error("failed to create timer queue");
> -    }
> -
>      RED_CHANNEL(worker->cursor_channel)->thread_id = pthread_self();
>      RED_CHANNEL(worker->display_channel)->thread_id = pthread_self();
>  
> -    for (;;) {
> -        int i, num_events;
> -        unsigned int timeout;
> -
> -        timeout = spice_timer_queue_get_timeout_ms();
> -        worker->event_timeout = MIN(timeout, worker->event_timeout);
> -        timeout =
> display_channel_get_streams_timeout(worker->display_channel);
> -        worker->event_timeout = MIN(timeout, worker->event_timeout);
> -        num_events = poll(worker->poll_fds, MAX_EVENT_SOURCES,
> worker->event_timeout);
> -        stream_timeout(worker->display_channel);
> -        spice_timer_queue_cb();
> -
> -        if (worker->display_channel) {
> -            /* during migration, in the dest, the display channel can be
> initialized
> -               while the global lz data not since migrate data msg hasn't
> been
> -               received yet */
> -
> display_channel_free_glz_drawables_to_free(worker->display_channel);
> -        }
> -
> -        worker->event_timeout = INF_EVENT_WAIT;
> -        if (num_events == -1) {
> -            if (errno != EINTR) {
> -                spice_error("poll failed, %s", strerror(errno));
> -            }
> -        }
> -
> -        for (i = 0; i < MAX_EVENT_SOURCES; i++) {
> -            /* The watch may have been removed by the watch-func from
> -               another fd (ie a disconnect through the dispatcher),
> -               in this case watch_func is NULL. */
> -            if (worker->poll_fds[i].revents &&
> worker->watches[i].watch_func) {
> -                int events = 0;
> -                if (worker->poll_fds[i].revents & POLLIN) {
> -                    events |= SPICE_WATCH_EVENT_READ;
> -                }
> -                if (worker->poll_fds[i].revents & POLLOUT) {
> -                    events |= SPICE_WATCH_EVENT_WRITE;
> -                }
> -                worker->watches[i].watch_func(worker->poll_fds[i].fd,
> events,
> -
> worker->watches[i].watch_func_opaque);
> -            }
> -        }
> -
> -        /* Clear the poll_fd for any removed watches, see the comment in
> -           watch_remove for why we don't do this there. */
> -        for (i = 0; i < MAX_EVENT_SOURCES; i++) {
> -            if (!worker->watches[i].watch_func) {
> -                worker->poll_fds[i].fd = -1;
> -            }
> -        }
> -
> -        if (worker->running) {
> -            int ring_is_empty;
> -            red_process_cursor(worker, MAX_PIPE_SIZE, &ring_is_empty);
> -            red_process_display(worker, MAX_PIPE_SIZE, &ring_is_empty);
> -        }
> -        red_push(worker);
> -    }
> +    GMainLoop *loop = g_main_loop_new(worker->main_context, FALSE);
> +    g_main_loop_run(loop);
> +    g_main_loop_unref(loop);
>  
> -    spice_warn_if_reached();
> +    /* FIXME: free worker, and join threads */
> +    exit(0);
>  }
>  
>  bool red_worker_run(RedWorker *worker)
> diff --git a/server/red-worker.h b/server/red-worker.h
> index 91533e1..6bcab3d 100644
> --- a/server/red-worker.h
> +++ b/server/red-worker.h
> @@ -97,6 +97,7 @@ bool       red_worker_run(RedWorker *worker);
>  QXLInstance* red_worker_get_qxl(RedWorker *worker);
>  RedChannel* red_worker_get_cursor_channel(RedWorker *worker);
>  RedChannel* red_worker_get_display_channel(RedWorker *worker);
> +GMainContext* red_worker_get_main_context(RedWorker *worker);
>  RedMemSlotInfo* red_worker_get_memslot(RedWorker *worker);
>  
>  void red_drawable_unref(RedWorker *worker, RedDrawable *red_drawable,
> diff --git a/server/spice_timer_queue.c b/server/spice_timer_queue.c
> deleted file mode 100644
> index 421b090..0000000
> --- a/server/spice_timer_queue.c
> +++ /dev/null
> @@ -1,267 +0,0 @@
> -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> -/*
> -   Copyright (C) 2013 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/>.
> -*/
> -#include <config.h>
> -#include <pthread.h>
> -#include "red-common.h"
> -#include "spice_timer_queue.h"
> -#include "common/ring.h"
> -#include "utils.h"
> -
> -static Ring timer_queue_list;
> -static int queue_count = 0;
> -static pthread_mutex_t queue_list_lock = PTHREAD_MUTEX_INITIALIZER;
> -
> -static void spice_timer_queue_init(void)
> -{
> -    ring_init(&timer_queue_list);
> -}
> -
> -struct SpiceTimer {
> -    RingItem link;
> -    RingItem active_link;
> -
> -    SpiceTimerFunc func;
> -    void *opaque;
> -
> -    SpiceTimerQueue *queue;
> -
> -    int is_active;
> -    uint32_t ms;
> -    uint64_t expiry_time;
> -};
> -
> -struct SpiceTimerQueue {
> -    RingItem link;
> -    pthread_t thread;
> -    Ring timers;
> -    Ring active_timers;
> -};
> -
> -static SpiceTimerQueue *spice_timer_queue_find(void)
> -{
> -    pthread_t self = pthread_self();
> -    RingItem *queue_item;
> -
> -    RING_FOREACH(queue_item, &timer_queue_list) {
> -         SpiceTimerQueue *queue = SPICE_CONTAINEROF(queue_item,
> SpiceTimerQueue, link);
> -
> -         if (pthread_equal(self, queue->thread) != 0) {
> -            return queue;
> -         }
> -    }
> -
> -    return NULL;
> -}
> -
> -static SpiceTimerQueue *spice_timer_queue_find_with_lock(void)
> -{
> -    SpiceTimerQueue *queue;
> -
> -    pthread_mutex_lock(&queue_list_lock);
> -    queue = spice_timer_queue_find();
> -    pthread_mutex_unlock(&queue_list_lock);
> -    return queue;
> -}
> -
> -int spice_timer_queue_create(void)
> -{
> -    SpiceTimerQueue *queue;
> -
> -    pthread_mutex_lock(&queue_list_lock);
> -    if (queue_count == 0) {
> -        spice_timer_queue_init();
> -    }
> -
> -    if (spice_timer_queue_find() != NULL) {
> -        spice_printerr("timer queue was already created for the thread");
> -        return FALSE;
> -    }
> -
> -    queue = spice_new0(SpiceTimerQueue, 1);
> -    queue->thread = pthread_self();
> -    ring_init(&queue->timers);
> -    ring_init(&queue->active_timers);
> -
> -    ring_add(&timer_queue_list, &queue->link);
> -    queue_count++;
> -
> -    pthread_mutex_unlock(&queue_list_lock);
> -
> -    return TRUE;
> -}
> -
> -void spice_timer_queue_destroy(void)
> -{
> -    RingItem *item;
> -    SpiceTimerQueue *queue;
> -
> -    pthread_mutex_lock(&queue_list_lock);
> -    queue = spice_timer_queue_find();
> -
> -    spice_assert(queue != NULL);
> -
> -    while ((item = ring_get_head(&queue->timers))) {
> -        SpiceTimer *timer;
> -
> -        timer = SPICE_CONTAINEROF(item, SpiceTimer, link);
> -        spice_timer_remove(timer);
> -    }
> -
> -    ring_remove(&queue->link);
> -    free(queue);
> -    queue_count--;
> -
> -    pthread_mutex_unlock(&queue_list_lock);
> -}
> -
> -SpiceTimer *spice_timer_queue_add(const SpiceCoreInterfaceInternal *iface,
> -                                  SpiceTimerFunc func, void *opaque)
> -{
> -    SpiceTimer *timer = spice_new0(SpiceTimer, 1);
> -    SpiceTimerQueue *queue = spice_timer_queue_find_with_lock();
> -
> -    spice_assert(queue != NULL);
> -
> -    ring_item_init(&timer->link);
> -    ring_item_init(&timer->active_link);
> -
> -    timer->opaque = opaque;
> -    timer->func = func;
> -    timer->queue = queue;
> -
> -    ring_add(&queue->timers, &timer->link);
> -
> -    return timer;
> -}
> -
> -static void _spice_timer_set(SpiceTimer *timer, uint32_t ms, uint64_t now)
> -{
> -    RingItem *next_item;
> -    SpiceTimerQueue *queue;
> -
> -    if (timer->is_active) {
> -        spice_timer_cancel(timer);
> -    }
> -
> -    queue = timer->queue;
> -    timer->expiry_time = now + ms;
> -    timer->ms = ms;
> -
> -    RING_FOREACH(next_item, &queue->active_timers) {
> -        SpiceTimer *next_timer = SPICE_CONTAINEROF(next_item, SpiceTimer,
> active_link);
> -
> -        if (timer->expiry_time <= next_timer->expiry_time) {
> -            break;
> -        }
> -    }
> -
> -    if (next_item) {
> -        ring_add_before(&timer->active_link, next_item);
> -    } else {
> -        ring_add_before(&timer->active_link, &queue->active_timers);
> -    }
> -    timer->is_active = TRUE;
> -}
> -
> -void spice_timer_set(SpiceTimer *timer, uint32_t ms)
> -{
> -    spice_assert(pthread_equal(timer->queue->thread, pthread_self()) != 0);
> -
> -    _spice_timer_set(timer, ms, spice_get_monotonic_time_ms());
> -}
> -
> -void spice_timer_cancel(SpiceTimer *timer)
> -{
> -    spice_assert(pthread_equal(timer->queue->thread, pthread_self()) != 0);
> -
> -    if (!ring_item_is_linked(&timer->active_link)) {
> -        spice_assert(!timer->is_active);
> -        return;
> -    }
> -
> -    spice_assert(timer->is_active);
> -    ring_remove(&timer->active_link);
> -    timer->is_active = FALSE;
> -}
> -
> -void spice_timer_remove(SpiceTimer *timer)
> -{
> -    spice_assert(timer->queue);
> -    spice_assert(ring_item_is_linked(&timer->link));
> -    spice_assert(pthread_equal(timer->queue->thread, pthread_self()) != 0);
> -
> -    if (timer->is_active) {
> -        spice_assert(ring_item_is_linked(&timer->active_link));
> -        ring_remove(&timer->active_link);
> -    }
> -    ring_remove(&timer->link);
> -    free(timer);
> -}
> -
> -unsigned int spice_timer_queue_get_timeout_ms(void)
> -{
> -    int64_t now_ms;
> -    RingItem *head;
> -    SpiceTimer *head_timer;
> -    SpiceTimerQueue *queue = spice_timer_queue_find_with_lock();
> -
> -    spice_assert(queue != NULL);
> -
> -    if (ring_is_empty(&queue->active_timers)) {
> -        return -1;
> -    }
> -
> -    head = ring_get_head(&queue->active_timers);
> -    head_timer = SPICE_CONTAINEROF(head, SpiceTimer, active_link);
> -
> -    now_ms = spice_get_monotonic_time_ms();
> -
> -    return MAX(0, ((int64_t)head_timer->expiry_time - now_ms));
> -}
> -
> -
> -void spice_timer_queue_cb(void)
> -{
> -    uint64_t now_ms;
> -    RingItem *head;
> -    SpiceTimerQueue *queue = spice_timer_queue_find_with_lock();
> -
> -    spice_assert(queue != NULL);
> -
> -    if (ring_is_empty(&queue->active_timers)) {
> -        return;
> -    }
> -
> -    now_ms = spice_get_monotonic_time_ms();
> -
> -    while ((head = ring_get_head(&queue->active_timers))) {
> -        SpiceTimer *timer = SPICE_CONTAINEROF(head, SpiceTimer,
> active_link);
> -
> -        if (timer->expiry_time > now_ms) {
> -            break;
> -        } else {
> -            /* Remove active timer before calling the timer function.
> -             * Timer function could delete the timer making the timer
> -             * pointer point to freed data.
> -             */
> -            spice_timer_cancel(timer);
> -            timer->func(timer->opaque);
> -            /* timer could now be invalid ! */
> -        }
> -    }
> -}
> diff --git a/server/spice_timer_queue.h b/server/spice_timer_queue.h
> deleted file mode 100644
> index b17cecf..0000000
> --- a/server/spice_timer_queue.h
> +++ /dev/null
> @@ -1,44 +0,0 @@
> -/*
> -   Copyright (C) 2013 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_SPICE_TIMER_QUEUE
> -#define _H_SPICE_TIMER_QUEUE
> -
> -#include  <stdint.h>
> -#include "spice.h"
> -
> -typedef struct SpiceTimerQueue SpiceTimerQueue;
> -
> -/* create/destroy a timer queue for the current thread.
> - * In order to execute the timers functions, spice_timer_queue_cb should be
> called
> - * periodically, according to spice_timer_queue_get_timeout_ms */
> -int spice_timer_queue_create(void);
> -void spice_timer_queue_destroy(void);
> -
> -SpiceTimer *spice_timer_queue_add(const SpiceCoreInterfaceInternal *iface,
> -                                  SpiceTimerFunc func, void *opaque);
> -void spice_timer_set(SpiceTimer *timer, uint32_t ms);
> -void spice_timer_cancel(SpiceTimer *timer);
> -void spice_timer_remove(SpiceTimer *timer);
> -
> -/* returns the time left till the earliest timer in the queue expires.
> - * returns (unsigned)-1 if there are no active timers */
> -unsigned int spice_timer_queue_get_timeout_ms(void);
> -/* call the timeout callbacks of all the expired timers */
> -void spice_timer_queue_cb(void);
> -
> -#endif
> --
> 2.4.3
> 
> 


More information about the Spice-devel mailing list