[libvirt PATCH 6/6] src: make virObject inherit from GObject

Daniel P. Berrangé berrange at redhat.com
Tue May 19 17:41:31 UTC 2020


To avoid bugs with mixing of g_object_(ref|unref) vs
virObject(Ref|Unref), we want every virObject to be
a GObject.

Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
---
 src/util/virobject.c | 141 +++++++++++++++++++++++++------------------
 src/util/virobject.h |  25 +++-----
 2 files changed, 90 insertions(+), 76 deletions(-)

diff --git a/src/util/virobject.c b/src/util/virobject.c
index 4060d7307b..3f0bcc38ea 100644
--- a/src/util/virobject.c
+++ b/src/util/virobject.c
@@ -39,6 +39,7 @@ static unsigned int magicCounter = 0xCAFE0000;
 struct _virClass {
     virClassPtr parent;
 
+    GType type;
     unsigned int magic;
     char *name;
     size_t objectSize;
@@ -46,25 +47,28 @@ struct _virClass {
     virObjectDisposeCallback dispose;
 };
 
-#define VIR_OBJECT_NOTVALID(obj) (!obj || ((obj->u.s.magic & 0xFFFF0000) != 0xCAFE0000))
+typedef struct _virObjectPrivate virObjectPrivate;
+struct _virObjectPrivate {
+    virClassPtr klass;
+};
+
+
+G_DEFINE_TYPE_WITH_PRIVATE(virObject, vir_object, G_TYPE_OBJECT)
+
+#define VIR_OBJECT_NOTVALID(obj) (!obj || !VIR_IS_OBJECT(obj))
 
 #define VIR_OBJECT_USAGE_PRINT_WARNING(anyobj, objclass) \
     do { \
         virObjectPtr obj = anyobj; \
-        if (VIR_OBJECT_NOTVALID(obj)) { \
-            if (!obj) \
-                VIR_WARN("Object cannot be NULL"); \
-            else \
-                VIR_WARN("Object %p has a bad magic number %X", \
-                         obj, obj->u.s.magic); \
-        } else { \
+        if (!obj) \
+            VIR_WARN("Object cannot be NULL"); \
+        if (VIR_OBJECT_NOTVALID(obj)) \
             VIR_WARN("Object %p (%s) is not a %s instance", \
-                     anyobj, obj->klass->name, #objclass); \
-        } \
+                     anyobj, g_type_name_from_instance((void*)anyobj), #objclass); \
     } while (0)
 
 
-static virClassPtr virObjectClass;
+static virClassPtr virObjectClassImpl;
 static virClassPtr virObjectLockableClass;
 static virClassPtr virObjectRWLockableClass;
 
@@ -74,17 +78,17 @@ static void virObjectRWLockableDispose(void *anyobj);
 static int
 virObjectOnceInit(void)
 {
-    if (!(virObjectClass = virClassNew(NULL,
-                                       "virObject",
-                                       sizeof(virObject),
-                                       0,
-                                       NULL)))
+    if (!(virObjectClassImpl = virClassNew(NULL,
+                                           "virObject",
+                                           sizeof(virObject),
+                                           0,
+                                           NULL)))
         return -1;
 
-    if (!VIR_CLASS_NEW(virObjectLockable, virObjectClass))
+    if (!VIR_CLASS_NEW(virObjectLockable, virObjectClassImpl))
         return -1;
 
-    if (!VIR_CLASS_NEW(virObjectRWLockable, virObjectClass))
+    if (!VIR_CLASS_NEW(virObjectRWLockable, virObjectClassImpl))
         return -1;
 
     return 0;
@@ -104,7 +108,7 @@ virClassForObject(void)
     if (virObjectInitialize() < 0)
         return NULL;
 
-    return virObjectClass;
+    return virObjectClassImpl;
 }
 
 
@@ -138,6 +142,14 @@ virClassForObjectRWLockable(void)
 }
 
 
+static void virClassDummyInit(void *klass G_GNUC_UNUSED)
+{
+}
+
+static void virObjectDummyInit(void *obj G_GNUC_UNUSED)
+{
+}
+
 /**
  * virClassNew:
  * @parent: the parent class
@@ -177,25 +189,26 @@ virClassNew(virClassPtr parent,
         return NULL;
     }
 
-    if (VIR_ALLOC(klass) < 0)
-        goto error;
-
+    klass = g_new0(virClass, 1);
     klass->parent = parent;
     klass->magic = g_atomic_int_add(&magicCounter, 1);
-    if (klass->magic > 0xCAFEFFFF) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                       _("too many object classes defined"));
-        goto error;
-    }
     klass->name = g_strdup(name);
     klass->objectSize = objectSize;
+    if (parent == NULL) {
+        klass->type = vir_object_get_type();
+    } else {
+        klass->type =
+            g_type_register_static_simple(parent->type,
+                                          name,
+                                          sizeof(virObjectClass),
+                                          (GClassInitFunc)virClassDummyInit,
+                                          objectSize,
+                                          (GInstanceInitFunc)virObjectDummyInit,
+                                          0);
+    }
     klass->dispose = dispose;
 
     return klass;
-
- error:
-    VIR_FREE(klass);
-    return NULL;
 }
 
 
@@ -237,17 +250,13 @@ void *
 virObjectNew(virClassPtr klass)
 {
     virObjectPtr obj = NULL;
+    virObjectPrivate *priv;
 
-    if (VIR_ALLOC_VAR(obj,
-                      char,
-                      klass->objectSize - sizeof(virObject)) < 0)
-        return NULL;
-
-    obj->u.s.magic = klass->magic;
-    obj->klass = klass;
-    g_atomic_int_set(&obj->u.s.refs, 1);
+    obj = g_object_new(klass->type, NULL);
 
-    PROBE(OBJECT_NEW, "obj=%p classname=%s", obj, obj->klass->name);
+    priv = vir_object_get_instance_private(obj);
+    priv->klass = klass;
+    PROBE(OBJECT_NEW, "obj=%p classname=%s", obj, priv->klass->name);
 
     return obj;
 }
@@ -304,6 +313,33 @@ virObjectRWLockableNew(virClassPtr klass)
     return obj;
 }
 
+static void vir_object_finalize(GObject *gobj)
+{
+    PROBE(OBJECT_DISPOSE, "obj=%p", gobj);
+    virObjectPtr obj = VIR_OBJECT(gobj);
+    virObjectPrivate *priv = vir_object_get_instance_private(obj);
+
+    virClassPtr klass = priv->klass;
+    while (klass) {
+        if (klass->dispose)
+            klass->dispose(obj);
+        klass = klass->parent;
+    }
+
+    G_OBJECT_CLASS(vir_object_parent_class)->finalize(gobj);
+}
+
+static void vir_object_init(virObject *obj G_GNUC_UNUSED)
+{
+}
+
+
+static void vir_object_class_init(virObjectClass *klass)
+{
+    GObjectClass *obj = G_OBJECT_CLASS(klass);
+
+    obj->finalize = vir_object_finalize;
+}
 
 static void
 virObjectLockableDispose(void *anyobj)
@@ -340,23 +376,8 @@ virObjectUnref(void *anyobj)
     if (VIR_OBJECT_NOTVALID(obj))
         return;
 
-    bool lastRef = !!g_atomic_int_dec_and_test(&obj->u.s.refs);
+    g_object_unref(anyobj);
     PROBE(OBJECT_UNREF, "obj=%p", obj);
-    if (lastRef) {
-        PROBE(OBJECT_DISPOSE, "obj=%p", obj);
-        virClassPtr klass = obj->klass;
-        while (klass) {
-            if (klass->dispose)
-                klass->dispose(obj);
-            klass = klass->parent;
-        }
-
-        /* Clear & poison object */
-        memset(obj, 0, obj->klass->objectSize);
-        obj->u.s.magic = 0xDEADBEEF;
-        obj->klass = (void*)0xDEADBEEF;
-        VIR_FREE(obj);
-    }
 }
 
 
