[Spice-devel] [PATCH 13/13] Move SpiceCharDeviceCallbacks into RedCharDeviceClass

Frediano Ziglio fziglio at redhat.com
Wed Mar 23 12:48:39 UTC 2016


From: Christophe Fergeau <cfergeau at redhat.com>

This structure holding virtual function pointers was kept until now as a
RedCharDevice member in order to make the GObject conversion easier.
Now that all RedCharDevice children are converted to GObject, it can be
moved into RedCharDeviceClass.
---
 server/char-device.c | 45 ++++++++++++++++-----------------
 server/char-device.h | 71 +++++++++++++++++++++++-----------------------------
 server/reds.c        | 35 +++++++++++---------------
 server/smartcard.c   | 20 +++++++--------
 server/spicevmc.c    | 36 +++++++++++---------------
 5 files changed, 94 insertions(+), 113 deletions(-)

diff --git a/server/char-device.c b/server/char-device.c
index e1004d8..c9c2095 100644
--- a/server/char-device.c
+++ b/server/char-device.c
@@ -69,7 +69,6 @@ struct RedCharDevicePrivate {
     int during_read_from_device;
     int during_write_to_device;
 
-    SpiceCharDeviceCallbacks cbs;
     void *opaque;
     SpiceServer *reds;
 };
