qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC v0 1/8] qom: revamp interfaces


From: Peter A. G. Crosthwaite
Subject: [Qemu-devel] [RFC v0 1/8] qom: revamp interfaces
Date: Wed, 13 Jun 2012 19:38:30 +1000

From: Paolo Bonzini <address@hidden>

This commit is composed of several changes:

1) it provides a complete set of macros that serve as building blocks
for the definition of Interface types.

2) make Interface public.  This is because this type serves as the
base class for the actual implementation objects that are returned
by dynamic_cast.  While the type itself need not be subclassed by
clients and in principle could remain opaque, it is useful in helper
macros.

3) Change the definition of Interface, prefixing field names with
"iface_" so that the macros can perform a limited a amount of static
type checking.

4) Add documentation for interfaces.

It doesn't change the interface SList to a type-safe qemu-queue.h
list.  This can be left for later.

Signed-off-by: Paolo Bonzini <address@hidden>
Signed-off-by: Peter A.G. Crosthwaite <address@hidden>
---
 include/qemu/object.h |  110 +++++++++++++++++++++++++++++++++++++++++++++++++
 qom/object.c          |   14 ++----
 2 files changed, 114 insertions(+), 10 deletions(-)

diff --git a/include/qemu/object.h b/include/qemu/object.h
index d93b772..a82be5f 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -186,6 +186,40 @@ typedef struct InterfaceInfo InterfaceInfo;
  * similar to normal types except for the fact that are only defined by
  * their classes and never carry any state.  You can dynamically cast an object
  * to one of its #Interface types and vice versa.
+ *
+ * Interfaces are special in that a cast from or to an interface type returns
+ * a different object pointer than what you pass.  Interface methods typically
+ * pass the whole object as the first argument, rather than the interface.
+ *
+ * <example>
+ *   <title>Defining an interface</title>
+ *   <programlisting>
+ * // An interface has the same basic pieces as a class.
+ * #define TYPE_DMA_PEER "dma-peer"
+ * typedef Interface DMAPeer;
+ * typedef struct DMAPeerIface DMAPeerIface;
+ * struct DMAPeerIface {
+ *     InterfaceClass parent;
+ *     void (*push)(Object *obj, int channel, uint8_t *buf, size_t len);
+ * };
+ *
+ * // Interfaces also define utility macros for casting.
+ * #define DMA_PEER_GET_IFACE(obj) \
+ *    INTERFACE_GET_IFACE(DMAPeerIface, obj, TYPE_DMA_PEER)
+ * #define DMA_PEER_IFACE(klass) \
+ *    INTERFACE_IFACE_CHECK(DMAPeerIface, klass, TYPE_DMA_PEER)
+ * #define DMA_PEER(obj) \
+ *    INTERFACE_CHECK(obj, TYPE_DMA_PEER)
+ *
+ * // This is the wrapper that calls the method.
+ * void dma_push(DMAPeer *peer, int channel, uint8_t *buf, size_t len)
+ * {
+ *     DMAPeerIface *iface = DMA_PEER_GET_IFACE(peer);
+ *
+ *     peer->push(INTERFACE_OBJECT(peer), channel, buf, len);
+ * }
+ *    </programlisting>
+ *  </example>
  */
 
 
@@ -392,6 +426,82 @@ struct InterfaceClass
     ObjectClass parent_class;
 };
 
