Skip to content

Commit d4c71c6

Browse files
committed
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 <[email protected]> Signed-off-by: Daniel P. Berrangé <[email protected]>
1 parent a771351 commit d4c71c6

File tree

2 files changed

+90
-76
lines changed

2 files changed

+90
-76
lines changed

src/util/virobject.c

+83-58
Original file line numberDiff line numberDiff line change
@@ -39,32 +39,36 @@ static unsigned int magicCounter = 0xCAFE0000;
3939
struct _virClass {
4040
virClassPtr parent;
4141

42+
GType type;
4243
unsigned int magic;
4344
char *name;
4445
size_t objectSize;
4546

4647
virObjectDisposeCallback dispose;
4748
};
4849

49-
#define VIR_OBJECT_NOTVALID(obj) (!obj || ((obj->u.s.magic & 0xFFFF0000) != 0xCAFE0000))
50+
typedef struct _virObjectPrivate virObjectPrivate;
51+
struct _virObjectPrivate {
52+
virClassPtr klass;
53+
};
54+
55+
56+
G_DEFINE_TYPE_WITH_PRIVATE(virObject, vir_object, G_TYPE_OBJECT)
57+
58+
#define VIR_OBJECT_NOTVALID(obj) (!obj || !VIR_IS_OBJECT(obj))
5059

5160
#define VIR_OBJECT_USAGE_PRINT_WARNING(anyobj, objclass) \
5261
do { \
5362
virObjectPtr obj = anyobj; \
54-
if (VIR_OBJECT_NOTVALID(obj)) { \
55-
if (!obj) \
56-
VIR_WARN("Object cannot be NULL"); \
57-
else \
58-
VIR_WARN("Object %p has a bad magic number %X", \
59-
obj, obj->u.s.magic); \
60-
} else { \
63+
if (!obj) \
64+
VIR_WARN("Object cannot be NULL"); \
65+
if (VIR_OBJECT_NOTVALID(obj)) \
6166
VIR_WARN("Object %p (%s) is not a %s instance", \
62-
anyobj, obj->klass->name, #objclass); \
63-
} \
67+
anyobj, g_type_name_from_instance((void*)anyobj), #objclass); \
6468
} while (0)
6569

6670

67-
static virClassPtr virObjectClass;
71+
static virClassPtr virObjectClassImpl;
6872
static virClassPtr virObjectLockableClass;
6973
static virClassPtr virObjectRWLockableClass;
7074

@@ -74,17 +78,17 @@ static void virObjectRWLockableDispose(void *anyobj);
7478
static int
7579
virObjectOnceInit(void)
7680
{
77-
if (!(virObjectClass = virClassNew(NULL,
78-
"virObject",
79-
sizeof(virObject),
80-
0,
81-
NULL)))
81+
if (!(virObjectClassImpl = virClassNew(NULL,
82+
"virObject",
83+
sizeof(virObject),
84+
0,
85+
NULL)))
8286
return -1;
8387

84-
if (!VIR_CLASS_NEW(virObjectLockable, virObjectClass))
88+
if (!VIR_CLASS_NEW(virObjectLockable, virObjectClassImpl))
8589
return -1;
8690

87-
if (!VIR_CLASS_NEW(virObjectRWLockable, virObjectClass))
91+
if (!VIR_CLASS_NEW(virObjectRWLockable, virObjectClassImpl))
8892
return -1;
8993

9094
return 0;
@@ -104,7 +108,7 @@ virClassForObject(void)
104108
if (virObjectInitialize() < 0)
105109
return NULL;
106110

107-
return virObjectClass;
111+
return virObjectClassImpl;
108112
}
109113

110114

@@ -138,6 +142,14 @@ virClassForObjectRWLockable(void)
138142
}
139143

140144