@@ -114,21 +113,27 @@ typedef struct SpiceCharDeviceMsgToClientItem {
 static SpiceCharDeviceMsgToClient *
 spice_char_device_read_one_msg_from_device(SpiceCharDeviceState *dev)
 {
-   return dev->priv->cbs.read_one_msg_from_device(dev->priv->sin, dev->priv->opaque);
+   RedCharDeviceClass *klass = RED_CHAR_DEVICE_GET_CLASS(dev);
+
+   return klass->read_one_msg_from_device(dev->priv->sin, dev->priv->opaque);
 }
 
 static SpiceCharDeviceMsgToClient *
 spice_char_device_ref_msg_to_client(SpiceCharDeviceState *dev,
                                     SpiceCharDeviceMsgToClient *msg)
 {
-   return dev->priv->cbs.ref_msg_to_client(msg, dev->priv->opaque);
+   RedCharDeviceClass *klass = RED_CHAR_DEVICE_GET_CLASS(dev);
+
+   return klass->ref_msg_to_client(msg, dev->priv->opaque);
 }
 
 static void
 spice_char_device_unref_msg_to_client(SpiceCharDeviceState *dev,
                                       SpiceCharDeviceMsgToClient *msg)
 {
-   dev->priv->cbs.unref_msg_to_client(msg, dev->priv->opaque);
+   RedCharDeviceClass *klass = RED_CHAR_DEVICE_GET_CLASS(dev);
+
+   klass->unref_msg_to_client(msg, dev->priv->opaque);
 }
 
 static void
@@ -136,7 +141,9 @@ spice_char_device_send_msg_to_client(SpiceCharDeviceState *dev,
                                      SpiceCharDeviceMsgToClient *msg,
                                      RedClient *client)
 {
-   dev->priv->cbs.send_msg_to_client(msg, client, dev->priv->opaque);
+   RedCharDeviceClass *klass = RED_CHAR_DEVICE_GET_CLASS(dev);
+
+   klass->send_msg_to_client(msg, client, dev->priv->opaque);
 }
 
 static void
@@ -144,21 +151,27 @@ spice_char_device_send_tokens_to_client(SpiceCharDeviceState *dev,
                                         RedClient *client,
                                         uint32_t tokens)
 {
-   dev->priv->cbs.send_tokens_to_client(client, tokens, dev->priv->opaque);
+   RedCharDeviceClass *klass = RED_CHAR_DEVICE_GET_CLASS(dev);
+
+   klass->send_tokens_to_client(client, tokens, dev->priv->opaque);
 }
 
 static void
 spice_char_device_on_free_self_token(SpiceCharDeviceState *dev)
 {
-   if (dev->priv->cbs.on_free_self_token != NULL) {
-       dev->priv->cbs.on_free_self_token(dev->priv->opaque);
+   RedCharDeviceClass *klass = RED_CHAR_DEVICE_GET_CLASS(dev);
+
+   if (klass->on_free_self_token != NULL) {
+       klass->on_free_self_token(dev->priv->opaque);
    }
 }
 
 static void
 spice_char_device_remove_client(SpiceCharDeviceState *dev, RedClient *client)
 {
-   dev->priv->cbs.remove_client(client, dev->priv->opaque);
+   RedCharDeviceClass *klass = RED_CHAR_DEVICE_GET_CLASS(dev);
+
+   klass->remove_client(client, dev->priv->opaque);
 }
 
 static void spice_char_device_write_buffer_free(SpiceCharDeviceWriteBuffer *buf)
@@ -1244,17 +1257,3 @@ red_char_device_init(RedCharDevice *self)
 
     g_signal_connect(self, "notify::sin", G_CALLBACK(red_char_device_on_sin_changed), NULL);
 }
-
-/* TODO: needs to be moved to class vfuncs once all child classes are gobjects */
-void
-red_char_device_set_callbacks(RedCharDevice *dev,
-                              SpiceCharDeviceCallbacks *cbs,
-                              gpointer opaque)
-{
-    g_assert(cbs->read_one_msg_from_device && cbs->ref_msg_to_client &&
-             cbs->unref_msg_to_client && cbs->send_msg_to_client &&
-             cbs->send_tokens_to_client && cbs->remove_client);
-
-    dev->priv->cbs = *cbs;
-    dev->priv->opaque = opaque;
-}
diff --git a/server/char-device.h b/server/char-device.h
index d0fc63c..207c6d5 100644
--- a/server/char-device.h
+++ b/server/char-device.h
@@ -24,6 +24,8 @@
 #include "red-channel.h"
 #include "migration-protocol.h"
 
+typedef void SpiceCharDeviceMsgToClient;
+
 #define RED_TYPE_CHAR_DEVICE red_char_device_get_type()
 
 #define RED_CHAR_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), RED_TYPE_CHAR_DEVICE, RedCharDevice))
@@ -47,15 +49,40 @@ struct SpiceCharDeviceState
 struct RedCharDeviceClass
 {
     GObjectClass parent_class;
+
+    /*
+     * Messages that are addressed to the client can be queued in case we have
+     * multiple clients and some of them don't have enough tokens.
+     */
+
+    /* reads from the device till reaching a msg that should be sent to the client,
+     * or till the reading fails */
+    SpiceCharDeviceMsgToClient* (*read_one_msg_from_device)(SpiceCharDeviceInstance *sin,
+                                                            void *opaque);
+    SpiceCharDeviceMsgToClient* (*ref_msg_to_client)(SpiceCharDeviceMsgToClient *msg,
+                                                     void *opaque);
+    void (*unref_msg_to_client)(SpiceCharDeviceMsgToClient *msg,
+                                void *opaque);
+    void (*send_msg_to_client)(SpiceCharDeviceMsgToClient *msg,
+                               RedClient *client,
+                               void *opaque); /* after this call, the message is unreferenced */
+
+    /* The cb is called when a predefined number of write buffers were consumed by the
+     * device */
+    void (*send_tokens_to_client)(RedClient *client, uint32_t tokens, void *opaque);
+
+    /* The cb is called when a server (self) message that was addressed to the device,
+     * has been completely written to it */
+    void (*on_free_self_token)(void *opaque);
+
+    /* This cb is called if it is recommanded that a client will be removed
+     * due to slow flow or due to some other error.
+     * The called instance should disconnect the client, or at least the corresponding channel */
+    void (*remove_client)(RedClient *client, void *opaque);
 };
 
 GType red_char_device_get_type(void) G_GNUC_CONST;
 
-typedef struct SpiceCharDeviceCallbacks SpiceCharDeviceCallbacks;
-void red_char_device_set_callbacks(RedCharDevice *dev,
-                                   SpiceCharDeviceCallbacks *cbs,
-                                   gpointer opaque);
-
 /*
  * Shared code for char devices, mainly for flow control.
  *
@@ -127,40 +154,6 @@ typedef struct SpiceCharDeviceWriteBuffer {
     uint32_t refs;
 } SpiceCharDeviceWriteBuffer;
 
-typedef void SpiceCharDeviceMsgToClient;
-
-struct SpiceCharDeviceCallbacks {
-    /*
-     * Messages that are addressed to the client can be queued in case we have
-     * multiple clients and some of them don't have enough tokens.
-     */
-
-    /* reads from the device till reaching a msg that should be sent to the client,
-     * or till the reading fails */
-    SpiceCharDeviceMsgToClient* (*read_one_msg_from_device)(SpiceCharDeviceInstance *sin,
-                                                            void *opaque);
-    SpiceCharDeviceMsgToClient* (*ref_msg_to_client)(SpiceCharDeviceMsgToClient *msg,
-                                                     void *opaque);
-    void (*unref_msg_to_client)(SpiceCharDeviceMsgToClient *msg,
-                                void *opaque);
-    void (*send_msg_to_client)(SpiceCharDeviceMsgToClient *msg,
-                               RedClient *client,
-                               void *opaque); /* after this call, the message is unreferenced */
-
-    /* The cb is called when a predefined number of write buffers were consumed by the
-     * device */
-    void (*send_tokens_to_client)(RedClient *client, uint32_t tokens, void *opaque);
-
-    /* The cb is called when a server (self) message that was addressed to the device,
-     * has been completely written to it */
-    void (*on_free_self_token)(void *opaque);
-
-    /* This cb is called if it is recommanded that a client will be removed
-     * due to slow flow or due to some other error.
-     * The called instance should disconnect the client, or at least the corresponding channel */
-    void (*remove_client)(RedClient *client, void *opaque);
-};
-
 void spice_char_device_state_reset_dev_instance(SpiceCharDeviceState *dev,
                                                 SpiceCharDeviceInstance *sin);
 void spice_char_device_state_destroy(SpiceCharDeviceState *dev);
