Skip to content

Commit 3d3eaca

Browse files
elmarcoMarkus Armbruster
authored and
Markus Armbruster
committed
qobject: use a QObjectBase_ struct
By moving the base fields to a QObjectBase_, QObject can be a type which also has a 'base' field. This allows writing a generic QOBJECT() macro that will work with any QObject type, including QObject itself. The container_of() macro ensures that the object to cast has a QObjectBase_ base field, giving some type safety guarantees. QObject must have no members but QObjectBase_ base, or else QOBJECT() breaks. QObjectBase_ is not a typedef and uses a trailing underscore to make it obvious it is not for normal use and to avoid potential abuse. Signed-off-by: Marc-André Lureau <[email protected]> Reviewed-by: Eric Blake <[email protected]> Message-Id: <[email protected]> Reviewed-by: Markus Armbruster <[email protected]> Signed-off-by: Markus Armbruster <[email protected]>
1 parent 7ee9edf commit 3d3eaca

File tree

9 files changed

+35
-26
lines changed

9 files changed

+35
-26
lines changed

include/qapi/qmp/qbool.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include "qapi/qmp/qobject.h"
1818

1919
struct QBool {
20-
QObject base;
20+
struct QObjectBase_ base;
2121
bool value;
2222
};
2323

include/qapi/qmp/qdict.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ typedef struct QDictEntry {
2525
} QDictEntry;
2626

2727
struct QDict {
28-
QObject base;
28+
struct QObjectBase_ base;
2929
size_t size;
3030
QLIST_HEAD(,QDictEntry) table[QDICT_BUCKET_MAX];
3131
};

include/qapi/qmp/qlist.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ typedef struct QListEntry {
2222
} QListEntry;
2323

2424
struct QList {
25-
QObject base;
25+
struct QObjectBase_ base;
2626
QTAILQ_HEAD(,QListEntry) head;
2727
};
2828

include/qapi/qmp/qnull.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include "qapi/qmp/qobject.h"
1717

1818
struct QNull {
19-
QObject base;
19+
struct QObjectBase_ base;
2020
};
2121

2222
extern QNull qnull_;

include/qapi/qmp/qnum.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ typedef enum {
4545
* convert under the hood.
4646
*/
4747
struct QNum {
48-
QObject base;
48+
struct QObjectBase_ base;
4949
QNumKind kind;
5050
union {
5151
int64_t i64;

include/qapi/qmp/qobject.h

+20-11
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,21 @@
3434

3535
#include "qapi/qapi-builtin-types.h"
3636

37-
struct QObject {
37+
/* Not for use outside include/qapi/qmp/ */
38+
struct QObjectBase_ {
3839
QType type;
3940
size_t refcnt;
4041
};
4142

42-
/* Get the 'base' part of an object */
43-
#define QOBJECT(obj) (&(obj)->base)
43+
/* this struct must have no other members than base */
44+
struct QObject {
45+
struct QObjectBase_ base;
46+
};
47+
48+
#define QOBJECT(obj) ({ \
49+
typeof(obj) _obj = (obj); \
50+
_obj ? container_of(&(_obj)->base, QObject, base) : NULL; \
51+
})
4452

4553
/* High-level interface for qobject_incref() */
4654
#define QINCREF(obj) \
@@ -68,17 +76,18 @@ QEMU_BUILD_BUG_MSG(QTYPE__MAX != 7,
6876
static inline void qobject_init(QObject *obj, QType type)
6977
{
7078
assert(QTYPE_NONE < type && type < QTYPE__MAX);
71-
obj->refcnt = 1;
72-
obj->type = type;
79+
obj->base.refcnt = 1;
80+
obj->base.type = type;
7381
}
7482

7583
/**
7684
* qobject_incref(): Increment QObject's reference count
7785
*/
7886
static inline void qobject_incref(QObject *obj)
7987
{
80-
if (obj)
81-
obj->refcnt++;
88+
if (obj) {
89+
obj->base.refcnt++;
90+
}
8291
}
8392

8493
/**
@@ -101,8 +110,8 @@ void qobject_destroy(QObject *obj);
101110
*/
102111
static inline void qobject_decref(QObject *obj)
103112
{
104-
assert(!obj || obj->refcnt);
105-
if (obj && --obj->refcnt == 0) {
113+
assert(!obj || obj->base.refcnt);
114+
if (obj && --obj->base.refcnt == 0) {
106115
qobject_destroy(obj);
107116
}
108117
}
@@ -112,8 +121,8 @@ static inline void qobject_decref(QObject *obj)
112121
*/
113122
static inline QType qobject_type(const QObject *obj)
114123
{
115-
assert(QTYPE_NONE < obj->type && obj->type < QTYPE__MAX);
116-
return obj->type;
124+
assert(QTYPE_NONE < obj->base.type && obj->base.type < QTYPE__MAX);
125+
return obj->base.type;
117126
}
118127

119128
/**

include/qapi/qmp/qstring.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include "qapi/qmp/qobject.h"
1717

1818
struct QString {
19-
QObject base;
19+
struct QObjectBase_ base;
2020
char *string;
2121
size_t length;
2222
size_t capacity;

qobject/qobject.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ static void (*qdestroy[QTYPE__MAX])(QObject *) = {
3737

3838
void qobject_destroy(QObject *obj)
3939
{
40-
assert(!obj->refcnt);
41-
assert(QTYPE_QNULL < obj->type && obj->type < QTYPE__MAX);
42-
qdestroy[obj->type](obj);
40+
assert(!obj->base.refcnt);
41+
assert(QTYPE_QNULL < obj->base.type && obj->base.type < QTYPE__MAX);
42+
qdestroy[obj->base.type](obj);
4343
}
4444

4545

@@ -62,11 +62,11 @@ bool qobject_is_equal(const QObject *x, const QObject *y)
6262
return true;
6363
}
6464

65-
if (!x || !y || x->type != y->type) {
65+
if (!x || !y || x->base.type != y->base.type) {
6666
return false;
6767
}
6868

69-
assert(QTYPE_NONE < x->type && x->type < QTYPE__MAX);
69+
assert(QTYPE_NONE < x->base.type && x->base.type < QTYPE__MAX);
7070

71-
return qis_equal[x->type](x, y);
71+
return qis_equal[x->base.type](x, y);
7272
}

tests/check-qdict.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -570,11 +570,11 @@ static void qdict_join_test(void)
570570
}
571571

572572
/* Check the references */
573-
g_assert(qdict_get(dict1, "foo")->refcnt == 1);
574-
g_assert(qdict_get(dict1, "bar")->refcnt == 1);
573+
g_assert(qdict_get(dict1, "foo")->base.refcnt == 1);
574+
g_assert(qdict_get(dict1, "bar")->base.refcnt == 1);
575575

576576
if (!overwrite) {
577-
g_assert(qdict_get(dict2, "foo")->refcnt == 1);
577+
g_assert(qdict_get(dict2, "foo")->base.refcnt == 1);
578578
}
579579

580580
/* Clean up */

0 commit comments

Comments
 (0)