mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
src: make virObject inherit from GObject
To avoid bugs with mixing of g_object_(ref|unref) vs virObject(Ref|Unref), we want every virObject to be a GObject. Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
a771351ae4
commit
d4c71c6725
@ -39,6 +39,7 @@ static unsigned int magicCounter = 0xCAFE0000;
|
|||||||
struct _virClass {
|
struct _virClass {
|
||||||
virClassPtr parent;
|
virClassPtr parent;
|
||||||
|
|
||||||
|
GType type;
|
||||||
unsigned int magic;
|
unsigned int magic;
|
||||||
char *name;
|
char *name;
|
||||||
size_t objectSize;
|
size_t objectSize;
|
||||||
@ -46,25 +47,28 @@ struct _virClass {
|
|||||||
virObjectDisposeCallback dispose;
|
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) \
|
#define VIR_OBJECT_USAGE_PRINT_WARNING(anyobj, objclass) \
|
||||||
do { \
|
do { \
|
||||||
virObjectPtr obj = anyobj; \
|
virObjectPtr obj = anyobj; \
|
||||||
if (VIR_OBJECT_NOTVALID(obj)) { \
|
if (!obj) \
|
||||||
if (!obj) \
|
VIR_WARN("Object cannot be NULL"); \
|
||||||
VIR_WARN("Object cannot be NULL"); \
|
if (VIR_OBJECT_NOTVALID(obj)) \
|
||||||
else \
|
|
||||||
VIR_WARN("Object %p has a bad magic number %X", \
|
|
||||||
obj, obj->u.s.magic); \
|
|
||||||
} else { \
|
|
||||||
VIR_WARN("Object %p (%s) is not a %s instance", \
|
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)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
static virClassPtr virObjectClass;
|
static virClassPtr virObjectClassImpl;
|
||||||
static virClassPtr virObjectLockableClass;
|
static virClassPtr virObjectLockableClass;
|
||||||
static virClassPtr virObjectRWLockableClass;
|
static virClassPtr virObjectRWLockableClass;
|
||||||
|
|
||||||
@ -74,17 +78,17 @@ static void virObjectRWLockableDispose(void *anyobj);
|
|||||||
static int
|
static int
|
||||||
virObjectOnceInit(void)
|
virObjectOnceInit(void)
|
||||||
{
|
{
|
||||||
if (!(virObjectClass = virClassNew(NULL,
|
if (!(virObjectClassImpl = virClassNew(NULL,
|
||||||
"virObject",
|
"virObject",
|
||||||
sizeof(virObject),
|
sizeof(virObject),
|
||||||
0,
|
0,
|
||||||
NULL)))
|
NULL)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!VIR_CLASS_NEW(virObjectLockable, virObjectClass))
|
if (!VIR_CLASS_NEW(virObjectLockable, virObjectClassImpl))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!VIR_CLASS_NEW(virObjectRWLockable, virObjectClass))
|
if (!VIR_CLASS_NEW(virObjectRWLockable, virObjectClassImpl))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -104,7 +108,7 @@ virClassForObject(void)
|
|||||||
if (virObjectInitialize() < 0)
|
if (virObjectInitialize() < 0)
|
||||||
return NULL;
|
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:
|
* virClassNew:
|
||||||
* @parent: the parent class
|
* @parent: the parent class
|
||||||
@ -177,25 +189,26 @@ virClassNew(virClassPtr parent,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VIR_ALLOC(klass) < 0)
|
klass = g_new0(virClass, 1);
|
||||||
goto error;
|
|
||||||
|
|
||||||
klass->parent = parent;
|
klass->parent = parent;
|
||||||
klass->magic = g_atomic_int_add(&magicCounter, 1);
|
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->name = g_strdup(name);
|
||||||
klass->objectSize = objectSize;
|
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;
|
klass->dispose = dispose;
|
||||||
|
|
||||||
return klass;
|
return klass;
|
||||||
|
|
||||||
error:
|
|
||||||
VIR_FREE(klass);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -237,17 +250,13 @@ void *
|
|||||||
virObjectNew(virClassPtr klass)
|
virObjectNew(virClassPtr klass)
|
||||||
{
|
{
|
||||||
virObjectPtr obj = NULL;
|
virObjectPtr obj = NULL;
|
||||||
|
virObjectPrivate *priv;
|
||||||
|
|
||||||
if (VIR_ALLOC_VAR(obj,
|
obj = g_object_new(klass->type, NULL);
|
||||||
char,
|
|
||||||
klass->objectSize - sizeof(virObject)) < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
obj->u.s.magic = klass->magic;
|
priv = vir_object_get_instance_private(obj);
|
||||||
obj->klass = klass;
|
priv->klass = klass;
|
||||||
g_atomic_int_set(&obj->u.s.refs, 1);
|
PROBE(OBJECT_NEW, "obj=%p classname=%s", obj, priv->klass->name);
|
||||||
|
|
||||||
PROBE(OBJECT_NEW, "obj=%p classname=%s", obj, obj->klass->name);
|
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@ -304,6 +313,33 @@ virObjectRWLockableNew(virClassPtr klass)
|
|||||||
return obj;
|
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
|
static void
|
||||||
virObjectLockableDispose(void *anyobj)
|
virObjectLockableDispose(void *anyobj)
|
||||||
@ -340,23 +376,8 @@ virObjectUnref(void *anyobj)
|
|||||||
if (VIR_OBJECT_NOTVALID(obj))
|
if (VIR_OBJECT_NOTVALID(obj))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool lastRef = !!g_atomic_int_dec_and_test(&obj->u.s.refs);
|
g_object_unref(anyobj);
|
||||||
PROBE(OBJECT_UNREF, "obj=%p", obj);
|
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))
|
if (VIR_OBJECT_NOTVALID(obj))
|
||||||
return NULL;
|
return NULL;
|
||||||
g_atomic_int_add(&obj->u.s.refs, 1);
|
|
||||||
|
g_object_ref(obj);
|
||||||
PROBE(OBJECT_REF, "obj=%p", obj);
|
PROBE(OBJECT_REF, "obj=%p", obj);
|
||||||
return anyobj;
|
return anyobj;
|
||||||
}
|
}
|
||||||
@ -539,10 +561,13 @@ virObjectIsClass(void *anyobj,
|
|||||||
virClassPtr klass)
|
virClassPtr klass)
|
||||||
{
|
{
|
||||||
virObjectPtr obj = anyobj;
|
virObjectPtr obj = anyobj;
|
||||||
|
virObjectPrivate *priv;
|
||||||
|
|
||||||
if (VIR_OBJECT_NOTVALID(obj))
|
if (VIR_OBJECT_NOTVALID(obj))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return virClassIsDerivedFrom(obj->klass, klass);
|
priv = vir_object_get_instance_private(obj);
|
||||||
|
return virClassIsDerivedFrom(priv->klass, klass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "virthread.h"
|
#include "virthread.h"
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
typedef struct _virClass virClass;
|
typedef struct _virClass virClass;
|
||||||
typedef virClass *virClassPtr;
|
typedef virClass *virClassPtr;
|
||||||
|
|
||||||
@ -38,22 +40,11 @@ typedef virObjectRWLockable *virObjectRWLockablePtr;
|
|||||||
|
|
||||||
typedef void (*virObjectDisposeCallback)(void *obj);
|
typedef void (*virObjectDisposeCallback)(void *obj);
|
||||||
|
|
||||||
/* Most code should not play with the contents of this struct; however,
|
#define VIR_TYPE_OBJECT vir_object_get_type()
|
||||||
* the struct itself is public so that it can be embedded as the first
|
G_DECLARE_DERIVABLE_TYPE(virObject, vir_object, VIR, OBJECT, GObject);
|
||||||
* field of a subclassed object. */
|
|
||||||
struct _virObject {
|
struct _virObjectClass {
|
||||||
/* Ensure correct alignment of this and all subclasses, even on
|
GObjectClass parent;
|
||||||
* 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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _virObjectLockable {
|
struct _virObjectLockable {
|
||||||
@ -109,8 +100,6 @@ virObjectNew(virClassPtr klass)
|
|||||||
void
|
void
|
||||||
virObjectUnref(void *obj);
|
virObjectUnref(void *obj);
|
||||||
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virObject, virObjectUnref);
|
|
||||||
|
|
||||||
void *
|
void *
|
||||||
virObjectRef(void *obj);
|
virObjectRef(void *obj);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user