[Spice-devel] [PATCH 03/14] Introduce simple RedPipeItem class

Jonathon Jongsma jjongsma at redhat.com
Thu Apr 7 22:11:16 UTC 2016


From: Christophe Fergeau <cfergeau at redhat.com>

This is similar to PipeItem (which is a type id + a RingItem linked list
member), except that it's refcounted. A user-defined callback is called
when the refcount drops to 0.
Refcounted is open coded for several classes deriving from PipeItem, so
this base class will help to share this code, and allow to remove some
ref/unref virtual functions in some interfaces when we can assume every
instance derives from this base class.
---
 server/Makefile.am     |  2 ++
 server/red-channel.c   |  6 -----
 server/red-channel.h   | 13 +---------
 server/red-pipe-item.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++
 server/red-pipe-item.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++
 server/smartcard.c     |  1 +
 6 files changed, 129 insertions(+), 18 deletions(-)
 create mode 100644 server/red-pipe-item.c
 create mode 100644 server/red-pipe-item.h

diff --git a/server/Makefile.am b/server/Makefile.am
index a7a8d9f..a119c86 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -112,6 +112,8 @@ libserver_la_SOURCES =				\
 	display-channel.h			\
 	cursor-channel.c			\
 	cursor-channel.h			\
+	red-pipe-item.c				\
+	red-pipe-item.h				\
 	reds.c					\
 	reds.h					\
 	reds-private.h				\
diff --git a/server/red-channel.c b/server/red-channel.c
index d8f1d27..dcec39e 100644
--- a/server/red-channel.c
+++ b/server/red-channel.c
@@ -1658,12 +1658,6 @@ void red_channel_client_set_message_serial(RedChannelClient *rcc, uint64_t seria
     rcc->send_data.serial = serial;
 }
 
-void pipe_item_init(PipeItem *item, int type)
-{
-    ring_item_init(&item->link);
-    item->type = type;
-}
-
 static inline gboolean client_pipe_add(RedChannelClient *rcc, PipeItem *item, RingItem *pos)
 {
     spice_assert(rcc && item);
diff --git a/server/red-channel.h b/server/red-channel.h
index 94b09eb..3c762ff 100644
--- a/server/red-channel.h
+++ b/server/red-channel.h
@@ -33,6 +33,7 @@
 #include "demarshallers.h"
 #include "reds-stream.h"
 #include "stat.h"
+#include "red-pipe-item.h"
 
 #define MAX_SEND_BUFS 1000
 #define CLIENT_ACK_WINDOW 20
@@ -147,16 +148,6 @@ enum {
     PIPE_ITEM_TYPE_CHANNEL_BASE=101,
 };
 
-typedef struct PipeItem {
-    RingItem link;
-    int type;
-} PipeItem;
-
-static inline int pipe_item_is_linked(PipeItem *item)
-{
-    return ring_item_is_linked(&item->link);
-}
-
 typedef uint8_t *(*channel_alloc_msg_recv_buf_proc)(RedChannelClient *channel,
                                                     uint16_t type, uint32_t size);
 typedef int (*channel_handle_parsed_proc)(RedChannelClient *rcc, uint32_t size, uint16_t type,
@@ -473,8 +464,6 @@ int red_channel_client_get_roundtrip_ms(RedChannelClient *rcc);
  */
 void red_channel_client_start_connectivity_monitoring(RedChannelClient *rcc, uint32_t timeout_ms);
 
-void pipe_item_init(PipeItem *item, int type);
-
 // TODO: add back the channel_pipe_add functionality - by adding reference counting
 // to the PipeItem.
 
diff --git a/server/red-pipe-item.c b/server/red-pipe-item.c
new file mode 100644
index 0000000..a9ebfda
--- /dev/null
+++ b/server/red-pipe-item.c
@@ -0,0 +1,65 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 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
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#include <config.h>
+
+#include "red-channel.h"
+#include "red-pipe-item.h"
+
+void pipe_item_init(PipeItem *item, int type)
+{
+    ring_item_init(&item->link);
+    item->type = type;
+}
+
+RedPipeItem *red_pipe_item_ref(gpointer object)
+{
+    RedPipeItem *item = object;
+
+    g_return_val_if_fail(item->refcount > 0, NULL);
+
+    item->refcount++;
+
+    return item;
+}
+
+void red_pipe_item_unref(gpointer object)
+{
+    RedPipeItem *item = object;
+
+    g_return_if_fail(item->refcount > 0);
+
+    item->refcount--;
+    if (item->refcount == 0) {
+        if (item->free_func) {
+            item->free_func(item);
+        } else {
+            free(item);
+        }
+    }
+}
+
+void red_pipe_item_init(RedPipeItem *item,
+                        gint type,
+                        GDestroyNotify free_func)
+{
+    g_return_if_fail(item->refcount == 0);
+
+    pipe_item_init(&item->parent, type);
+    item->refcount = 1;
+    item->free_func = free_func;
+}
diff --git a/server/red-pipe-item.h b/server/red-pipe-item.h
new file mode 100644
index 0000000..7bc5abc
--- /dev/null
+++ b/server/red-pipe-item.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 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
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef __RED_MINI_OBJECT_H__
+#define __RED_MINI_OBJECT_H__
+
+#include <glib.h>
+
+typedef struct PipeItem {
+    RingItem link;
+    int type;
+} PipeItem;
+
+static inline int pipe_item_is_linked(PipeItem *item)
+{
+    return ring_item_is_linked(&item->link);
+}
+
+void pipe_item_init(PipeItem *item, int type);
+
+/* Refcounted pipe item */
+/* Future goals are to:
+ * - merge it with PipeItem
+ * - stop having RingItem embedded at the beginning of the PipeItem base class
+ *   but instead have:
+ *   {
+ *       int type;
+ *       int refcount;
+ *       PipeItem link;
+ *   }
+ *   or even drop PipeItem, and use a GList in RedChannel
+ */
+typedef struct {
+    PipeItem parent;
+
+    /* private */
+    int refcount;
+
+    GDestroyNotify free_func;
+} RedPipeItem;
+
+RedPipeItem *red_pipe_item_ref(gpointer item);
+void red_pipe_item_unref(gpointer item);
+void red_pipe_item_init(RedPipeItem *item, int type, GDestroyNotify free_func);
+
+#endif
diff --git a/server/smartcard.c b/server/smartcard.c
index eb68a8b..557a622 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -88,6 +88,7 @@ typedef struct ErrorItem {
     VSCMsgError  error;
 } ErrorItem;
 
+
 typedef struct MsgItem {
     PipeItem base;
     uint32_t refs;
-- 
2.4.11



More information about the Spice-devel mailing list