@@ -376,7 +397,8 @@ virObjectRef(void *anyobj)
 
     if (VIR_OBJECT_NOTVALID(obj))
         return NULL;
-    g_atomic_int_add(&obj->u.s.refs, 1);
+
+    g_object_ref(obj);
     PROBE(OBJECT_REF, "obj=%p", obj);
     return anyobj;
 }
@@ -539,10 +561,13 @@ virObjectIsClass(void *anyobj,
                  virClassPtr klass)
 {
     virObjectPtr obj = anyobj;
+    virObjectPrivate *priv;
+
     if (VIR_OBJECT_NOTVALID(obj))
         return false;
 
-    return virClassIsDerivedFrom(obj->klass, klass);
+    priv = vir_object_get_instance_private(obj);
+    return virClassIsDerivedFrom(priv->klass, klass);
 }
 
 
diff --git a/src/util/virobject.h b/src/util/virobject.h
index cfedb19b13..18a9f098a6 100644
--- a/src/util/virobject.h
+++ b/src/util/virobject.h
@@ -24,6 +24,8 @@
 #include "internal.h"
 #include "virthread.h"
 
+#include <glib-object.h>
+
 typedef struct _virClass virClass;
 typedef virClass *virClassPtr;
 
@@ -38,22 +40,11 @@ typedef virObjectRWLockable *virObjectRWLockablePtr;
 
 typedef void (*virObjectDisposeCallback)(void *obj);
 
-/* Most code should not play with the contents of this struct; however,
- * the struct itself is public so that it can be embedded as the first
- * field of a subclassed object.  */
-struct _virObject {
-    /* Ensure correct alignment of this and all subclasses, even on
-     * platforms where 'long long' or function pointers have stricter
-     * requirements than 'void *'.  */
-    union {
-        long long dummy_align1;
-        void (*dummy_align2) (void);
-        struct {
-            unsigned int magic;
-            int refs;
-        } s;
-    } u;
-    virClassPtr klass;
+#define VIR_TYPE_OBJECT vir_object_get_type()
+G_DECLARE_DERIVABLE_TYPE(virObject, vir_object, VIR, OBJECT, GObject);
+
+struct _virObjectClass {
+    GObjectClass parent;
 };
 
 struct _virObjectLockable {
@@ -109,8 +100,6 @@ virObjectNew(virClassPtr klass)
 void
 virObjectUnref(void *obj);
 
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(virObject, virObjectUnref);
-
 void *
 virObjectRef(void *obj);
 
-- 
2.24.1




More information about the libvir-list mailing list