[Spice-devel] [PATCH 06/19] Convert Dispatcher and MainDispatcher to GObjects
Frediano Ziglio
fziglio at redhat.com
Fri Feb 19 11:54:36 UTC 2016
>
> From: Jonathon Jongsma <jjongsma at redhat.com>
>
> Allows more explicit inheritance relationship, and numerous other
> advantages.
> ---
> server/dispatcher.c | 231
> ++++++++++++++++++++++++++++++++++++-----------
> server/dispatcher.h | 53 ++++++-----
> server/main-dispatcher.c | 152 +++++++++++++++++++++++++------
> server/main-dispatcher.h | 25 +++++
> server/red-dispatcher.c | 81 +++++++++--------
> server/red-dispatcher.h | 3 +-
> 6 files changed, 401 insertions(+), 144 deletions(-)
>
> diff --git a/server/dispatcher.c b/server/dispatcher.c
> index d6c03ca..2c04eb4 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,153 @@
> #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);
Missed to destroy the mutex.
> + G_OBJECT_CLASS(dispatcher_parent_class)->finalize(object);
> +}
> +
> +static void dispatcher_constructed(GObject *object)
> +{
> + Dispatcher *self = DISPATCHER(object);
> + int channels[2];
> +
> +#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",
Looking at all patches this (nick) 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,
max_message_type should be converted to guint.
This could cause problem on some architectures.
> + "opaque", opaque,
> + NULL);
> +}
> +
> +
> #define ACK 0xffffffff
>
> /*
> @@ -118,10 +264,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 +275,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 +317,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 +343,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 +360,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 +376,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 +403,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..6b8ca53 100644
> --- a/server/main-dispatcher.c
> +++ b/server/main-dispatcher.c
> @@ -47,12 +47,96 @@
> * 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 */
Not that weak, try to set them NULL and see what's happening...
> +};
> +
> +
> +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_class_init(MainDispatcherClass *klass)
> +{
> + GObjectClass *object_class = G_OBJECT_CLASS(klass);
> +
> + g_type_class_add_private(klass, sizeof(MainDispatcherPrivate));
> +
> + 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 +169,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 +187,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 +204,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 +213,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 +224,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 +233,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 +247,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 +265,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 +276,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 +286,33 @@ 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);
> + 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-dispatcher.c b/server/red-dispatcher.c
> index 33cd12f..4b839a9 100644
> --- a/server/red-dispatcher.c
> +++ b/server/red-dispatcher.c
> @@ -48,7 +48,7 @@ struct AsyncCommand {
> struct RedDispatcher {
> QXLWorker base;
> QXLInstance *qxl;
> - Dispatcher dispatcher;
> + Dispatcher *dispatcher;
Here you are changing inheritance to association... (1)
> uint32_t pending;
> int primary_active;
> int x_res;
> @@ -89,7 +89,7 @@ static void red_dispatcher_set_display_peer(RedChannel
> *channel, RedClient *clie
> memcpy(payload.common_caps, common_caps,
> sizeof(uint32_t)*num_common_caps);
> memcpy(payload.caps, caps, sizeof(uint32_t)*num_caps);
>
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_DISPLAY_CONNECT,
> &payload);
> }
> @@ -110,7 +110,7 @@ static void
> red_dispatcher_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(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_DISPLAY_DISCONNECT,
> &payload);
> }
> @@ -125,7 +125,7 @@ static void
> red_dispatcher_display_migrate(RedChannelClient *rcc)
> dispatcher = (RedDispatcher *)rcc->channel->data;
> spice_printerr("channel type %u id %u", rcc->channel->type,
> rcc->channel->id);
> payload.rcc = rcc;
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_DISPLAY_MIGRATE,
> &payload);
> }
> @@ -149,7 +149,7 @@ static void red_dispatcher_set_cursor_peer(RedChannel
> *channel, RedClient *clien
> memcpy(payload.common_caps, common_caps,
> sizeof(uint32_t)*num_common_caps);
> memcpy(payload.caps, caps, sizeof(uint32_t)*num_caps);
>
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_CURSOR_CONNECT,
> &payload);
> }
> @@ -167,7 +167,7 @@ static void
> red_dispatcher_disconnect_cursor_peer(RedChannelClient *rcc)
> spice_printerr("");
> payload.rcc = rcc;
>
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_CURSOR_DISCONNECT,
> &payload);
> }
> @@ -183,7 +183,7 @@ static void
> red_dispatcher_cursor_migrate(RedChannelClient *rcc)
> dispatcher = (RedDispatcher *)rcc->channel->data;
> spice_printerr("channel type %u id %u", rcc->channel->type,
> rcc->channel->id);
> payload.rcc = rcc;
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_CURSOR_MIGRATE,
> &payload);
> }
> @@ -199,7 +199,7 @@ static void red_dispatcher_update_area(RedDispatcher
> *dispatcher, uint32_t surfa
> payload.qxl_dirty_rects = qxl_dirty_rects;
> payload.num_dirty_rects = num_dirty_rects;
> payload.clear_dirty_region = clear_dirty_region;
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_UPDATE,
> &payload);
> }
> @@ -245,7 +245,7 @@ static void
> red_dispatcher_update_area_async(RedDispatcher *dispatcher,
> payload.surface_id = surface_id;
> payload.qxl_area = *qxl_area;
> payload.clear_dirty_region = clear_dirty_region;
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> message,
> &payload);
> }
> @@ -263,7 +263,7 @@ static void red_dispatcher_add_memslot(RedDispatcher
> *dispatcher, QXLDevMemSlot
> RedWorkerMessageAddMemslot payload;
>
> payload.mem_slot = *mem_slot;
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_ADD_MEMSLOT,
> &payload);
> }
> @@ -280,7 +280,7 @@ static void
> red_dispatcher_add_memslot_async(RedDispatcher *dispatcher, QXLDevMe
>
> payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
> payload.mem_slot = *mem_slot;
> - dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
> + dispatcher_send_message(dispatcher->dispatcher, message, &payload);
> }
>
> static void red_dispatcher_del_memslot(RedDispatcher *dispatcher, uint32_t
> slot_group_id, uint32_t slot_id)
> @@ -290,7 +290,7 @@ static void red_dispatcher_del_memslot(RedDispatcher
> *dispatcher, uint32_t slot_
>
> payload.slot_group_id = slot_group_id;
> payload.slot_id = slot_id;
> - dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
> + dispatcher_send_message(dispatcher->dispatcher, message, &payload);
> }
>
> static void qxl_worker_del_memslot(QXLWorker *qxl_worker, uint32_t
> slot_group_id, uint32_t slot_id)
> @@ -302,7 +302,7 @@ static void red_dispatcher_destroy_surfaces(RedDispatcher
> *dispatcher)
> {
> RedWorkerMessageDestroySurfaces payload;
>
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_DESTROY_SURFACES,
> &payload);
> }
> @@ -318,7 +318,7 @@ static void
> red_dispatcher_destroy_surfaces_async(RedDispatcher *dispatcher, uin
> RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC;
>
> payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
> - dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
> + dispatcher_send_message(dispatcher->dispatcher, message, &payload);
> }
>
> static void red_dispatcher_destroy_primary_surface_complete(RedDispatcher
> *dispatcher)
> @@ -337,7 +337,7 @@ red_dispatcher_destroy_primary_surface_sync(RedDispatcher
> *dispatcher,
> {
> RedWorkerMessageDestroyPrimarySurface payload;
> payload.surface_id = surface_id;
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE,
> &payload);
> red_dispatcher_destroy_primary_surface_complete(dispatcher);
> @@ -352,7 +352,7 @@
> red_dispatcher_destroy_primary_surface_async(RedDispatcher *dispatcher,
>
> payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
> payload.surface_id = surface_id;
> - dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
> + dispatcher_send_message(dispatcher->dispatcher, message, &payload);
> }
>
> static void
> @@ -395,7 +395,7 @@ red_dispatcher_create_primary_surface_async(RedDispatcher
> *dispatcher, uint32_t
> payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
> payload.surface_id = surface_id;
> payload.surface = *surface;
> - dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
> + dispatcher_send_message(dispatcher->dispatcher, message, &payload);
> }
>
> static void
> @@ -407,7 +407,7 @@ red_dispatcher_create_primary_surface_sync(RedDispatcher
> *dispatcher, uint32_t s
> dispatcher->surface_create = *surface;
> payload.surface_id = surface_id;
> payload.surface = *surface;
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE,
> &payload);
> red_dispatcher_create_primary_surface_complete(dispatcher);
> @@ -434,7 +434,7 @@ static void
> red_dispatcher_reset_image_cache(RedDispatcher *dispatcher)
> {
> RedWorkerMessageResetImageCache payload;
>
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_RESET_IMAGE_CACHE,
> &payload);
> }
> @@ -448,7 +448,7 @@ static void red_dispatcher_reset_cursor(RedDispatcher
> *dispatcher)
> {
> RedWorkerMessageResetCursor payload;
>
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_RESET_CURSOR,
> &payload);
> }
> @@ -464,7 +464,7 @@ static void
> red_dispatcher_destroy_surface_wait_sync(RedDispatcher *dispatcher,
> RedWorkerMessageDestroySurfaceWait payload;
>
> payload.surface_id = surface_id;
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT,
> &payload);
> }
> @@ -478,7 +478,7 @@ static void
> red_dispatcher_destroy_surface_wait_async(RedDispatcher *dispatcher,
>
> payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
> payload.surface_id = surface_id;
> - dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
> + dispatcher_send_message(dispatcher->dispatcher, message, &payload);
> }
>
> static void red_dispatcher_destroy_surface_wait(RedDispatcher *dispatcher,
> @@ -501,7 +501,7 @@ static void red_dispatcher_reset_memslots(RedDispatcher
> *dispatcher)
> {
> RedWorkerMessageResetMemslots payload;
>
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_RESET_MEMSLOTS,
> &payload);
> }
> @@ -529,7 +529,7 @@ static void red_dispatcher_wakeup(RedDispatcher
> *dispatcher)
> if (red_dispatcher_set_pending(dispatcher,
> RED_DISPATCHER_PENDING_WAKEUP))
> return;
>
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_WAKEUP,
> &payload);
> }
> @@ -546,7 +546,7 @@ static void red_dispatcher_oom(RedDispatcher *dispatcher)
> if (red_dispatcher_set_pending(dispatcher, RED_DISPATCHER_PENDING_OOM))
> return;
>
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_OOM,
> &payload);
> }
> @@ -560,7 +560,7 @@ void red_dispatcher_start(RedDispatcher *dispatcher)
> {
> RedWorkerMessageStart payload;
>
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_START,
> &payload);
> }
> @@ -576,7 +576,7 @@ static void
> red_dispatcher_flush_surfaces_async(RedDispatcher *dispatcher, uint6
> RedWorkerMessage message = RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC;
>
> payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
> - dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
> + dispatcher_send_message(dispatcher->dispatcher, message, &payload);
> }
>
> static void red_dispatcher_monitors_config_async(RedDispatcher *dispatcher,
> @@ -592,14 +592,14 @@ static void
> red_dispatcher_monitors_config_async(RedDispatcher *dispatcher,
> payload.group_id = group_id;
> payload.max_monitors = dispatcher->max_monitors;
>
> - dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
> + dispatcher_send_message(dispatcher->dispatcher, message, &payload);
> }
>
> static void red_dispatcher_driver_unload(RedDispatcher *dispatcher)
> {
> RedWorkerMessageDriverUnload payload;
>
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_DRIVER_UNLOAD,
> &payload);
> }
> @@ -608,7 +608,7 @@ void red_dispatcher_stop(RedDispatcher *dispatcher)
> {
> RedWorkerMessageStop payload;
>
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_STOP,
> &payload);
> }
> @@ -627,7 +627,7 @@ static void red_dispatcher_loadvm_commands(RedDispatcher
> *dispatcher,
> spice_printerr("");
> payload.count = count;
> payload.ext = ext;
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_LOADVM_COMMANDS,
> &payload);
> }
> @@ -848,7 +848,7 @@ void spice_qxl_gl_scanout(QXLInstance *qxl,
> pthread_mutex_unlock(&qxl->st->scanout_mutex);
>
> /* FIXME: find a way to coallesce all pending SCANOUTs */
> - dispatcher_send_message(&qxl->st->dispatcher->dispatcher,
> +
> dispatcher_send_message(red_dispatcher_get_dispatcher(qxl->st->dispatcher),
> RED_WORKER_MESSAGE_GL_SCANOUT, NULL);
> }
>
> @@ -873,7 +873,8 @@ void spice_qxl_gl_draw_async(QXLInstance *qxl,
>
> dispatcher = qxl->st->dispatcher;
> qxl->st->gl_draw_async = async_command_alloc(dispatcher, message,
> cookie);
> - dispatcher_send_message(&dispatcher->dispatcher, message, &draw);
> + dispatcher_send_message(red_dispatcher_get_dispatcher(dispatcher),
> + message, &draw);
> }
>
> void red_dispatcher_async_complete(struct RedDispatcher *dispatcher,
> @@ -922,7 +923,7 @@ void red_dispatcher_init(RedsState *reds, QXLInstance
> *qxl)
> red_dispatcher = spice_new0(RedDispatcher, 1);
> red_dispatcher->reds = reds;
> red_dispatcher->qxl = qxl;
> - dispatcher_init(&red_dispatcher->dispatcher, RED_WORKER_MESSAGE_COUNT,
> NULL);
> + red_dispatcher->dispatcher = dispatcher_new(RED_WORKER_MESSAGE_COUNT,
> NULL);
> red_dispatcher->base.major_version = SPICE_INTERFACE_QXL_MAJOR;
> red_dispatcher->base.minor_version = SPICE_INTERFACE_QXL_MINOR;
> red_dispatcher->base.wakeup = qxl_worker_wakeup;
> @@ -972,15 +973,15 @@ void red_dispatcher_init(RedsState *reds, QXLInstance
> *qxl)
> qxl->st->dispatcher = red_dispatcher;
> }
>
> -struct Dispatcher *red_dispatcher_get_dispatcher(RedDispatcher
> *red_dispatcher)
> +Dispatcher *red_dispatcher_get_dispatcher(RedDispatcher *red_dispatcher)
> {
> - return &red_dispatcher->dispatcher;
> + return red_dispatcher->dispatcher;
> }
>
> void red_dispatcher_set_dispatcher_opaque(RedDispatcher *red_dispatcher,
> void *opaque)
> {
> - dispatcher_set_opaque(&red_dispatcher->dispatcher, opaque);
> + dispatcher_set_opaque(red_dispatcher->dispatcher, opaque);
> }
>
> void red_dispatcher_clear_pending(RedDispatcher *red_dispatcher, int
> pending)
> @@ -1010,7 +1011,7 @@ void red_dispatcher_on_ic_change(RedDispatcher
> *dispatcher, SpiceImageCompressio
> {
> RedWorkerMessageSetCompression payload;
> payload.image_compression = ic;
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_SET_COMPRESSION,
> &payload);
> }
> @@ -1019,7 +1020,7 @@ void red_dispatcher_on_sv_change(RedDispatcher
> *dispatcher, int sv)
> {
> RedWorkerMessageSetStreamingVideo payload;
> payload.streaming_video = sv;
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_SET_STREAMING_VIDEO,
> &payload);
> }
> @@ -1028,7 +1029,7 @@ void red_dispatcher_set_mouse_mode(RedDispatcher
> *dispatcher, uint32_t mode)
> {
> RedWorkerMessageSetMouseMode payload;
> payload.mode = mode;
> - dispatcher_send_message(&dispatcher->dispatcher,
> + dispatcher_send_message(dispatcher->dispatcher,
> RED_WORKER_MESSAGE_SET_MOUSE_MODE,
> &payload);
> }
> diff --git a/server/red-dispatcher.h b/server/red-dispatcher.h
> index b5b794f..14a8079 100644
> --- a/server/red-dispatcher.h
> +++ b/server/red-dispatcher.h
> @@ -19,6 +19,7 @@
> #define _H_RED_DISPATCHER
>
> #include "red-channel.h"
> +#include "dispatcher.h"
>
> typedef struct RedDispatcher RedDispatcher;
>
> @@ -36,7 +37,7 @@ void red_dispatcher_stop(RedDispatcher *dispatcher);
> void red_dispatcher_start(RedDispatcher *dispatcher);
> uint32_t red_dispatcher_qxl_ram_size(RedDispatcher *dispatcher);
> void red_dispatcher_async_complete(struct RedDispatcher *, AsyncCommand *);
> -struct Dispatcher *red_dispatcher_get_dispatcher(struct RedDispatcher *);
> +Dispatcher *red_dispatcher_get_dispatcher(struct RedDispatcher *);
> gboolean red_dispatcher_use_client_monitors_config(RedDispatcher
> *dispatcher);
> gboolean red_dispatcher_client_monitors_config(RedDispatcher *dispatcher,
> VDAgentMonitorsConfig *monitors_config);
> gboolean red_dispatcher_get_primary_active(RedDispatcher *dispatcher);
Frediano
More information about the Spice-devel
mailing list