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@xxxxxxxxxx> --- 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