From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58851) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZlzTW-0002Jm-Ex for qemu-devel@nongnu.org; Tue, 13 Oct 2015 09:18:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZlzTR-0003c6-3W for qemu-devel@nongnu.org; Tue, 13 Oct 2015 09:18:42 -0400 Received: from mailout3.w1.samsung.com ([210.118.77.13]:21029) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZlzTQ-0003bZ-P3 for qemu-devel@nongnu.org; Tue, 13 Oct 2015 09:18:37 -0400 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout3.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0NW50063EUAVBG40@mailout3.w1.samsung.com> for qemu-devel@nongnu.org; Tue, 13 Oct 2015 14:18:31 +0100 (BST) From: Pavel Fedin References: <1444739866-14798-1-git-send-email-berrange@redhat.com> <1444739866-14798-8-git-send-email-berrange@redhat.com> In-reply-to: <1444739866-14798-8-git-send-email-berrange@redhat.com> Date: Tue, 13 Oct 2015 16:18:28 +0300 Message-id: <013c01d105b9$a6ef8a20$f4ce9e60$@samsung.com> MIME-version: 1.0 Content-type: text/plain; charset=UTF-8 Content-transfer-encoding: quoted-printable Content-language: ru Subject: Re: [Qemu-devel] [PATCH v4 7/7] qom: allow properties to be registered against classes List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: "'Daniel P. Berrange'" , qemu-devel@nongnu.org Cc: 'Paolo Bonzini' , 'Markus Armbruster' , =?UTF-8?Q?'Andreas_F=C3=A4rber'?= Hello! > -----Original Message----- > From: qemu-devel-bounces+p.fedin=3Dsamsung.com@nongnu.org = [mailto:qemu-devel- > bounces+p.fedin=3Dsamsung.com@nongnu.org] On Behalf Of Daniel P. = Berrange > Sent: Tuesday, October 13, 2015 3:38 PM > To: qemu-devel@nongnu.org > Cc: Pavel Fedin; Markus Armbruster; Paolo Bonzini; Andreas F=C3=A4rber > Subject: [Qemu-devel] [PATCH v4 7/7] qom: allow properties to be = registered against classes >=20 > When there are many instances of a given class, registering > properties against the instance is wasteful of resources. The > majority of objects have a statically defined list of possible > properties, so most of the properties are easily registerable > against the class. Only those properties which are conditionally > registered at runtime need be recorded against the klass. >=20 > Registering properties against classes also makes it possible > to provide static introspection of QOM - currently introspection > is only possible after creating an instance of a class, which > severely limits its usefulness. >=20 > This impl only supports simple scalar properties. It does not > attempt to allow child object / link object properties against > the class. There are ways to support those too, but it would > make this patch more complicated, so it is left as an exercise > for the future. >=20 > There is no equivalent to object_property_del provided, since > classes must be immutable once they are defined. >=20 > Signed-off-by: Daniel P. Berrange > --- > include/qom/object.h | 50 ++++++++++ > qom/object.c | 237 = ++++++++++++++++++++++++++++++++++++++++++--- > tests/check-qom-proplist.c | 31 ++++-- > 3 files changed, 293 insertions(+), 25 deletions(-) >=20 > diff --git a/include/qom/object.h b/include/qom/object.h > index 2a54515..38f41d3 100644 > --- a/include/qom/object.h > +++ b/include/qom/object.h > @@ -381,6 +381,8 @@ struct ObjectClass > const char *class_cast_cache[OBJECT_CLASS_CAST_CACHE]; >=20 > ObjectUnparent *unparent; > + > + GHashTable *properties; > }; >=20 > /** > @@ -947,6 +949,13 @@ ObjectProperty *object_property_add(Object *obj, = const char *name, >=20 > void object_property_del(Object *obj, const char *name, Error = **errp); >=20 > +ObjectProperty *object_class_property_add(ObjectClass *klass, const = char *name, > + const char *type, > + ObjectPropertyAccessor = *get, > + ObjectPropertyAccessor = *set, > + ObjectPropertyRelease = *release, > + void *opaque, Error = **errp); > + > /** > * object_property_find: > * @obj: the object > @@ -957,6 +966,8 @@ void object_property_del(Object *obj, const char = *name, Error **errp); > */ > ObjectProperty *object_property_find(Object *obj, const char *name, > Error **errp); > +ObjectProperty *object_class_property_find(ObjectClass *klass, const = char *name, > + Error **errp); >=20 > typedef struct ObjectPropertyIterator ObjectPropertyIterator; >=20 > @@ -964,8 +975,14 @@ typedef struct ObjectPropertyIterator = ObjectPropertyIterator; > * object_property_iter_init: > * @obj: the object > * > +<<<<<<< HEAD > * Initializes an iterator for traversing all properties > * registered against an object instance. > +=3D=3D=3D=3D=3D=3D=3D > + * Iterates over all properties defined against the object > + * instance, its class and all parent classes, calling > + * @iter for each property. > +>>>>>>> 0ca9307... qom: allow properties to be registered against = classes Conflict markers slipped in the comment > * > * It is forbidden to modify the property list while iterating, > * whether removing or adding properties. > @@ -1375,6 +1392,12 @@ void object_property_add_str(Object *obj, const = char *name, > void (*set)(Object *, const char *, = Error **), > Error **errp); >=20 > +void object_class_property_add_str(ObjectClass *klass, const char = *name, > + char *(*get)(Object *, Error **), > + void (*set)(Object *, const char = *, > + Error **), > + Error **errp); > + > /** > * object_property_add_bool: > * @obj: the object to add a property to > @@ -1391,6 +1414,11 @@ void object_property_add_bool(Object *obj, = const char *name, > void (*set)(Object *, bool, Error **), > Error **errp); >=20 > +void object_class_property_add_bool(ObjectClass *klass, const char = *name, > + bool (*get)(Object *, Error **), > + void (*set)(Object *, bool, Error = **), > + Error **errp); > + > /** > * object_property_add_enum: > * @obj: the object to add a property to > @@ -1410,6 +1438,13 @@ void object_property_add_enum(Object *obj, = const char *name, > void (*set)(Object *, int, Error **), > Error **errp); >=20 > +void object_class_property_add_enum(ObjectClass *klass, const char = *name, > + const char *typename, > + const char * const *strings, > + int (*get)(Object *, Error **), > + void (*set)(Object *, int, Error = **), > + Error **errp); > + > /** > * object_property_add_tm: > * @obj: the object to add a property to > @@ -1424,6 +1459,10 @@ void object_property_add_tm(Object *obj, const = char *name, > void (*get)(Object *, struct tm *, Error = **), > Error **errp); >=20 > +void object_class_property_add_tm(ObjectClass *klass, const char = *name, > + void (*get)(Object *, struct tm *, = Error **), > + Error **errp); > + > /** > * object_property_add_uint8_ptr: > * @obj: the object to add a property to > @@ -1436,6 +1475,8 @@ void object_property_add_tm(Object *obj, const = char *name, > */ > void object_property_add_uint8_ptr(Object *obj, const char *name, > const uint8_t *v, Error **errp); > +void object_class_property_add_uint8_ptr(ObjectClass *klass, const = char *name, > + const uint8_t *v, Error = **errp); >=20 > /** > * object_property_add_uint16_ptr: > @@ -1449,6 +1490,8 @@ void object_property_add_uint8_ptr(Object *obj, = const char *name, > */ > void object_property_add_uint16_ptr(Object *obj, const char *name, > const uint16_t *v, Error **errp); > +void object_class_property_add_uint16_ptr(ObjectClass *klass, const = char *name, > + const uint16_t *v, Error = **errp); >=20 > /** > * object_property_add_uint32_ptr: > @@ -1462,6 +1505,8 @@ void object_property_add_uint16_ptr(Object *obj, = const char *name, > */ > void object_property_add_uint32_ptr(Object *obj, const char *name, > const uint32_t *v, Error **errp); > +void object_class_property_add_uint32_ptr(ObjectClass *klass, const = char *name, > + const uint32_t *v, Error = **errp); >=20 > /** > * object_property_add_uint64_ptr: > @@ -1475,6 +1520,8 @@ void object_property_add_uint32_ptr(Object *obj, = const char *name, > */ > void object_property_add_uint64_ptr(Object *obj, const char *name, > const uint64_t *v, Error **Errp); > +void object_class_property_add_uint64_ptr(ObjectClass *klass, const = char *name, > + const uint64_t *v, Error = **Errp); >=20 > /** > * object_property_add_alias: > @@ -1526,6 +1573,9 @@ void object_property_add_const_link(Object *obj, = const char *name, > */ > void object_property_set_description(Object *obj, const char *name, > const char *description, Error = **errp); > +void object_class_property_set_description(ObjectClass *klass, const = char *name, > + const char *description, > + Error **errp); >=20 > /** > * object_child_foreach: > diff --git a/qom/object.c b/qom/object.c > index dd01652..f41edf4 100644 > --- a/qom/object.c > +++ b/qom/object.c > @@ -68,6 +68,7 @@ struct TypeImpl > }; >=20 > struct ObjectPropertyIterator { > + ObjectClass *nextclass; > GHashTableIter iter; > }; >=20 > @@ -246,6 +247,16 @@ static void type_initialize_interface(TypeImpl = *ti, TypeImpl > *interface_type, > iface_impl->class); > } >=20 > +static void property_free(gpointer data) > +{ > + ObjectProperty *prop =3D data; > + > + g_free(prop->name); > + g_free(prop->type); > + g_free(prop->description); > + g_free(prop); > +} > + > static void type_initialize(TypeImpl *ti) > { > TypeImpl *parent; > @@ -268,6 +279,8 @@ static void type_initialize(TypeImpl *ti) > g_assert(parent->class_size <=3D ti->class_size); > memcpy(ti->class, parent->class, parent->class_size); > ti->class->interfaces =3D NULL; > + ti->class->properties =3D g_hash_table_new_full( > + g_str_hash, g_str_equal, g_free, property_free); >=20 > for (e =3D parent->class->interfaces; e; e =3D e->next) { > InterfaceClass *iface =3D e->data; > @@ -292,6 +305,9 @@ static void type_initialize(TypeImpl *ti) >=20 > type_initialize_interface(ti, t, t); > } > + } else { > + ti->class->properties =3D g_hash_table_new_full( > + g_str_hash, g_str_equal, g_free, property_free); > } >=20 > ti->class->type =3D ti; > @@ -330,16 +346,6 @@ static void object_post_init_with_type(Object = *obj, TypeImpl *ti) > } > } >=20 > -static void property_free(gpointer data) > -{ > - ObjectProperty *prop =3D data; > - > - g_free(prop->name); > - g_free(prop->type); > - g_free(prop->description); > - g_free(prop); > -} > - > void object_initialize_with_type(void *data, size_t size, TypeImpl = *type) > { > Object *obj =3D data; > @@ -902,10 +908,11 @@ object_property_add(Object *obj, const char = *name, const char *type, > return ret; > } >=20 > - if (g_hash_table_contains(obj->properties, name)) { > + > + if (object_property_find(obj, name, NULL) !=3D NULL) { > error_setg(errp, "attempt to add duplicate property '%s'" > - " to object (type '%s')", name, > - object_get_typename(obj)); > + " to object (type '%s')", name, > + object_get_typename(obj)); > return NULL; > } >=20 > @@ -923,10 +930,50 @@ object_property_add(Object *obj, const char = *name, const char *type, > return prop; > } >=20 > +ObjectProperty * > +object_class_property_add(ObjectClass *klass, > + const char *name, > + const char *type, > + ObjectPropertyAccessor *get, > + ObjectPropertyAccessor *set, > + ObjectPropertyRelease *release, > + void *opaque, > + Error **errp) > +{ > + ObjectProperty *prop; > + > + if (object_class_property_find(klass, name, NULL) !=3D NULL) { > + error_setg(errp, "attempt to add duplicate property '%s'" > + " to object (type '%s')", name, > + object_class_get_name(klass)); > + return NULL; > + } > + > + prop =3D g_malloc0(sizeof(*prop)); > + > + prop->name =3D g_strdup(name); > + prop->type =3D g_strdup(type); > + > + prop->get =3D get; > + prop->set =3D set; > + prop->release =3D release; > + prop->opaque =3D opaque; > + > + g_hash_table_insert(klass->properties, g_strdup(name), prop); > + > + return prop; > +} > + > ObjectProperty *object_property_find(Object *obj, const char *name, > Error **errp) > { > ObjectProperty *prop; > + ObjectClass *klass =3D object_get_class(obj); > + > + prop =3D object_class_property_find(klass, name, NULL); > + if (prop) { > + return prop; > + } >=20 > prop =3D g_hash_table_lookup(obj->properties, name); > if (prop) { > @@ -941,6 +988,7 @@ ObjectPropertyIterator = *object_property_iter_init(Object *obj) > { > ObjectPropertyIterator *ret =3D g_new0(ObjectPropertyIterator, = 1); > g_hash_table_iter_init(&ret->iter, obj->properties); > + ret->nextclass =3D object_get_class(obj); > return ret; > } >=20 > @@ -957,12 +1005,37 @@ void = object_property_iter_free(ObjectPropertyIterator *iter) > ObjectProperty *object_property_iter_next(ObjectPropertyIterator = *iter) > { > gpointer key, val; > - if (!g_hash_table_iter_next(&iter->iter, &key, &val)) { > - return NULL; > + while (!g_hash_table_iter_next(&iter->iter, &key, &val)) { > + if (!iter->nextclass) { > + return NULL; > + } > + g_hash_table_iter_init(&iter->iter, = iter->nextclass->properties); > + iter->nextclass =3D object_class_get_parent(iter->nextclass); > } > return val; > } >=20 > +ObjectProperty *object_class_property_find(ObjectClass *klass, const = char *name, > + Error **errp) > +{ > + ObjectProperty *prop; > + ObjectClass *parent_klass; > + > + parent_klass =3D object_class_get_parent(klass); > + if (parent_klass) { > + prop =3D object_class_property_find(parent_klass, name, = NULL); > + if (prop) { > + return prop; > + } > + } > + > + prop =3D g_hash_table_lookup(klass->properties, name); > + if (!prop) { > + error_setg(errp, "Property '.%s' not found", name); > + } > + return prop; > +} > + >=20 > void object_property_del(Object *obj, const char *name, Error **errp) > { > @@ -1717,6 +1790,29 @@ void object_property_add_str(Object *obj, const = char *name, > } > } >=20 > +void object_class_property_add_str(ObjectClass *klass, const char = *name, > + char *(*get)(Object *, Error **), > + void (*set)(Object *, const char = *, > + Error **), > + Error **errp) > +{ > + Error *local_err =3D NULL; > + StringProperty *prop =3D g_malloc0(sizeof(*prop)); > + > + prop->get =3D get; > + prop->set =3D set; > + > + object_class_property_add(klass, name, "string", > + get ? property_get_str : NULL, > + set ? property_set_str : NULL, > + property_release_str, > + prop, &local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + g_free(prop); > + } > +} > + > typedef struct BoolProperty > { > bool (*get)(Object *, Error **); > @@ -1784,6 +1880,28 @@ void object_property_add_bool(Object *obj, = const char *name, > } > } >=20 > +void object_class_property_add_bool(ObjectClass *klass, const char = *name, > + bool (*get)(Object *, Error **), > + void (*set)(Object *, bool, Error = **), > + Error **errp) > +{ > + Error *local_err =3D NULL; > + BoolProperty *prop =3D g_malloc0(sizeof(*prop)); > + > + prop->get =3D get; > + prop->set =3D set; > + > + object_class_property_add(klass, name, "bool", > + get ? property_get_bool : NULL, > + set ? property_set_bool : NULL, > + property_release_bool, > + prop, &local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + g_free(prop); > + } > +} > + > static void property_get_enum(Object *obj, Visitor *v, void *opaque, > const char *name, Error **errp) > { > @@ -1847,6 +1965,31 @@ void object_property_add_enum(Object *obj, = const char *name, > } > } >=20 > +void object_class_property_add_enum(ObjectClass *klass, const char = *name, > + const char *typename, > + const char * const *strings, > + int (*get)(Object *, Error **), > + void (*set)(Object *, int, Error = **), > + Error **errp) > +{ > + Error *local_err =3D NULL; > + EnumProperty *prop =3D g_malloc(sizeof(*prop)); > + > + prop->strings =3D strings; > + prop->get =3D get; > + prop->set =3D set; > + > + object_class_property_add(klass, name, typename, > + get ? property_get_enum : NULL, > + set ? property_set_enum : NULL, > + property_release_enum, > + prop, &local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + g_free(prop); > + } > +} > + > typedef struct TMProperty { > void (*get)(Object *, struct tm *, Error **); > } TMProperty; > @@ -1926,6 +2069,25 @@ void object_property_add_tm(Object *obj, const = char *name, > } > } >=20 > +void object_class_property_add_tm(ObjectClass *klass, const char = *name, > + void (*get)(Object *, struct tm *, = Error **), > + Error **errp) > +{ > + Error *local_err =3D NULL; > + TMProperty *prop =3D g_malloc0(sizeof(*prop)); > + > + prop->get =3D get; > + > + object_class_property_add(klass, name, "struct tm", > + get ? property_get_tm : NULL, NULL, > + property_release_tm, > + prop, &local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + g_free(prop); > + } > +} > + > static char *qdev_get_type(Object *obj, Error **errp) > { > return g_strdup(object_get_typename(obj)); > @@ -1970,6 +2132,13 @@ void object_property_add_uint8_ptr(Object *obj, = const char *name, > NULL, NULL, (void *)v, errp); > } >=20 > +void object_class_property_add_uint8_ptr(ObjectClass *klass, const = char *name, > + const uint8_t *v, Error = **errp) > +{ > + object_class_property_add(klass, name, "uint8", = property_get_uint8_ptr, > + NULL, NULL, (void *)v, errp); > +} > + > void object_property_add_uint16_ptr(Object *obj, const char *name, > const uint16_t *v, Error **errp) > { > @@ -1977,6 +2146,13 @@ void object_property_add_uint16_ptr(Object = *obj, const char *name, > NULL, NULL, (void *)v, errp); > } >=20 > +void object_class_property_add_uint16_ptr(ObjectClass *klass, const = char *name, > + const uint16_t *v, Error = **errp) > +{ > + object_class_property_add(klass, name, "uint16", = property_get_uint16_ptr, > + NULL, NULL, (void *)v, errp); > +} > + > void object_property_add_uint32_ptr(Object *obj, const char *name, > const uint32_t *v, Error **errp) > { > @@ -1984,6 +2160,13 @@ void object_property_add_uint32_ptr(Object = *obj, const char *name, > NULL, NULL, (void *)v, errp); > } >=20 > +void object_class_property_add_uint32_ptr(ObjectClass *klass, const = char *name, > + const uint32_t *v, Error = **errp) > +{ > + object_class_property_add(klass, name, "uint32", = property_get_uint32_ptr, > + NULL, NULL, (void *)v, errp); > +} > + > void object_property_add_uint64_ptr(Object *obj, const char *name, > const uint64_t *v, Error **errp) > { > @@ -1991,6 +2174,13 @@ void object_property_add_uint64_ptr(Object = *obj, const char *name, > NULL, NULL, (void *)v, errp); > } >=20 > +void object_class_property_add_uint64_ptr(ObjectClass *klass, const = char *name, > + const uint64_t *v, Error = **errp) > +{ > + object_class_property_add(klass, name, "uint64", = property_get_uint64_ptr, > + NULL, NULL, (void *)v, errp); > +} > + > typedef struct { > Object *target_obj; > char *target_name; > @@ -2088,6 +2278,23 @@ void object_property_set_description(Object = *obj, const char *name, > op->description =3D g_strdup(description); > } >=20 > +void object_class_property_set_description(ObjectClass *klass, > + const char *name, > + const char *description, > + Error **errp) > +{ > + ObjectProperty *op; > + > + op =3D g_hash_table_lookup(klass->properties, name); > + if (!op) { > + error_setg(errp, "Property '.%s' not found", name); > + return; > + } > + > + g_free(op->description); > + op->description =3D g_strdup(description); > +} > + > static void object_instance_init(Object *obj) > { > object_property_add_str(obj, "type", qdev_get_type, NULL, NULL); > diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c > index 1be8b9e..87de80b 100644 > --- a/tests/check-qom-proplist.c > +++ b/tests/check-qom-proplist.c > @@ -123,18 +123,28 @@ static void dummy_init(Object *obj) > dummy_get_bv, > dummy_set_bv, > NULL); > - object_property_add_str(obj, "sv", > - dummy_get_sv, > - dummy_set_sv, > - NULL); > - object_property_add_enum(obj, "av", > - "DummyAnimal", > - dummy_animal_map, > - dummy_get_av, > - dummy_set_av, > - NULL); > } >=20 > + > +static void dummy_class_init(ObjectClass *cls, void *data) > +{ > + object_class_property_add_bool(cls, "bv", > + dummy_get_bv, > + dummy_set_bv, > + NULL); > + object_class_property_add_str(cls, "sv", > + dummy_get_sv, > + dummy_set_sv, > + NULL); > + object_class_property_add_enum(cls, "av", > + "DummyAnimal", > + dummy_animal_map, > + dummy_get_av, > + dummy_set_av, > + NULL); > +} > + > + > static void dummy_finalize(Object *obj) > { > DummyObject *dobj =3D DUMMY_OBJECT(obj); > @@ -150,6 +160,7 @@ static const TypeInfo dummy_info =3D { > .instance_init =3D dummy_init, > .instance_finalize =3D dummy_finalize, > .class_size =3D sizeof(DummyObjectClass), > + .class_init =3D dummy_class_init, > }; >=20 > static void test_dummy_createv(void) > -- > 2.4.3 Kind regards, Pavel Fedin Expert Engineer Samsung Electronics Research center Russia