+typedef struct Interface
+{
+    Object iface_parent;
+    Object *iface_obj;
+} Interface;
+
+/**
+ * INTERFACE_CLASS:
+ * @class: A derivative of #InterfaceClass.
+ *
+ * Converts a class to an #InterfaceClass.  Right now it really has the
+ * same layout as #ObjectClass, so this function will always succeed.
+ * This may change in the future.
+ */
+#define INTERFACE_CLASS(class) \
+    ((InterfaceClass *)(class))
+
+/**
+ * INTERFACE_GET_CLASS:
+ * @class: An interface object (an instance of Interface)
+ *
+ * Retrieve the class object (vtable) of the implementation object for an
+ * interface.  Since all such objects have the same layout, this function
+ * can be statically type-checked and will always succeed.  However, note
+ * that the result is typically passed to an OBJECT_CLASS_CHECK macro,
+ * which actually may fail.
+ */
+#define INTERFACE_GET_CLASS(iface_obj) \
+    INTERFACE_CLASS(object_get_class(&(iface_obj)->iface_parent))
+
+/**
+ * INTERFACE_IFACE_CHECK:
+ * @class: The C type to use for the return value.
+ * @obj: A derivative of @type to cast.
+ * @name: the QOM typename of @class.
+ *
+ * A type safe version of @object_class_dynamic_cast_assert.  This macro is
+ * typically wrapped by each type to perform type safe casts of an interface
+ * to a specific type.
+ */
+#define INTERFACE_IFACE_CHECK(class, obj, name) \
+    OBJECT_CLASS_CHECK(class, obj, name)
+
+/**
+ * INTERFACE_GET_IFACE:
+ * @class: An interface object (an instance of Interface)
+ *
+ * Retrieve the class object (vtable) of the implementation object for an
+ * interface.  This macro is typically wrapped by each type to safely
+ * retrieve a specific vtable from an implementation object.
+ */
+#define INTERFACE_GET_IFACE(iface, obj, type) \
+     INTERFACE_IFACE_CHECK(iface, INTERFACE_GET_CLASS(obj), type)
+
+/**
+ * INTERFACE_CHECK:
+ * @obj: The object to obtain the class for.
+ * @name: The QOM typename of @obj.
+ *
+ * This function will return the specific implementation object for a given
+ * interface.  It's generally used by each type to provide a type safe macro
+ * to get a specific class type from an object.
+ */
+#define INTERFACE_CHECK(obj, name) OBJECT_CHECK(Interface, obj, name)
+
+/**
+ * INTERFACE_OBJECT:
+ * @impl: The interface implementation to obtain the parent object for.
+ *
+ * This function will return the parent object associated to any object
+ * that is an interface implementation.  It expects a pointer to Interface.
+ * Since all interface objects have the same layout, this function can be
+ * statically type-checked and will always succeed.
+ */
+#define INTERFACE_OBJECT(impl)      ((impl)->iface_obj)
+
 /**
  * InterfaceInfo:
  * @type: The name of the interface.
diff --git a/qom/object.c b/qom/object.c
index 6f839ad..e6c3cfb 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -63,13 +63,7 @@ struct TypeImpl
     InterfaceImpl interfaces[MAX_INTERFACES];
 };
 
-typedef struct Interface
-{
-    Object parent;
-    Object *obj;
-} Interface;
-
-#define INTERFACE(obj) OBJECT_CHECK(Interface, obj, TYPE_INTERFACE)
+#define INTERFACE(obj) INTERFACE_CHECK(obj, TYPE_INTERFACE)
 
 static Type type_interface;
 
@@ -251,7 +245,7 @@ static void object_interface_init(Object *obj, 
InterfaceImpl *iface)
     Interface *iface_obj;
 
     iface_obj = INTERFACE(object_new(ti->name));
-    iface_obj->obj = obj;
+    iface_obj->iface_obj = obj;
 
     obj->interfaces = g_slist_prepend(obj->interfaces, iface_obj);
 }
@@ -435,7 +429,7 @@ Object *object_dynamic_cast(Object *obj, const char 
*typename)
      */
     if (object_is_type(obj, type_interface)) {
         assert(!obj->interfaces);
-        obj = INTERFACE(obj)->obj;
+        obj = INTERFACE(obj)->iface_obj;
         if (object_is_type(obj, target_type)) {
             return obj;
         }
@@ -986,7 +980,7 @@ gchar *object_get_canonical_path(Object *obj)
     char *newpath = NULL, *path = NULL;
 
     if (object_is_type(obj, type_interface)) {
-        obj = INTERFACE(obj)->obj;
+        obj = INTERFACE(obj)->iface_obj;
     }
 
     while (obj != root) {
-- 
1.7.3.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]