diff --git a/server/reds.c b/server/reds.c
index a8cc5da..e32dbd2 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -4337,33 +4337,28 @@ static void
 red_char_device_vdi_port_class_init(RedCharDeviceVDIPortClass *klass)
 {
     GObjectClass *object_class = G_OBJECT_CLASS(klass);
+    RedCharDeviceClass *char_dev_class = RED_CHAR_DEVICE_CLASS(klass);
 
     g_type_class_add_private(klass, sizeof (RedCharDeviceVDIPortPrivate));
 
     object_class->finalize = red_char_device_vdi_port_finalize;
     object_class->constructed = red_char_device_vdi_port_constructed;
+
+    char_dev_class->read_one_msg_from_device = vdi_port_read_one_msg_from_device;
+    char_dev_class->ref_msg_to_client = vdi_port_ref_msg_to_client;
+    char_dev_class->unref_msg_to_client = vdi_port_unref_msg_to_client;
+    char_dev_class->send_msg_to_client = vdi_port_send_msg_to_client;
+    char_dev_class->send_tokens_to_client = vdi_port_send_tokens_to_client;
+    char_dev_class->remove_client = vdi_port_remove_client;
+    char_dev_class->on_free_self_token = vdi_port_on_free_self_token;
 }
 
 static RedCharDeviceVDIPort *red_char_device_vdi_port_new(RedsState *reds)
 {
-    RedCharDevice *char_dev;
-    SpiceCharDeviceCallbacks char_dev_cbs = {
-        .read_one_msg_from_device = vdi_port_read_one_msg_from_device,
-        .ref_msg_to_client = vdi_port_ref_msg_to_client,
-        .unref_msg_to_client = vdi_port_unref_msg_to_client,
-        .send_msg_to_client = vdi_port_send_msg_to_client,
-        .send_tokens_to_client = vdi_port_send_tokens_to_client,
-        .remove_client = vdi_port_remove_client,
-        .on_free_self_token = vdi_port_on_free_self_token,
-    };
-
-    char_dev = g_object_new(RED_TYPE_CHAR_DEVICE_VDIPORT,
-                            "spice-server", reds,
-                            "client-tokens-interval", REDS_TOKENS_TO_SEND,
-                            "self-tokens", REDS_NUM_INTERNAL_AGENT_MESSAGES,
-                            NULL);
-
-    red_char_device_set_callbacks(RED_CHAR_DEVICE(char_dev),
-                                  &char_dev_cbs, reds);
-    return RED_CHAR_DEVICE_VDIPORT(char_dev);
+    return g_object_new(RED_TYPE_CHAR_DEVICE_VDIPORT,
+                        "spice-server", reds,
+                        "client-tokens-interval", REDS_TOKENS_TO_SEND,
+                        "self-tokens", REDS_NUM_INTERNAL_AGENT_MESSAGES,
+                        "opaque", reds,
+                        NULL);
 }
