From: Eduardo Habkost <ehabkost@redhat.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: "Andreas Färber" <afaerber@suse.de>,
qemu-devel@nongnu.org, "Paolo Bonzini" <pbonzini@redhat.com>,
"Lin Ma" <lma@suse.com>
Subject: Re: [Qemu-devel] [PATCH for-2.9 v2] qom: Make all interface types abstract
Date: Wed, 14 Dec 2016 11:48:41 -0200 [thread overview]
Message-ID: <20161214134841.GG3808@thinpad.lan.raisama.net> (raw)
In-Reply-To: <87zijyfyq5.fsf@dusky.pond.sub.org>
On Wed, Dec 14, 2016 at 02:04:50PM +0100, Markus Armbruster wrote:
> Eduardo Habkost <ehabkost@redhat.com> writes:
>
> > "qom-list-types abstract=false" currently returns all interface
> > types, as if they were not abstract. Fix this by making sure all
> > interface types are abstract.
> >
> > All interface types have instance_size == 0, so we can use
> > it to set abstract=true on type_initialize().
> >
> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > ---
> > Changes v1 -> v2:
> > * Use old-fashioned if statement instead of "|=" on bool field
> > Suggested-by: Andreas Färber <afaerber@suse.de>
> > * Keep "device/introspect" path prefix on unit test
> > * Suggested-by: Andreas Färber <afaerber@suse.de>
> > ---
> > qom/object.c | 6 +++++
> > tests/device-introspect-test.c | 60 +++++++++++++++++++++++++++++++++++++++---
> > 2 files changed, 63 insertions(+), 3 deletions(-)
> >
> > diff --git a/qom/object.c b/qom/object.c
> > index 7a05e35..760fafb 100644
> > --- a/qom/object.c
> > +++ b/qom/object.c
> > @@ -272,6 +272,12 @@ static void type_initialize(TypeImpl *ti)
> >
> > ti->class_size = type_class_get_size(ti);
> > ti->instance_size = type_object_get_size(ti);
> > + /* Any type with zero instance_size is implicitly abstract.
> > + * This means interface types are all abstract.
> > + */
> > + if (ti->instance_size == 0) {
> > + ti->abstract = true;
> > + }
> >
> > ti->class = g_malloc0(ti->class_size);
> >
>
> Letting zero instance_size imply abstract works (I guess), but is it
> wise to imply? Is requiring explicit .abstract = true really too much
> trouble?
>
> Consider:
>
> static const TypeInfo uc_interface_info = {
> .name = TYPE_USER_CREATABLE,
> .parent = TYPE_INTERFACE,
> .class_size = sizeof(UserCreatableClass),
> };
>
> Is this abstract? Yes, because there's no .instance_size = ...,
> therefore .instance_size remains zero, and .abstract defaults to true.
>
> static const TypeInfo memory_region_info = {
> .parent = TYPE_OBJECT,
> .name = TYPE_MEMORY_REGION,
> .instance_size = sizeof(MemoryRegion),
> .instance_init = memory_region_initfn,
> .instance_finalize = memory_region_finalize,
> };
>
> Is this abstract? No, because with .instance_size =
> sizeof(MemoryRegion), which known to be non-zero, .abstract defaults to
> false.
Let's make it worse:
static const TypeInfo palmetto_bmc_type = {
.name = MACHINE_TYPE_NAME("palmetto-bmc"),
.parent = TYPE_MACHINE,
.class_init = palmetto_bmc_class_init,
};
Is this abstract? No, because instance_size from the parent type is used, and
it is not zero.
>
> Is such a complex default a good idea?
>
> static const TypeInfo rng_backend_info = {
> .name = TYPE_RNG_BACKEND,
> .parent = TYPE_OBJECT,
> .instance_size = sizeof(RngBackend),
> .instance_init = rng_backend_init,
> .instance_finalize = rng_backend_finalize,
> .class_size = sizeof(RngBackendClass),
> .class_init = rng_backend_class_init,
> .abstract = true,
> .interfaces = (InterfaceInfo[]) {
> { TYPE_USER_CREATABLE },
> { }
> }
> };
>
> Is this abstract? Yes, because with .abstract = true, the default
> doesn't matter.
>
> How do you find all abstract TypeInfo in the source? The uninitiated
> might grep for .abstract = true, and be misled. The initiated will be
> annoyed instead, because grepping for *absence* of .instance_size = is
> bothersome.
>
> I suspect life could be easier going forward if we instead required
> .abstract = true for interfaces, and enforced it with
> assert(ti->instance_size || ti->abstract) here.
I was doing that before deciding to change type_initialize(). I
think I still have the commit in my git reflog, I will recover it
and submit it as v3.
[...]
> > +static void test_abstract_interfaces(void)
> > +{
> > + QList *all_types;
> > + QList *obj_types;
> > + QListEntry *ae;
> > +
> > + qtest_start(common_args);
> > + /* qom-list-types implements=interface would return any type
> > + * that implements _any_ interface (not just interface types),
> > + * so use a trick to find the interface type names:
> > + * - list all object types
> > + * - list all types, and look for items that are not
> > + * on the first list
> > + */
> > + all_types = qom_list_types(NULL, false);
> > + obj_types = qom_list_types("object", false);
> > +
> > + QLIST_FOREACH_ENTRY(all_types, ae) {
> > + QDict *at = qobject_to_qdict(qlist_entry_obj(ae));
> > + const char *aname = qdict_get_str(at, "name");
> > + QListEntry *oe;
> > + const char *found = NULL;
> > +
> > + QLIST_FOREACH_ENTRY(obj_types, oe) {
> > + QDict *ot = qobject_to_qdict(qlist_entry_obj(oe));
> > + const char *oname = qdict_get_str(ot, "name");
> > + if (!strcmp(aname, oname)) {
> > + found = oname;
> > + break;
> > + }
> > + }
> > +
> > + /* Using g_assert_cmpstr() will give more useful failure
> > + * messages than g_assert(found) */
>
> Sure this comment is worth having?
All we need to check here is if 'found' is not NULL. I think I
would be confused by the usage of g_assert_cmpstr() if I was
reading the code, so I decided to add the comment.
>
> > + g_assert_cmpstr(aname, ==, found);
>
> I'm having a mental block... what exactly is this loop nest testing?
It's implementing the trick described above:
1) list all object types
2) list all types, and look for items that are not on the first
list.
In other words, checking if all items in all_types are present in
obj_types.
My first attempt was to just check if
qom-list-types implements="interface" abstract=false
returned an empty list, but it failed because it returns all
object types that implement any interface.
--
Eduardo
next prev parent reply other threads:[~2016-12-14 13:48 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-12-12 18:31 [Qemu-devel] [PATCH for-2.9 v2] qom: Make all interface types abstract Eduardo Habkost
2016-12-14 13:04 ` Markus Armbruster
2016-12-14 13:48 ` Eduardo Habkost [this message]
2016-12-14 17:07 ` Paolo Bonzini
2016-12-14 17:45 ` Eduardo Habkost
2016-12-14 17:47 ` Markus Armbruster
2016-12-15 13:45 ` Paolo Bonzini
2016-12-19 10:21 ` Markus Armbruster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20161214134841.GG3808@thinpad.lan.raisama.net \
--to=ehabkost@redhat.com \
--cc=afaerber@suse.de \
--cc=armbru@redhat.com \
--cc=lma@suse.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).