提交 d4c71c67 编写于 作者: D Daniel P. Berrangé

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: NMichal Privoznik <mprivozn@redhat.com>
Signed-off-by: NDaniel P. Berrangé <berrange@redhat.com>
上级 a771351a
......@@ -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);
}
......
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册