diff --git a/server/smartcard.c b/server/smartcard.c
index fc27bfe..910afc2 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -275,14 +275,6 @@ static SpiceCharDeviceInstance *smartcard_readers_get_unattached(void)
 static SmartCardDeviceState *smartcard_device_state_new(RedsState *reds, SpiceCharDeviceInstance *sin)
 {
     RedCharDevice *char_dev;
-    SpiceCharDeviceCallbacks char_dev_cbs = {
-        .read_one_msg_from_device = smartcard_read_msg_from_device,
-        .ref_msg_to_client = smartcard_ref_msg_to_client,
-        .unref_msg_to_client = smartcard_unref_msg_to_client,
-        .send_msg_to_client = smartcard_send_msg_to_client,
-        .send_tokens_to_client = smartcard_send_tokens_to_client,
-        .remove_client = smartcard_remove_client,
-    };
 
     char_dev = g_object_new(RED_TYPE_CHAR_DEVICE_SMARTCARD,
                             "sin", sin,
@@ -291,8 +283,8 @@ static SmartCardDeviceState *smartcard_device_state_new(RedsState *reds, SpiceCh
                             "self-tokens", ~0ULL,
                             NULL);
 
-    red_char_device_set_callbacks(RED_CHAR_DEVICE(char_dev),
-                                  &char_dev_cbs, char_dev);
+    g_object_set(char_dev, "opaque", char_dev, NULL);
+
     return RED_CHAR_DEVICE_SMARTCARD(char_dev);
 }
 
@@ -872,10 +864,18 @@ static void
 red_char_device_smartcard_class_init(RedCharDeviceSmartcardClass *klass)
 {
     GObjectClass *object_class = G_OBJECT_CLASS(klass);
+    RedCharDeviceClass *char_dev_class = RED_CHAR_DEVICE_CLASS(klass);
 
     g_type_class_add_private(klass, sizeof (RedCharDeviceSmartcardPrivate));
 
     object_class->finalize = red_char_device_smartcard_finalize;
+
+    char_dev_class->read_one_msg_from_device = smartcard_read_msg_from_device;
+    char_dev_class->ref_msg_to_client = smartcard_ref_msg_to_client;
+    char_dev_class->unref_msg_to_client = smartcard_unref_msg_to_client;
+    char_dev_class->send_msg_to_client = smartcard_send_msg_to_client;
+    char_dev_class->send_tokens_to_client = smartcard_send_tokens_to_client;
+    char_dev_class->remove_client = smartcard_remove_client;
 }
 
 static void
diff --git a/server/spicevmc.c b/server/spicevmc.c
index 9a009b9..c5434c1 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -624,10 +624,18 @@ static void
 red_char_device_spicevmc_class_init(RedCharDeviceSpiceVmcClass *klass)
 {
     GObjectClass *object_class = G_OBJECT_CLASS(klass);
+    RedCharDeviceClass *char_dev_class = RED_CHAR_DEVICE_CLASS(klass);
 
     g_type_class_add_private(klass, sizeof (RedCharDeviceSpiceVmcPrivate));
 
     object_class->finalize = red_char_device_spicevmc_finalize;
+
+    char_dev_class->read_one_msg_from_device = spicevmc_chardev_read_msg_from_dev;
+    char_dev_class->ref_msg_to_client = spicevmc_chardev_ref_msg_to_client;
+    char_dev_class->unref_msg_to_client = spicevmc_chardev_unref_msg_to_client;
+    char_dev_class->send_msg_to_client = spicevmc_chardev_send_msg_to_client;
+    char_dev_class->send_tokens_to_client = spicevmc_char_dev_send_tokens_to_client;
+    char_dev_class->remove_client = spicevmc_char_dev_remove_client;
 }
 
 static void
@@ -641,25 +649,11 @@ red_char_device_spicevmc_new(SpiceCharDeviceInstance *sin,
                              RedsState *reds,
                              void *opaque)
 {
-    RedCharDevice *char_dev;
-    SpiceCharDeviceCallbacks char_dev_cbs = {
-        .read_one_msg_from_device = spicevmc_chardev_read_msg_from_dev,
-        .ref_msg_to_client = spicevmc_chardev_ref_msg_to_client,
-        .unref_msg_to_client = spicevmc_chardev_unref_msg_to_client,
-        .send_msg_to_client = spicevmc_chardev_send_msg_to_client,
-        .send_tokens_to_client = spicevmc_char_dev_send_tokens_to_client,
-        .remove_client = spicevmc_char_dev_remove_client,
-    };
-
-    char_dev = g_object_new(RED_TYPE_CHAR_DEVICE_SPICEVMC,
-                            "sin", sin,
-                            "spice-server", reds,
-                            "client-tokens-interval", 0ULL,
-                            "self-tokens", ~0ULL,
-                            "opaque", opaque,
-                            NULL);
-
-    red_char_device_set_callbacks(RED_CHAR_DEVICE(char_dev),
-                                  &char_dev_cbs, opaque);
-    return char_dev;
+    return g_object_new(RED_TYPE_CHAR_DEVICE_SPICEVMC,
+                        "sin", sin,
+                        "spice-server", reds,
+                        "client-tokens-interval", 0ULL,
+                        "self-tokens", ~0ULL,
+                        "opaque", opaque,
+                        NULL);
 }
-- 
2.5.5



More information about the Spice-devel mailing list