Daniel P. Berrangé <berra...@redhat.com> writes: > On Tue, Jan 21, 2020 at 02:36:17PM +0100, Markus Armbruster wrote: >> Marc-André Lureau <marcandre.lur...@gmail.com> writes: >> >> > Hi >> > >> > On Tue, Jan 21, 2020 at 3:32 PM Stefan Hajnoczi <stefa...@gmail.com> wrote: >> >> >> >> On Tue, Jan 21, 2020 at 06:42:47AM +0100, Markus Armbruster wrote: >> >> > Stefan Hajnoczi <stefa...@gmail.com> writes: >> >> > >> >> > > On Wed, Jan 15, 2020 at 01:15:17PM +0100, Markus Armbruster wrote: >> >> > >> Christophe de Dinechin <dinec...@redhat.com> writes: >> >> > >> >> On 15 Jan 2020, at 10:20, Markus Armbruster <arm...@redhat.com> >> >> > >> >> wrote: >> >> > >> * qemuMonitorJSONSetIOThread() uses it to control iothread's >> >> > >> properties >> >> > >> poll-max-ns, poll-grow, poll-shrink. Their use with -object is >> >> > >> documented (in qemu-options.hx), their use with qom-set is not. >> >> > > >> >> > > I'm happy to use a different interface. >> >> > > >> >> > > Writing a boilerplate "iothread-set-poll-params" QMP command in C >> >> > > would >> >> > > be a step backwards. >> >> > >> >> > No argument. >> >> > >> >> > > Maybe the QAPI code generator could map something like this: >> >> > > >> >> > > { 'command': 'iothread-set-poll-params', >> >> > > 'data': { >> >> > > 'id': 'str', >> >> > > '*max-ns': 'uint64', >> >> > > '*grow': 'uint64', >> >> > > '*shrink': 'uint64' >> >> > > }, >> >> > > 'map-to-qom-set': 'IOThread' >> >> > > } >> >> > > >> >> > > And turn it into QOM accessors on the IOThread object. >> >> > >> >> > I think a generic "set this configuration to that value" command is just >> >> > fine. qom-set fails on several counts, though: >> >> > >> >> > * Tolerable: qom-set is not actually generic, it applies only to QOM. >> >> > >> >> > * qom-set lets you set tons of stuff that is not meant to be changed at >> >> > run time. If it breaks your guest, you get to keep the pieces. >> >> > >> >> > * There is virtually no documentation on what can be set to what values, >> >> > and their semantics. >> >> > >> >> > In its current state, QOM is a user interface superfund site. >> >> >> >> Thoughts about a solution: >> >> >> >> Static QOM properties should be declared via QAPI instead of >> >> imperatively via QOM APIs. That way they are introspectable and type >> >> information is present in the schema. >> >> >> >> The QAPI code generator could emit a function that is callable from >> >> .class_init(). This eliminates the need to manually call >> >> object_class_property_add(). >> >> We need to make up our minds what exactly we want generated. Then we >> can design the QAPI language, and code up the generator. >> >> Skeleton QOM type, to help with the discussion: >> >> #define TYPE_FOO "foo" >> >> #define FOO(obj) OBJECT_CHECK(Foo, (obj), TYPE_FOO) >> #define FOO_CLASS(klass) \ >> OBJECT_CLASS_CHECK(FooClass, (klass), TYPE_FOO) >> #define FOO_GET_CLASS(obj) \ >> OBJECT_GET_CLASS(FooClass, (obj), TYPE_FOO) >> >> typedef FooClass { >> ParentClass parent_class; >> ... // hand-written per-class state >> } >> >> struct Chardev { >> ParentObject parent_obj; >> ... // hand-written instance (per-object) state >> }; >> >> static const TypeInfo char_type_info = { >> .name = TYPE_FOO, >> .parent = TYPE_OBJECT, >> .instance_size = sizeof(Foo), >> .instance_init = ..., // methods to initialize >> .instance_post_init = ..., // and finalize instances, >> .instance_finalize = ..., // all optional >> .abstract = ..., // true or false (d'oh) >> .class_size = sizeof(FooClass), >> .class_init = ..., // methods to initialize >> .class_base_init = ..., // classes, optional >> .class_data = ..., // extra argument for them >> .interfaces = ... >> }; >> >> There's substantial boilerplate, with plenty of hand-written code in the >> gaps. What of the boilerplate do we plan to generate? How do we plan >> to fill the gaps, if any? > > FWIW, even without a QOM generator, we can do waaaaaaay better on the > amount of boilerplate needed for QOM without very much work. It just > needs a few convenience macros writing. > > QOM is not GObject, but is heavily inspired by it and so looking at > GObject gives us a design pattern we can aim to match in terms of > amount of boilerplate. > > What we do manually with TypeInfo struct there has essentially always > been done by a 1 line macro in GObject: > > G_DEFINE_TYPE(virIdentity, vir_identity, G_TYPE_OBJECT) > > If implementing interfaces, there's 1 extra line needed per interface > to associate them. > > > https://developer.gnome.org/gobject/stable/gobject-Type-Information.html#G-DEFINE-TYPE:CAPS > > > And what we do in the header file to add the 4 or more FOO_XXX macros, > and the class struct and the object struct has recently been turned > into a 2-liner: > > #define VIR_TYPE_IDENTITY vir_identity_get_type() > G_DECLARE_FINAL_TYPE(virIdentity, vir_identity, VIR, IDENTITY, GObject); > > > https://developer.gnome.org/gobject/stable/gobject-Type-Information.html#G-DECLARE-FINAL-TYPE:CAPS > > Or > > #define VIR_TYPE_IDENTITY vir_identity_get_type() > G_DECLARE_DERIVABLE_TYPE(virIdentity, vir_identity, VIR, IDENTITY, GObject); > > > https://developer.gnome.org/gobject/stable/gobject-Type-Information.html#G-DECLARE-DERIVABLE-TYPE:CAPS > > > It would be nice to have a QOM code generator so that we can statically > declare properties & parent/child/interface relationships, but for an > immediate low cost win, better macros would be very useful IMHO.
Volunteers?