From: Jonathon Jongsma <jjongsma@xxxxxxxxxx> 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); + 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", + "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, + "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); -- 2.5.0 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel