[Spice-devel] [PATCH 02/15] Convert Dispatcher and MainDispatcher to GObjects

Frediano Ziglio fziglio at redhat.com
Wed Mar 9 16:44:41 UTC 2016


> 
> From: Jonathon Jongsma <jjongsma at redhat.com>
> 
> Allows more explicit inheritance relationship, and numerous other
> advantages.
> ---
>  server/dispatcher.c      | 233
>  ++++++++++++++++++++++++++++++++++++-----------
>  server/dispatcher.h      |  53 ++++++-----
>  server/main-dispatcher.c | 157 +++++++++++++++++++++++++------
>  server/main-dispatcher.h |  25 +++++
>  server/red-qxl.c         |  80 ++++++++--------
>  server/red-qxl.h         |   3 +-
>  6 files changed, 407 insertions(+), 144 deletions(-)
> 
> diff --git a/server/dispatcher.c b/server/dispatcher.c
> index d6c03ca..cd2f2cb 100644
> --- a/server/dispatcher.c
> +++ b/server/dispatcher.c
> @@ -1,6 +1,5 @@
> -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
>  /*
> -   Copyright (C) 2009-2012 Red Hat, Inc.
> +   Copyright (C) 2009-2015 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
> @@ -39,6 +38,155 @@
>  #include <signal.h>
>  #endif
>  
> +G_DEFINE_TYPE(Dispatcher, dispatcher, G_TYPE_OBJECT)
> +
> +#define DISPATCHER_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o),
> TYPE_DISPATCHER, DispatcherPrivate))
> +
> +struct DispatcherPrivate {
> +    int recv_fd;
> +    int send_fd;
> +    pthread_t self;
> +    pthread_mutex_t lock;
> +    DispatcherMessage *messages;
> +    int stage;  /* message parser stage - sender has no stages */
> +    size_t max_message_type;
> +    void *payload; /* allocated as max of message sizes */
> +    size_t payload_size; /* used to track realloc calls */
> +    void *opaque;
> +    dispatcher_handle_async_done handle_async_done;
> +    dispatcher_handle_any_message any_handler;
> +};
> +
> +enum {
> +    PROP_0,
> +    PROP_MAX_MESSAGE_TYPE,
> +    PROP_OPAQUE
> +};
> +
> +static void
> +dispatcher_get_property(GObject    *object,
> +                        guint       property_id,
> +                        GValue     *value,
> +                        GParamSpec *pspec)
> +{
> +    Dispatcher *self = DISPATCHER(object);
> +
> +    switch (property_id)
> +    {
> +        case PROP_MAX_MESSAGE_TYPE:
> +            g_value_set_uint(value, self->priv->max_message_type);
> +            break;
> +        case PROP_OPAQUE:
> +            g_value_set_pointer(value, self->priv->opaque);
> +            break;
> +        default:
> +            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
> +    }
> +}
> +
> +static void
> +dispatcher_set_property(GObject      *object,
> +                        guint         property_id,
> +                        const GValue *value,
> +                        GParamSpec   *pspec)
> +{
> +    Dispatcher *self = DISPATCHER(object);
> +
> +    switch (property_id)
> +    {
> +        case PROP_MAX_MESSAGE_TYPE:
> +            self->priv->max_message_type = g_value_get_uint(value);
> +            break;
> +        case PROP_OPAQUE:
> +            dispatcher_set_opaque(self, g_value_get_pointer(value));
> +            break;
> +        default:
> +            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
> +    }
> +}
> +
> +static void
> +dispatcher_finalize(GObject *object)
> +{
> +    Dispatcher *self = DISPATCHER(object);
> +    g_free(self->priv->messages);
> +    close(self->priv->send_fd);
> +    close(self->priv->recv_fd);
> +    free(self->priv->payload);

The pthread mutex should be destroyed too, I forgot to update the patch.

> +    G_OBJECT_CLASS(dispatcher_parent_class)->finalize(object);
> +}
> +
> +static void dispatcher_constructed(GObject *object)
> +{
> +    Dispatcher *self = DISPATCHER(object);
> +    int channels[2];
> +
> +    G_OBJECT_CLASS(dispatcher_parent_class)->constructed(object);
> +
> +#ifdef DEBUG_DISPATCHER
> +    setup_dummy_signal_handler();
> +#endif
> +    if (socketpair(AF_LOCAL, SOCK_STREAM, 0, channels) == -1) {
> +        spice_error("socketpair failed %s", strerror(errno));
> +        return;
> +    }
> +    pthread_mutex_init(&self->priv->lock, NULL);
> +    self->priv->recv_fd = channels[0];
> +    self->priv->send_fd = channels[1];
> +    self->priv->self = pthread_self();
> +
> +    self->priv->messages = g_new0(DispatcherMessage,
> +                                  self->priv->max_message_type);
> +}
> +
> +static void
> +dispatcher_class_init(DispatcherClass *klass)
> +{
> +    GObjectClass *object_class = G_OBJECT_CLASS(klass);
> +
> +    g_type_class_add_private(klass, sizeof (DispatcherPrivate));
> +
> +    object_class->get_property = dispatcher_get_property;
> +    object_class->set_property = dispatcher_set_property;
> +    object_class->constructed = dispatcher_constructed;
> +    object_class->finalize = dispatcher_finalize;
> +
> +    g_object_class_install_property(object_class,
> +                                    PROP_MAX_MESSAGE_TYPE,
> +                                    g_param_spec_uint("max-message-type",
> +                                                      "Maximum message
> type",

This should be "max-message-type".

> +                                                      "Maximum message
> type",
> +                                                      0, G_MAXUINT, 0,
> +                                                      G_PARAM_STATIC_STRINGS
> |
> +                                                      G_PARAM_READWRITE |
> +
> G_PARAM_CONSTRUCT_ONLY));
> +    g_object_class_install_property(object_class,
> +                                    PROP_OPAQUE,
> +                                    g_param_spec_pointer("opaque",
> +                                                      "opaque",
> +                                                      "User data to pass to
> callbacks",
> +                                                      G_PARAM_STATIC_STRINGS
> |
> +                                                      G_PARAM_READWRITE |
> +                                                      G_PARAM_CONSTRUCT));
> +
> +}
> +
> +static void
> +dispatcher_init(Dispatcher *self)
> +{
> +    self->priv = DISPATCHER_PRIVATE(self);
> +}
> +
> +Dispatcher *
> +dispatcher_new(size_t max_message_type, void *opaque)
> +{
> +    return g_object_new(TYPE_DISPATCHER,
> +                        "max-message-type", max_message_type,

better to cast the max_message_type to guint.

> +                        "opaque", opaque,
> +                        NULL);
> +}
> +
> +
>  #define ACK 0xffffffff
>  
>  /*
> @@ -118,10 +266,10 @@ static int dispatcher_handle_single_read(Dispatcher
> *dispatcher)
>      int ret;
>      uint32_t type;
>      DispatcherMessage *msg = NULL;
> -    uint8_t *payload = dispatcher->payload;
> +    uint8_t *payload = dispatcher->priv->payload;
>      uint32_t ack = ACK;
>  
> -    if ((ret = read_safe(dispatcher->recv_fd, (uint8_t*)&type, sizeof(type),
> 0)) == -1) {
> +    if ((ret = read_safe(dispatcher->priv->recv_fd, (uint8_t*)&type,
> sizeof(type), 0)) == -1) {
>          spice_printerr("error reading from dispatcher: %d", errno);
>          return 0;
>      }
> @@ -129,28 +277,28 @@ static int dispatcher_handle_single_read(Dispatcher
> *dispatcher)
>          /* no messsage */
>          return 0;
>      }
> -    msg = &dispatcher->messages[type];
> -    if (read_safe(dispatcher->recv_fd, payload, msg->size, 1) == -1) {
> +    msg = &dispatcher->priv->messages[type];
> +    if (read_safe(dispatcher->priv->recv_fd, payload, msg->size, 1) == -1) {
>          spice_printerr("error reading from dispatcher: %d", errno);
>          /* TODO: close socketpair? */
>          return 0;
>      }
> -    if (dispatcher->any_handler) {
> -        dispatcher->any_handler(dispatcher->opaque, type, payload);
> +    if (dispatcher->priv->any_handler) {
> +        dispatcher->priv->any_handler(dispatcher->priv->opaque, type,
> payload);
>      }
>      if (msg->handler) {
> -        msg->handler(dispatcher->opaque, (void *)payload);
> +        msg->handler(dispatcher->priv->opaque, payload);
>      } else {
>          spice_printerr("error: no handler for message type %d", type);
>      }
>      if (msg->ack == DISPATCHER_ACK) {
> -        if (write_safe(dispatcher->recv_fd,
> +        if (write_safe(dispatcher->priv->recv_fd,
>                         (uint8_t*)&ack, sizeof(ack)) == -1) {
>              spice_printerr("error writing ack for message %d", type);
>              /* TODO: close socketpair? */
>          }
> -    } else if (msg->ack == DISPATCHER_ASYNC && dispatcher->handle_async_done) {
> -        dispatcher->handle_async_done(dispatcher->opaque, type,
> +    } else if (msg->ack == DISPATCHER_ASYNC && dispatcher->priv->handle_async_done) {
> +        dispatcher->priv->handle_async_done(dispatcher->priv->opaque, type,
>                                        (void *)payload);
>      }
>      return 1;
> @@ -171,12 +319,12 @@ void dispatcher_send_message(Dispatcher *dispatcher,
> uint32_t message_type,
>  {
>      DispatcherMessage *msg;
>      uint32_t ack;
> -    int send_fd = dispatcher->send_fd;
> +    int send_fd = dispatcher->priv->send_fd;
>  
> -    assert(dispatcher->max_message_type > message_type);
> -    assert(dispatcher->messages[message_type].handler);
> -    msg = &dispatcher->messages[message_type];
> -    pthread_mutex_lock(&dispatcher->lock);
> +    assert(dispatcher->priv->max_message_type > message_type);
> +    assert(dispatcher->priv->messages[message_type].handler);
> +    msg = &dispatcher->priv->messages[message_type];
> +    pthread_mutex_lock(&dispatcher->priv->lock);
>      if (write_safe(send_fd, (uint8_t*)&message_type, sizeof(message_type))
>      == -1) {
>          spice_printerr("error: failed to send message type for message %d",
>                     message_type);
> @@ -197,15 +345,15 @@ void dispatcher_send_message(Dispatcher *dispatcher,
> uint32_t message_type,
>          }
>      }
>  unlock:
> -    pthread_mutex_unlock(&dispatcher->lock);
> +    pthread_mutex_unlock(&dispatcher->priv->lock);
>  }
>  
>  void dispatcher_register_async_done_callback(
>                                          Dispatcher *dispatcher,
>                                          dispatcher_handle_async_done
>                                          handler)
>  {
> -    assert(dispatcher->handle_async_done == NULL);
> -    dispatcher->handle_async_done = handler;
> +    assert(dispatcher->priv->handle_async_done == NULL);
> +    dispatcher->priv->handle_async_done = handler;
>  }
>  
>  void dispatcher_register_handler(Dispatcher *dispatcher, uint32_t
>  message_type,
> @@ -214,15 +362,15 @@ void dispatcher_register_handler(Dispatcher
> *dispatcher, uint32_t message_type,
>  {
>      DispatcherMessage *msg;
>  
> -    assert(message_type < dispatcher->max_message_type);
> -    assert(dispatcher->messages[message_type].handler == 0);
> -    msg = &dispatcher->messages[message_type];
> +    assert(message_type < dispatcher->priv->max_message_type);
> +    assert(dispatcher->priv->messages[message_type].handler == 0);
> +    msg = &dispatcher->priv->messages[message_type];
>      msg->handler = handler;
>      msg->size = size;
>      msg->ack = ack;
> -    if (msg->size > dispatcher->payload_size) {
> -        dispatcher->payload = realloc(dispatcher->payload, msg->size);
> -        dispatcher->payload_size = msg->size;
> +    if (msg->size > dispatcher->priv->payload_size) {
> +        dispatcher->priv->payload = realloc(dispatcher->priv->payload, msg->size);
> +        dispatcher->priv->payload_size = msg->size;
>      }
>  }
>  
> @@ -230,7 +378,7 @@ void dispatcher_register_universal_handler(
>                                 Dispatcher *dispatcher,
>                                 dispatcher_handle_any_message any_handler)
>  {
> -    dispatcher->any_handler = any_handler;
> +    dispatcher->priv->any_handler = any_handler;
>  }
>  
>  #ifdef DEBUG_DISPATCHER
> @@ -257,35 +405,18 @@ static void setup_dummy_signal_handler(void)
>  }
>  #endif
>  
> -void dispatcher_init(Dispatcher *dispatcher, size_t max_message_type,
> -                     void *opaque)
> +void dispatcher_set_opaque(Dispatcher *self, void *opaque)
>  {
> -    int channels[2];
> -
> -#ifdef DEBUG_DISPATCHER
> -    setup_dummy_signal_handler();
> -#endif
> -    dispatcher->opaque = opaque;
> -    if (socketpair(AF_LOCAL, SOCK_STREAM, 0, channels) == -1) {
> -        spice_error("socketpair failed %s", strerror(errno));
> -        return;
> -    }
> -    pthread_mutex_init(&dispatcher->lock, NULL);
> -    dispatcher->recv_fd = channels[0];
> -    dispatcher->send_fd = channels[1];
> -    dispatcher->self = pthread_self();
> -
> -    dispatcher->messages = spice_malloc0_n(max_message_type,
> -                                           sizeof(dispatcher->messages[0]));
> -    dispatcher->max_message_type = max_message_type;
> +    self->priv->opaque = opaque;
> +    g_object_notify(G_OBJECT(self), "opaque");
>  }
>  
> -void dispatcher_set_opaque(Dispatcher *dispatcher, void *opaque)
> +int dispatcher_get_recv_fd(Dispatcher *dispatcher)
>  {
> -    dispatcher->opaque = opaque;
> +    return dispatcher->priv->recv_fd;
>  }
>  
> -int dispatcher_get_recv_fd(Dispatcher *dispatcher)
> +pthread_t dispatcher_get_thread_id(Dispatcher *self)
>  {
> -    return dispatcher->recv_fd;
> +    return self->priv->self;
>  }
> diff --git a/server/dispatcher.h b/server/dispatcher.h
> index 78ef663..caaebc5 100644
> --- a/server/dispatcher.h
> +++ b/server/dispatcher.h
> @@ -18,9 +18,37 @@
>  #ifndef DISPATCHER_H
>  #define DISPATCHER_H
>  
> +#include <glib-object.h>
>  #include "red-common.h"
>  
> +#define TYPE_DISPATCHER dispatcher_get_type()
> +
> +#define DISPATCHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_DISPATCHER, Dispatcher))
> +#define DISPATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_DISPATCHER, DispatcherClass))
> +#define IS_DISPATCHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_DISPATCHER))
> +#define IS_DISPATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_DISPATCHER))
> +#define DISPATCHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_DISPATCHER, DispatcherClass))
> +
>  typedef struct Dispatcher Dispatcher;
> +typedef struct DispatcherClass DispatcherClass;
> +typedef struct DispatcherPrivate DispatcherPrivate;
> +
> +struct Dispatcher
> +{
> +    GObject parent;
> +
> +    DispatcherPrivate *priv;
> +};
> +
> +struct DispatcherClass
> +{
> +    GObjectClass parent_class;
> +};
> +
> +GType dispatcher_get_type(void) G_GNUC_CONST;
> +
> +Dispatcher *dispatcher_new(size_t max_message_type, void *opaque);
> +
>  
>  typedef void (*dispatcher_handle_message)(void *opaque,
>                                            void *payload);
> @@ -40,20 +68,6 @@ typedef struct DispatcherMessage {
>      dispatcher_handle_message handler;
>  } DispatcherMessage;
>  
> -struct Dispatcher {
> -    int recv_fd;
> -    int send_fd;
> -    pthread_t self;
> -    pthread_mutex_t lock;
> -    DispatcherMessage *messages;
> -    int stage;  /* message parser stage - sender has no stages */
> -    size_t max_message_type;
> -    void *payload; /* allocated as max of message sizes */
> -    size_t payload_size; /* used to track realloc calls */
> -    void *opaque;
> -    dispatcher_handle_async_done handle_async_done;
> -    dispatcher_handle_any_message any_handler;
> -};
>  
>  /*
>   * dispatcher_send_message
> @@ -63,15 +77,6 @@ struct Dispatcher {
>  void dispatcher_send_message(Dispatcher *dispatcher, uint32_t message_type,
>                               void *payload);
>  
> -/*
> - * dispatcher_init
> - * @max_message_type: number of message types. Allows upfront allocation
> - *  of a DispatcherMessage list.
> - * up front, and registration in any order wanted.
> - */
> -void dispatcher_init(Dispatcher *dispatcher, size_t max_message_type,
> -                     void *opaque);
> -
>  enum {
>      DISPATCHER_NONE = 0,
>      DISPATCHER_ACK,
> @@ -131,4 +136,6 @@ int dispatcher_get_recv_fd(Dispatcher *);
>   */
>  void dispatcher_set_opaque(Dispatcher *dispatcher, void *opaque);
>  
> +pthread_t dispatcher_get_thread_id(Dispatcher *self);
> +
>  #endif //DISPATCHER_H
> diff --git a/server/main-dispatcher.c b/server/main-dispatcher.c
> index 298a961..bc0de24 100644
> --- a/server/main-dispatcher.c
> +++ b/server/main-dispatcher.c
> @@ -47,12 +47,99 @@
>   *   seperate from self because it may send an ack or do other work in the
>   future.
>   */
>  
> -struct MainDispatcher {
> -    Dispatcher base;
> -    SpiceCoreInterfaceInternal *core;
> -    RedsState *reds;
> +G_DEFINE_TYPE(MainDispatcher, main_dispatcher, TYPE_DISPATCHER)
> +
> +#define MAIN_DISPATCHER_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o),
> TYPE_MAIN_DISPATCHER, MainDispatcherPrivate))
> +
> +struct MainDispatcherPrivate
> +{
> +    SpiceCoreInterfaceInternal *core; /* weak */
> +    RedsState *reds; /* weak */
>  };
>  
> +
> +enum {
> +    PROP0,
> +    PROP_SPICE_SERVER,
> +    PROP_CORE_INTERFACE
> +};
> +
> +static void
> +main_dispatcher_get_property(GObject    *object,
> +                                  guint       property_id,
> +                                  GValue     *value,
> +                                  GParamSpec *pspec)
> +{
> +    MainDispatcher *self = MAIN_DISPATCHER(object);
> +
> +    switch (property_id) {
> +        case PROP_SPICE_SERVER:
> +             g_value_set_pointer(value, self->priv->reds);
> +            break;
> +        case PROP_CORE_INTERFACE:
> +             g_value_set_pointer(value, self->priv->core);
> +            break;
> +        default:
> +            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
> +    }
> +}
> +
> +static void
> +main_dispatcher_set_property(GObject      *object,
> +                                  guint         property_id,
> +                                  const GValue *value,
> +                                  GParamSpec   *pspec)
> +{
> +    MainDispatcher *self = MAIN_DISPATCHER(object);
> +
> +    switch (property_id) {
> +        case PROP_SPICE_SERVER:
> +            self->priv->reds = g_value_get_pointer(value);
> +            break;
> +        case PROP_CORE_INTERFACE:
> +            self->priv->core = g_value_get_pointer(value);
> +            break;
> +        default:
> +            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
> +    }
> +}
> +
> +static void main_dispatcher_constructed(GObject *object);
> +
> +static void
> +main_dispatcher_class_init(MainDispatcherClass *klass)
> +{
> +    GObjectClass *object_class = G_OBJECT_CLASS(klass);
> +
> +    g_type_class_add_private(klass, sizeof(MainDispatcherPrivate));
> +
> +    object_class->constructed = main_dispatcher_constructed;
> +    object_class->get_property = main_dispatcher_get_property;
> +    object_class->set_property = main_dispatcher_set_property;
> +
> +    g_object_class_install_property(object_class,
> +                                    PROP_SPICE_SERVER,
> +                                    g_param_spec_pointer("spice-server",
> +                                                         "spice-server",
> +                                                         "The spice server
> associated with this dispatcher",
> +                                                         G_PARAM_READWRITE |
> +
> G_PARAM_CONSTRUCT_ONLY));
> +
> +    g_object_class_install_property(object_class,
> +                                    PROP_CORE_INTERFACE,
> +                                    g_param_spec_pointer("core-interface",
> +                                                         "core-interface",
> +                                                         "The
> SpiceCoreInterface server associated with this dispatcher",
> +                                                         G_PARAM_READWRITE |
> +
> G_PARAM_CONSTRUCT_ONLY));
> +}
> +
> +static void
> +main_dispatcher_init(MainDispatcher *self)
> +{
> +    self->priv = MAIN_DISPATCHER_PRIVATE(self);
> +}
> +
>  enum {
>      MAIN_DISPATCHER_CHANNEL_EVENT = 0,
>      MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE,
> @@ -85,7 +172,7 @@ static void
> main_dispatcher_self_handle_channel_event(MainDispatcher *self,
>                                                        int event,
>                                                        SpiceChannelEventInfo
>                                                        *info)
>  {
> -    reds_handle_channel_event(self->reds, event, info);
> +    reds_handle_channel_event(self->priv->reds, event, info);
>  }
>  
>  static void main_dispatcher_handle_channel_event(void *opaque,
> @@ -103,13 +190,13 @@ void main_dispatcher_channel_event(MainDispatcher
> *self, int event, SpiceChannel
>  {
>      MainDispatcherChannelEventMessage msg = {0,};
>  
> -    if (pthread_self() == self->base.self) {
> +    if (pthread_self() == dispatcher_get_thread_id(DISPATCHER(self))) {
>          main_dispatcher_self_handle_channel_event(self, event, info);
>          return;
>      }
>      msg.event = event;
>      msg.info = info;
> -    dispatcher_send_message(&self->base, MAIN_DISPATCHER_CHANNEL_EVENT,
> +    dispatcher_send_message(DISPATCHER(self), MAIN_DISPATCHER_CHANNEL_EVENT,
>                              &msg);
>  }
>  
> @@ -120,7 +207,7 @@ static void main_dispatcher_handle_migrate_complete(void
> *opaque,
>      MainDispatcher *self = opaque;
>      MainDispatcherMigrateSeamlessDstCompleteMessage *mig_complete = payload;
>  
> -    reds_on_client_seamless_migrate_complete(self->reds,
> mig_complete->client);
> +    reds_on_client_seamless_migrate_complete(self->priv->reds,
> mig_complete->client);
>      red_client_unref(mig_complete->client);
>  }
>  
> @@ -129,7 +216,7 @@ static void main_dispatcher_handle_mm_time_latency(void
> *opaque,
>  {
>      MainDispatcher *self = opaque;
>      MainDispatcherMmTimeLatencyMessage *msg = payload;
> -    reds_set_client_mm_time_latency(self->reds, msg->client, msg->latency);
> +    reds_set_client_mm_time_latency(self->priv->reds, msg->client,
> msg->latency);
>      red_client_unref(msg->client);
>  }
>  
> @@ -140,7 +227,7 @@ static void main_dispatcher_handle_client_disconnect(void
> *opaque,
>      MainDispatcherClientDisconnectMessage *msg = payload;
>  
>      spice_debug("client=%p", msg->client);
> -    reds_client_disconnect(self->reds, msg->client);
> +    reds_client_disconnect(self->priv->reds, msg->client);
>      red_client_unref(msg->client);
>  }
>  
> @@ -149,13 +236,13 @@ void
> main_dispatcher_seamless_migrate_dst_complete(MainDispatcher *self,
>  {
>      MainDispatcherMigrateSeamlessDstCompleteMessage msg;
>  
> -    if (pthread_self() == self->base.self) {
> -        reds_on_client_seamless_migrate_complete(self->reds, client);
> +    if (pthread_self() == dispatcher_get_thread_id(DISPATCHER(self))) {
> +        reds_on_client_seamless_migrate_complete(self->priv->reds, client);
>          return;
>      }
>  
>      msg.client = red_client_ref(client);
> -    dispatcher_send_message(&self->base,
> MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE,
> +    dispatcher_send_message(DISPATCHER(self),
> MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE,
>                              &msg);
>  }
>  
> @@ -163,14 +250,14 @@ void main_dispatcher_set_mm_time_latency(MainDispatcher
> *self, RedClient *client
>  {
>      MainDispatcherMmTimeLatencyMessage msg;
>  
> -    if (pthread_self() == self->base.self) {
> -        reds_set_client_mm_time_latency(self->reds, client, latency);
> +    if (pthread_self() == dispatcher_get_thread_id(DISPATCHER(self))) {
> +        reds_set_client_mm_time_latency(self->priv->reds, client, latency);
>          return;
>      }
>  
>      msg.client = red_client_ref(client);
>      msg.latency = latency;
> -    dispatcher_send_message(&self->base,
> MAIN_DISPATCHER_SET_MM_TIME_LATENCY,
> +    dispatcher_send_message(DISPATCHER(self),
> MAIN_DISPATCHER_SET_MM_TIME_LATENCY,
>                              &msg);
>  }
>  
> @@ -181,7 +268,7 @@ void main_dispatcher_client_disconnect(MainDispatcher
> *self, RedClient *client)
>      if (!client->disconnecting) {
>          spice_debug("client %p", client);
>          msg.client = red_client_ref(client);
> -        dispatcher_send_message(&self->base,
> MAIN_DISPATCHER_CLIENT_DISCONNECT,
> +        dispatcher_send_message(DISPATCHER(self),
> MAIN_DISPATCHER_CLIENT_DISCONNECT,
>                                  &msg);
>      } else {
>          spice_debug("client %p already during disconnection", client);
> @@ -192,7 +279,7 @@ static void dispatcher_handle_read(int fd, int event,
> void *opaque)
>  {
>      MainDispatcher *self = opaque;
>  
> -    dispatcher_handle_recv_read(&self->base);
> +    dispatcher_handle_recv_read(DISPATCHER(self));
>  }
>  
>  /*
> @@ -202,23 +289,35 @@ static void dispatcher_handle_read(int fd, int event,
> void *opaque)
>   */
>  MainDispatcher* main_dispatcher_new(RedsState *reds,
>  SpiceCoreInterfaceInternal *core)
>  {
> -    MainDispatcher *main_dispatcher = g_new0(MainDispatcher, 1);
> -    main_dispatcher->core = core;
> -    main_dispatcher->reds = reds;
> -    dispatcher_init(&main_dispatcher->base, MAIN_DISPATCHER_NUM_MESSAGES,
> main_dispatcher);
> -    core->watch_add(core, main_dispatcher->base.recv_fd,
> SPICE_WATCH_EVENT_READ,
> -                    dispatcher_handle_read, main_dispatcher);
> -    dispatcher_register_handler(&main_dispatcher->base,
> MAIN_DISPATCHER_CHANNEL_EVENT,
> +    MainDispatcher *self = g_object_new(TYPE_MAIN_DISPATCHER,
> +                                        "spice-server", reds,
> +                                        "core-interface", core,
> +                                        "max-message-type",
> MAIN_DISPATCHER_NUM_MESSAGES,
> +                                        NULL);
> +    return self;
> +}
> +
> +void main_dispatcher_constructed(GObject *object)
> +{
> +    MainDispatcher *self = MAIN_DISPATCHER(object);
> +
> +    G_OBJECT_CLASS(main_dispatcher_parent_class)->constructed(object);
> +    dispatcher_set_opaque(DISPATCHER(self), self);
> +
> +    self->priv->core->watch_add(self->priv->core,
> +                                dispatcher_get_recv_fd(DISPATCHER(self)),
> +                                SPICE_WATCH_EVENT_READ,
> dispatcher_handle_read,
> +                                self);
> +    dispatcher_register_handler(DISPATCHER(self),
> MAIN_DISPATCHER_CHANNEL_EVENT,
>                                  main_dispatcher_handle_channel_event,
>                                  sizeof(MainDispatcherChannelEventMessage), 0
>                                  /* no ack */);
> -    dispatcher_register_handler(&main_dispatcher->base,
> MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE,
> +    dispatcher_register_handler(DISPATCHER(self),
> MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE,
>                                  main_dispatcher_handle_migrate_complete,
>                                  sizeof(MainDispatcherMigrateSeamlessDstCompleteMessage),
>                                  0 /* no ack */);
> -    dispatcher_register_handler(&main_dispatcher->base,
> MAIN_DISPATCHER_SET_MM_TIME_LATENCY,
> +    dispatcher_register_handler(DISPATCHER(self),
> MAIN_DISPATCHER_SET_MM_TIME_LATENCY,
>                                  main_dispatcher_handle_mm_time_latency,
>                                  sizeof(MainDispatcherMmTimeLatencyMessage),
>                                  0 /* no ack */);
> -    dispatcher_register_handler(&main_dispatcher->base,
> MAIN_DISPATCHER_CLIENT_DISCONNECT,
> +    dispatcher_register_handler(DISPATCHER(self),
> MAIN_DISPATCHER_CLIENT_DISCONNECT,
>                                  main_dispatcher_handle_client_disconnect,
>                                  sizeof(MainDispatcherClientDisconnectMessage),
>                                  0 /* no ack */);
> -    return main_dispatcher;
>  }
> diff --git a/server/main-dispatcher.h b/server/main-dispatcher.h
> index cbc3657..ffe82c8 100644
> --- a/server/main-dispatcher.h
> +++ b/server/main-dispatcher.h
> @@ -19,9 +19,34 @@
>  #define MAIN_DISPATCHER_H
>  
>  #include <spice.h>
> +#include "dispatcher.h"
>  #include "red-channel.h"
>  
> +#define TYPE_MAIN_DISPATCHER main_dispatcher_get_type()
> +
> +#define MAIN_DISPATCHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),
> TYPE_MAIN_DISPATCHER, MainDispatcher))
> +#define MAIN_DISPATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),
> TYPE_MAIN_DISPATCHER, MainDispatcherClass))
> +#define IS_MAIN_DISPATCHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),
> TYPE_MAIN_DISPATCHER))
> +#define IS_MAIN_DISPATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),
> TYPE_MAIN_DISPATCHER))
> +#define MAIN_DISPATCHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),
> TYPE_MAIN_DISPATCHER, MainDispatcherClass))
> +
>  typedef struct MainDispatcher MainDispatcher;
> +typedef struct MainDispatcherClass MainDispatcherClass;
> +typedef struct MainDispatcherPrivate MainDispatcherPrivate;
> +
> +struct MainDispatcher
> +{
> +    Dispatcher parent;
> +
> +    MainDispatcherPrivate *priv;
> +};
> +
> +struct MainDispatcherClass
> +{
> +    DispatcherClass parent_class;
> +};
> +
> +GType main_dispatcher_get_type(void) G_GNUC_CONST;
>  
>  void main_dispatcher_channel_event(MainDispatcher *self, int event,
>  SpiceChannelEventInfo *info);
>  void main_dispatcher_seamless_migrate_dst_complete(MainDispatcher *self,
>  RedClient *client);
> diff --git a/server/red-qxl.c b/server/red-qxl.c
> index 491046f..d209de6 100644
> --- a/server/red-qxl.c
> +++ b/server/red-qxl.c
> @@ -48,7 +48,7 @@ struct AsyncCommand {
>  struct QXLState {
>      QXLWorker base;
>      QXLInstance *qxl;
> -    Dispatcher dispatcher;
> +    Dispatcher *dispatcher;
>      uint32_t pending;
>      int primary_active;
>      int x_res;
> @@ -93,7 +93,7 @@ static void red_qxl_set_display_peer(RedChannel *channel,
> RedClient *client,
>      memcpy(payload.common_caps, common_caps,
>      sizeof(uint32_t)*num_common_caps);
>      memcpy(payload.caps, caps, sizeof(uint32_t)*num_caps);
>  
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_DISPLAY_CONNECT,
>                              &payload);
>  }
> @@ -114,7 +114,7 @@ static void
> red_qxl_disconnect_display_peer(RedChannelClient *rcc)
>  
>      // TODO: we turned it to be sync, due to client_destroy . Should we
>      support async? - for this we will need ref count
>      // for channels
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_DISPLAY_DISCONNECT,
>                              &payload);
>  }
> @@ -129,7 +129,7 @@ static void red_qxl_display_migrate(RedChannelClient
> *rcc)
>      qxl_state = (QXLState *)rcc->channel->data;
>      spice_printerr("channel type %u id %u", rcc->channel->type,
>      rcc->channel->id);
>      payload.rcc = rcc;
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_DISPLAY_MIGRATE,
>                              &payload);
>  }
> @@ -153,7 +153,7 @@ static void red_qxl_set_cursor_peer(RedChannel *channel,
> RedClient *client, Reds
>      memcpy(payload.common_caps, common_caps,
>      sizeof(uint32_t)*num_common_caps);
>      memcpy(payload.caps, caps, sizeof(uint32_t)*num_caps);
>  
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_CURSOR_CONNECT,
>                              &payload);
>  }
> @@ -171,7 +171,7 @@ static void
> red_qxl_disconnect_cursor_peer(RedChannelClient *rcc)
>      spice_printerr("");
>      payload.rcc = rcc;
>  
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_CURSOR_DISCONNECT,
>                              &payload);
>  }
> @@ -187,7 +187,7 @@ static void red_qxl_cursor_migrate(RedChannelClient *rcc)
>      qxl_state = (QXLState *)rcc->channel->data;
>      spice_printerr("channel type %u id %u", rcc->channel->type,
>      rcc->channel->id);
>      payload.rcc = rcc;
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_CURSOR_MIGRATE,
>                              &payload);
>  }
> @@ -203,7 +203,7 @@ static void red_qxl_update_area(QXLState *qxl_state,
> uint32_t surface_id,
>      payload.qxl_dirty_rects = qxl_dirty_rects;
>      payload.num_dirty_rects = num_dirty_rects;
>      payload.clear_dirty_region = clear_dirty_region;
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_UPDATE,
>                              &payload);
>  }
> @@ -249,7 +249,7 @@ static void red_qxl_update_area_async(QXLState
> *qxl_state,
>      payload.surface_id = surface_id;
>      payload.qxl_area = *qxl_area;
>      payload.clear_dirty_region = clear_dirty_region;
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              message,
>                              &payload);
>  }
> @@ -267,7 +267,7 @@ static void red_qxl_add_memslot(QXLState *qxl_state,
> QXLDevMemSlot *mem_slot)
>      RedWorkerMessageAddMemslot payload;
>  
>      payload.mem_slot = *mem_slot;
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_ADD_MEMSLOT,
>                              &payload);
>  }
> @@ -284,7 +284,7 @@ static void red_qxl_add_memslot_async(QXLState
> *qxl_state, QXLDevMemSlot *mem_sl
>  
>      payload.base.cmd = async_command_alloc(qxl_state, message, cookie);
>      payload.mem_slot = *mem_slot;
> -    dispatcher_send_message(&qxl_state->dispatcher, message, &payload);
> +    dispatcher_send_message(qxl_state->dispatcher, message, &payload);
>  }
>  
>  static void red_qxl_del_memslot(QXLState *qxl_state, uint32_t slot_group_id,
>  uint32_t slot_id)
> @@ -294,7 +294,7 @@ static void red_qxl_del_memslot(QXLState *qxl_state,
> uint32_t slot_group_id, uin
>  
>      payload.slot_group_id = slot_group_id;
>      payload.slot_id = slot_id;
> -    dispatcher_send_message(&qxl_state->dispatcher, message, &payload);
> +    dispatcher_send_message(qxl_state->dispatcher, message, &payload);
>  }
>  
>  static void qxl_worker_del_memslot(QXLWorker *qxl_worker, uint32_t
>  slot_group_id, uint32_t slot_id)
> @@ -306,7 +306,7 @@ static void red_qxl_destroy_surfaces(QXLState *qxl_state)
>  {
>      RedWorkerMessageDestroySurfaces payload;
>  
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_DESTROY_SURFACES,
>                              &payload);
>  }
> @@ -322,7 +322,7 @@ static void red_qxl_destroy_surfaces_async(QXLState
> *qxl_state, uint64_t cookie)
>      RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC;
>  
>      payload.base.cmd = async_command_alloc(qxl_state, message, cookie);
> -    dispatcher_send_message(&qxl_state->dispatcher, message, &payload);
> +    dispatcher_send_message(qxl_state->dispatcher, message, &payload);
>  }
>  
>  static void red_qxl_destroy_primary_surface_complete(QXLState *qxl_state)
> @@ -341,7 +341,7 @@ red_qxl_destroy_primary_surface_sync(QXLState *qxl_state,
>  {
>      RedWorkerMessageDestroyPrimarySurface payload;
>      payload.surface_id = surface_id;
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE,
>                              &payload);
>      red_qxl_destroy_primary_surface_complete(qxl_state);
> @@ -356,7 +356,7 @@ red_qxl_destroy_primary_surface_async(QXLState
> *qxl_state,
>  
>      payload.base.cmd = async_command_alloc(qxl_state, message, cookie);
>      payload.surface_id = surface_id;
> -    dispatcher_send_message(&qxl_state->dispatcher, message, &payload);
> +    dispatcher_send_message(qxl_state->dispatcher, message, &payload);
>  }
>  
>  static void
> @@ -399,7 +399,7 @@ red_qxl_create_primary_surface_async(QXLState *qxl_state,
> uint32_t surface_id,
>      payload.base.cmd = async_command_alloc(qxl_state, message, cookie);
>      payload.surface_id = surface_id;
>      payload.surface = *surface;
> -    dispatcher_send_message(&qxl_state->dispatcher, message, &payload);
> +    dispatcher_send_message(qxl_state->dispatcher, message, &payload);
>  }
>  
>  static void
> @@ -411,7 +411,7 @@ red_qxl_create_primary_surface_sync(QXLState *qxl_state,
> uint32_t surface_id,
>      qxl_state->surface_create = *surface;
>      payload.surface_id = surface_id;
>      payload.surface = *surface;
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE,
>                              &payload);
>      red_qxl_create_primary_surface_complete(qxl_state);
> @@ -438,7 +438,7 @@ static void red_qxl_reset_image_cache(QXLState
> *qxl_state)
>  {
>      RedWorkerMessageResetImageCache payload;
>  
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_RESET_IMAGE_CACHE,
>                              &payload);
>  }
> @@ -452,7 +452,7 @@ static void red_qxl_reset_cursor(QXLState *qxl_state)
>  {
>      RedWorkerMessageResetCursor payload;
>  
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_RESET_CURSOR,
>                              &payload);
>  }
> @@ -468,7 +468,7 @@ static void red_qxl_destroy_surface_wait_sync(QXLState
> *qxl_state,
>      RedWorkerMessageDestroySurfaceWait payload;
>  
>      payload.surface_id = surface_id;
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT,
>                              &payload);
>  }
> @@ -482,7 +482,7 @@ static void red_qxl_destroy_surface_wait_async(QXLState
> *qxl_state,
>  
>      payload.base.cmd = async_command_alloc(qxl_state, message, cookie);
>      payload.surface_id = surface_id;
> -    dispatcher_send_message(&qxl_state->dispatcher, message, &payload);
> +    dispatcher_send_message(qxl_state->dispatcher, message, &payload);
>  }
>  
>  static void red_qxl_destroy_surface_wait(QXLState *qxl_state,
> @@ -505,7 +505,7 @@ static void red_qxl_reset_memslots(QXLState *qxl_state)
>  {
>      RedWorkerMessageResetMemslots payload;
>  
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_RESET_MEMSLOTS,
>                              &payload);
>  }
> @@ -533,7 +533,7 @@ static void red_qxl_wakeup(QXLState *qxl_state)
>      if (red_qxl_set_pending(qxl_state, RED_DISPATCHER_PENDING_WAKEUP))
>          return;
>  
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_WAKEUP,
>                              &payload);
>  }
> @@ -550,7 +550,7 @@ static void red_qxl_oom(QXLState *qxl_state)
>      if (red_qxl_set_pending(qxl_state, RED_DISPATCHER_PENDING_OOM))
>          return;
>  
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_OOM,
>                              &payload);
>  }
> @@ -564,7 +564,7 @@ void red_qxl_start(QXLState *qxl_state)
>  {
>      RedWorkerMessageStart payload;
>  
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_START,
>                              &payload);
>  }
> @@ -580,7 +580,7 @@ static void red_qxl_flush_surfaces_async(QXLState
> *qxl_state, uint64_t cookie)
>      RedWorkerMessage message = RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC;
>  
>      payload.base.cmd = async_command_alloc(qxl_state, message, cookie);
> -    dispatcher_send_message(&qxl_state->dispatcher, message, &payload);
> +    dispatcher_send_message(qxl_state->dispatcher, message, &payload);
>  }
>  
>  static void red_qxl_monitors_config_async(QXLState *qxl_state,
> @@ -596,14 +596,14 @@ static void red_qxl_monitors_config_async(QXLState
> *qxl_state,
>      payload.group_id = group_id;
>      payload.max_monitors = qxl_state->max_monitors;
>  
> -    dispatcher_send_message(&qxl_state->dispatcher, message, &payload);
> +    dispatcher_send_message(qxl_state->dispatcher, message, &payload);
>  }
>  
>  static void red_qxl_driver_unload(QXLState *qxl_state)
>  {
>      RedWorkerMessageDriverUnload payload;
>  
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_DRIVER_UNLOAD,
>                              &payload);
>  }
> @@ -612,7 +612,7 @@ void red_qxl_stop(QXLState *qxl_state)
>  {
>      RedWorkerMessageStop payload;
>  
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_STOP,
>                              &payload);
>  }
> @@ -631,7 +631,7 @@ static void red_qxl_loadvm_commands(QXLState *qxl_state,
>      spice_printerr("");
>      payload.count = count;
>      payload.ext = ext;
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_LOADVM_COMMANDS,
>                              &payload);
>  }
> @@ -871,7 +871,7 @@ void spice_qxl_gl_scanout(QXLInstance *qxl,
>      pthread_mutex_unlock(&qxl_state->scanout_mutex);
>  
>      /* FIXME: find a way to coallesce all pending SCANOUTs */
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_GL_SCANOUT, NULL);
>  }
>  
> @@ -896,7 +896,7 @@ void spice_qxl_gl_draw_async(QXLInstance *qxl,
>      spice_return_if_fail(qxl_state->gl_draw_async == NULL);
>  
>      qxl_state->gl_draw_async = async_command_alloc(qxl_state, message,
>      cookie);
> -    dispatcher_send_message(&qxl_state->dispatcher, message, &draw);
> +    dispatcher_send_message(qxl_state->dispatcher, message, &draw);
>  }
>  
>  void red_qxl_async_complete(QXLState *qxl_state,
> @@ -954,7 +954,7 @@ void red_qxl_init(RedsState *reds, QXLInstance *qxl)
>      qxl_state->qxl = qxl;
>      pthread_mutex_init(&qxl_state->scanout_mutex, NULL);
>      qxl_state->scanout.drm_dma_buf_fd = -1;
> -    dispatcher_init(&qxl_state->dispatcher, RED_WORKER_MESSAGE_COUNT, NULL);
> +    qxl_state->dispatcher = dispatcher_new(RED_WORKER_MESSAGE_COUNT, NULL);
>      qxl_state->base.major_version = SPICE_INTERFACE_QXL_MAJOR;
>      qxl_state->base.minor_version = SPICE_INTERFACE_QXL_MINOR;
>      qxl_state->base.wakeup = qxl_worker_wakeup;
> @@ -1003,15 +1003,15 @@ void red_qxl_init(RedsState *reds, QXLInstance *qxl)
>      red_worker_run(worker);
>  }
>  
> -struct Dispatcher *red_qxl_get_dispatcher(QXLState *qxl_state)
> +Dispatcher *red_qxl_get_dispatcher(QXLState *qxl_state)
>  {
> -    return &qxl_state->dispatcher;
> +    return qxl_state->dispatcher;
>  }
>  
>  void red_qxl_set_dispatcher_opaque(QXLState *qxl_state,
>                                     void *opaque)
>  {
> -    dispatcher_set_opaque(&qxl_state->dispatcher, opaque);
> +    dispatcher_set_opaque(qxl_state->dispatcher, opaque);
>  }
>  
>  void red_qxl_clear_pending(QXLState *qxl_state, int pending)
> @@ -1041,7 +1041,7 @@ void red_qxl_on_ic_change(QXLState *qxl_state,
> SpiceImageCompression ic)
>  {
>      RedWorkerMessageSetCompression payload;
>      payload.image_compression = ic;
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_SET_COMPRESSION,
>                              &payload);
>  }
> @@ -1050,7 +1050,7 @@ void red_qxl_on_sv_change(QXLState *qxl_state, int sv)
>  {
>      RedWorkerMessageSetStreamingVideo payload;
>      payload.streaming_video = sv;
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_SET_STREAMING_VIDEO,
>                              &payload);
>  }
> @@ -1059,7 +1059,7 @@ void red_qxl_set_mouse_mode(QXLState *qxl_state,
> uint32_t mode)
>  {
>      RedWorkerMessageSetMouseMode payload;
>      payload.mode = mode;
> -    dispatcher_send_message(&qxl_state->dispatcher,
> +    dispatcher_send_message(qxl_state->dispatcher,
>                              RED_WORKER_MESSAGE_SET_MOUSE_MODE,
>                              &payload);
>  }
> diff --git a/server/red-qxl.h b/server/red-qxl.h
> index f100cb4..16a348d 100644
> --- a/server/red-qxl.h
> +++ b/server/red-qxl.h
> @@ -19,6 +19,7 @@
>  #define _H_RED_DISPATCHER
>  
>  #include "red-channel.h"
> +#include "dispatcher.h"
>  
>  typedef struct QXLState QXLState;
>  
> @@ -36,7 +37,7 @@ void red_qxl_stop(QXLState *qxl_state);
>  void red_qxl_start(QXLState *qxl_state);
>  uint32_t red_qxl_get_ram_size(QXLState *qxl_state);
>  void red_qxl_async_complete(QXLState *qxl_state, AsyncCommand *cmd);
> -struct Dispatcher *red_qxl_get_dispatcher(QXLState *qxl_state);
> +Dispatcher *red_qxl_get_dispatcher(QXLState *qxl_state);
>  gboolean red_qxl_use_client_monitors_config(QXLState *qxl_state);
>  gboolean red_qxl_client_monitors_config(QXLState *qxl_state,
>  VDAgentMonitorsConfig *monitors_config);
>  gboolean red_qxl_get_primary_active(QXLState *qxl_state);

Does not seem that the change to this file is necessary.
I would remove it.

I'll send an update.

Frediano


More information about the Spice-devel mailing list