145+
static void virClassDummyInit(void *klass G_GNUC_UNUSED)
146+
{
147+
}
148+
149+
static void virObjectDummyInit(void *obj G_GNUC_UNUSED)
150+
{
151+
}
152+
141153
/**
142154
* virClassNew:
143155
* @parent: the parent class
@@ -177,25 +189,26 @@ virClassNew(virClassPtr parent,
177189
return NULL;
178190
}
179191

180-
if (VIR_ALLOC(klass) < 0)
181-
goto error;
182-
192+
klass = g_new0(virClass, 1);
183193
klass->parent = parent;
184194
klass->magic = g_atomic_int_add(&magicCounter, 1);
185-
if (klass->magic > 0xCAFEFFFF) {
186-
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
187-
_("too many object classes defined"));
188-
goto error;
189-
}
190195
klass->name = g_strdup(name);
191196
klass->objectSize = objectSize;
197+
if (parent == NULL) {
198+
klass->type = vir_object_get_type();
199+
} else {
200+
klass->type =
201+
g_type_register_static_simple(parent->type,
202+
name,
203+
sizeof(virObjectClass),
204+
(GClassInitFunc)virClassDummyInit,
205+
objectSize,
206+
(GInstanceInitFunc)virObjectDummyInit,
207+
0);
208+
}
192209
klass->dispose = dispose;
193210

194211
return klass;
195-
196-
error:
197-
VIR_FREE(klass);
198-
return NULL;
199212
}
200213

201214

@@ -237,17 +250,13 @@ void *
237250
virObjectNew(virClassPtr klass)
238251
{
239252
virObjectPtr obj = NULL;
253+
virObjectPrivate *priv;
240254

241-
if (VIR_ALLOC_VAR(obj,
242-
char,
243-
klass->objectSize - sizeof(virObject)) < 0)
244-
return NULL;
245-
246-
obj->u.s.magic = klass->magic;
247-
obj->klass = klass;
248-
g_atomic_int_set(&obj->u.s.refs, 1);
255+
obj = g_object_new(klass->type, NULL);
249256

250-
PROBE(OBJECT_NEW, "obj=%p classname=%s", obj, obj->klass->name);
257+
priv = vir_object_get_instance_private(obj);
258+
priv->klass = klass;
259+
PROBE(OBJECT_NEW, "obj=%p classname=%s", obj, priv->klass->name);
251260

252261
return obj;
253262
}
@@ -304,6 +313,33 @@ virObjectRWLockableNew(virClassPtr klass)
304313
return obj;
305314
}
306315

316+
static void vir_object_finalize(GObject *gobj)
317+
{
318+
PROBE(OBJECT_DISPOSE, "obj=%p", gobj);
319+
virObjectPtr obj = VIR_OBJECT(gobj);
320+
virObjectPrivate *priv = vir_object_get_instance_private(obj);
321+
322+
virClassPtr klass = priv->klass;
323+
while (klass) {
324+
if (klass->dispose)
325+
klass->dispose(obj);
326+
klass = klass->parent;
327+
}
328+
329+
G_OBJECT_CLASS(vir_object_parent_class)->finalize(gobj);
330+
}
331+
332+
static void vir_object_init(virObject *obj G_GNUC_UNUSED)
333+
{
334+
}
335+
336+
337+
static void vir_object_class_init(virObjectClass *klass)
338+
{
339+
GObjectClass *obj = G_OBJECT_CLASS(klass);
340+
341+
obj->finalize = vir_object_finalize;
342+
}
307343

308344
static void
309345
virObjectLockableDispose(void *anyobj)
@@ -340,23 +376,8 @@ virObjectUnref(void *anyobj)
340376
if (VIR_OBJECT_NOTVALID(obj))
341377
return;
342378

343-
bool lastRef = !!g_atomic_int_dec_and_test(&obj->u.s.refs);
379+
g_object_unref(anyobj);
344380
PROBE(OBJECT_UNREF, "obj=%p", obj);
345-
if (lastRef) {
346-
PROBE(OBJECT_DISPOSE, "obj=%p", obj);
347-
virClassPtr klass = obj->klass;
348-
while (klass) {
349-
if (klass->dispose)
350-
klass->dispose(obj);
351-
klass = klass->parent;
352-
}
353-
354-
/* Clear & poison object */
355-
memset(obj, 0, obj->klass->objectSize);
356-
obj->u.s.magic = 0xDEADBEEF;
357-
obj->klass = (void*)0xDEADBEEF;
358-
VIR_FREE(obj);
359-
}
360381
}
361382

362383

@@ -376,7 +397,8 @@ virObjectRef(void *anyobj)
376397

377398
if (VIR_OBJECT_NOTVALID(obj))
378399
return NULL;
379-
g_atomic_int_add(&obj->u.s.refs, 1);
400+
401+
g_object_ref(obj);
380402
PROBE(OBJECT_REF, "obj=%p", obj);
381403
return anyobj;
382404
}
@@ -539,10 +561,13 @@ virObjectIsClass(void *anyobj,
539561
virClassPtr klass)
540562
{
541563
virObjectPtr obj = anyobj;
564+
virObjectPrivate *priv;
565+
542566
if (VIR_OBJECT_NOTVALID(obj))
543567
return false;
544568

545-
return virClassIsDerivedFrom(obj->klass, klass);
569+
priv = vir_object_get_instance_private(obj);
570+
return virClassIsDerivedFrom(priv->klass, klass);
546571
}
547572

548573

src/util/virobject.h

+7-18
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include "internal.h"
2525
#include "virthread.h"
2626

27+
#include <glib-object.h>
28+
2729
typedef struct _virClass virClass;
2830
typedef virClass *virClassPtr;
2931

@@ -38,22 +40,11 @@ typedef virObjectRWLockable *virObjectRWLockablePtr;
3840

3941
typedef void (*virObjectDisposeCallback)(void *obj);
4042

41-
/* Most code should not play with the contents of this struct; however,
42-
* the struct itself is public so that it can be embedded as the first
43-
* field of a subclassed object. */
44-
struct _virObject {
45-
/* Ensure correct alignment of this and all subclasses, even on
46-
* platforms where 'long long' or function pointers have stricter
47-
* requirements than 'void *'. */
48-
union {
49-
long long dummy_align1;
50-
void (*dummy_align2) (void);
51-
struct {
52-
unsigned int magic;
53-
int refs;
54-
} s;
55-
} u;
56-
virClassPtr klass;
43+
#define VIR_TYPE_OBJECT vir_object_get_type()
44+
G_DECLARE_DERIVABLE_TYPE(virObject, vir_object, VIR, OBJECT, GObject);
45+
46+
struct _virObjectClass {
47+
GObjectClass parent;
5748
};
5849

5950
struct _virObjectLockable {
@@ -109,8 +100,6 @@ virObjectNew(virClassPtr klass)
109100
void
110101
virObjectUnref(void *obj);
111102

112-
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virObject, virObjectUnref);
113-
114103
void *
115104
virObjectRef(void *obj);
116105

0 commit comments

Comments
 (0)