提交 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; ...@@ -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 { ...@@ -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); ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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 * ...@@ -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;
obj->klass = klass;
g_atomic_int_set(&obj->u.s.refs, 1);
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; return obj;
} }
...@@ -304,6 +313,33 @@ virObjectRWLockableNew(virClassPtr klass) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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 @@ ...@@ -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; ...@@ -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) ...@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册