Patchwork [06/21] plug: add socket property type

login
register
mail settings
Submitter Anthony Liguori
Date July 25, 2011, 1:44 a.m.
Message ID <1311558293-5855-7-git-send-email-aliguori@us.ibm.com>
Download mbox | patch
Permalink /patch/106580/
State New
Headers show

Comments

Anthony Liguori - July 25, 2011, 1:44 a.m.
Sockets form back links in the object graph.  From the object's perspective,
a socket just looks like a pointer to an object.  The socket property type
provides a generic mechanism to set those pointers to other objects while
providing strong type checking.

It's also useful to lock sockets, particularly after realize.  This allows for
an object to enforce that a socket is programmed prior to realize and then not
modified afterwards.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 include/qemu/plug.h |    2 +
 qom/plug.c          |   64 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+), 0 deletions(-)

Patch

diff --git a/include/qemu/plug.h b/include/qemu/plug.h
index fdefa04..a7ca985 100644
--- a/include/qemu/plug.h
+++ b/include/qemu/plug.h
@@ -72,6 +72,8 @@  void plug_add_property_plug(Plug *plug, Plug *value, const char *typename, const
 
 Plug *plug_get_property_plug(Plug *plug, Error **errp, const char *name, ...);
 
+void plug_add_property_socket(Plug *plug, const char *name, Plug **value, const char *typename);
+
 #include "qemu/plug-proptypes.h"
 
 #endif
diff --git a/qom/plug.c b/qom/plug.c
index 725cac2..a9d8154 100644
--- a/qom/plug.c
+++ b/qom/plug.c
@@ -261,6 +261,70 @@  Plug *plug_get_property_plug(Plug *plug, Error **errp, const char *name, ...)
     return value;
 }
 
+typedef struct SocketData
+{
+    const char *typename;
+    Plug **value;
+} SocketData;
+
+static void plug_get_property__socket(Plug *plug, const char *name, Visitor *v, void *opaque, Error **errp)
+{
+    SocketData *data = opaque;
+    const char *value = "";
+
+    if (*data->value) {
+        value = TYPE_INSTANCE(*data->value)->id;
+    }
+
+    visit_type_str(v, (char **)&value, name, errp);
+}
+
+static void plug_set_property__socket(Plug *plug, const char *name, Visitor *v, void *opaque, Error **errp)
+{
+    char *value = NULL;
+    Error *local_err = NULL;
+    SocketData *data = opaque;
+    TypeInstance *obj;
+
+    visit_type_str(v, &value, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    obj = type_find_by_id(value);
+    assert(obj != NULL);
+
+    *data->value = PLUG(type_dynamic_cast_assert(obj, data->typename));
+
+    qemu_free(value);
+}
+
+static void plug_del_property__socket(Plug *plug, const char *name, void *opaque)
+{
+    SocketData *data = opaque;
+
+    qemu_free(data);
+}
+
+void plug_add_property_socket(Plug *plug, const char *name, Plug **value, const char *typename)
+{
+    SocketData *data = qemu_mallocz(sizeof(*data));
+    char fulltype[33];
+
+    data->typename = typename;
+    data->value = value;
+
+    snprintf(fulltype, sizeof(fulltype), "socket<%s>", typename);
+
+    plug_add_property_full(plug, name,
+                           plug_get_property__socket,
+                           plug_set_property__socket,
+                           plug_del_property__socket,
+                           data,
+                           fulltype, PROP_F_READWRITE);
+}
+
 void plug_realize_all(Plug *plug)
 {
     /* This doesn't loop infinitely because the callbacks are only called when