qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: Anthony Liguori <aliguori@us.ibm.com>
Cc: qemu-devel@nongnu.org, Markus Armbruster <armbru@redhat.com>
Subject: Re: [Qemu-devel] [PATCH 01/27] qom: add the base Object class
Date: Wed, 21 Dec 2011 16:28:41 +0100	[thread overview]
Message-ID: <4EF1FB29.40504@redhat.com> (raw)
In-Reply-To: <4EF1EEA4.40209@us.ibm.com>

On 12/21/2011 03:35 PM, Anthony Liguori wrote:
>>> +Type type_register_static(const TypeInfo *info)
>>> +{
>>> + Type type = num_types++;
>>> + TypeImpl *ti;
>>> +
>>> + ti =&type_table[type];
>>> +
>>> + assert(info->name != NULL);
>>> +
>>> + printf("Added type %s -> %s\n", info->name, info->parent);
>>> +
>>> + ti->name = info->name;
>>
>> Why no strdup here?
>
> 'static' means that the strings are const char *.

Sure, but if you later want to unregister, the ownership of ->name and 
->parent need to be the same for all paths.  In this case 
type_register_anonymous makes it "owned by object.c" and 
type_register_static makes it "owned by caller".

>>> + ti->parent = info->parent;
>>
>> Please store a Type or a pointer to TypeImpl.
>
> It needs to be a symbolic name because the TypeImpl may not exist yet
> since we can't guarantee registration order.
>
> This ends up being a tremendous simplification because we don't have to
> care about type registration order.

Got it now.  However, let's cache the Type as soon as we resolve it the 
first time.

>> Otherwise, I don't see the need to
>> distinguish TypeInfo/InterfaceInfo and TypeImpl/InterfaceImpl at all.
>> The only
>> difference is num_interfaces, and
>>
>> for (i = 0; i < ti->num_interfaces; i++) {
>>
>> can be replaced just as well with
>>
>> for (i = 0; i < ti->interfaces[i].type; i++) {
>
> InterfaceInfo is specifically limited in what it contains to prevent
> someone from shooting themselves in the foot. It may be possible to just
> use TypeImpl in the backend but we should keep InterfaceInfo limited.

Let's keep Impl/Info separate, but use the difference so that we can 
cache name->type mappings as much as possible.

>>> + return type;
>>
>> The return value is unused. Looks like a premature optimization or a
>> leftover
>> from GObject.
>
> It will be used to allow type unregistration. Think about dynamic
> loadable/unloadable modules.

Ack.

>>> + for (i = 1; i< num_types; i++) {
>>> + if (strcmp(name, type_table[i].name) == 0) {
>>> + return i;
>>> + }
>>> + }
>>
>> Please use a hash table here. Ultimately object creation might be
>> in hot paths. For example I would like to turn SCSIRequests into
>> QOM objects. It would let me reuse the reference counting as well
>> as help with migration.
>
> Ack.
>
>> But in any case, this function should be called as little as
>> possible, and should not be static in case other places want to
>> cache the outcome.
>
> Hrm, I don't think it should ever be used outside of object.c. What are
> you thinking re: caching.

I'm thinking of using

>>> +static void object_interface_init(Object *obj, InterfaceImpl *iface)
>>> +{
>>> + TypeImpl *ti = type_get_instance(iface->type);
>>> + Interface *iface_obj;
>>> +
>>> + iface_obj = INTERFACE(object_new(ti->name));
>>> + iface_obj->obj = obj;
>>> +
>>> + obj->interfaces = g_slist_prepend(obj->interfaces, iface_obj);
>>
>> Please use a QSIMPLEQ.
>
> I saw your github comment and looked at it. Turns out, Interface
> shouldn't be public at all (because you only ever subclass
> InterfaceClass, never Interface).

I agree that Interface and INTERFACE() should be private to object.c, 
but it's not a big deal to leave them as opaque in object.h.  Leaving 
Interface as an opaque type is enough in order to use QSIMPLEQ.

>>> +void object_initialize(void *data, const char *typename)
>>> +{
>>> + TypeImpl *ti = type_get_instance(type_get_by_name(typename));
>>
>> I should be able to pass directly a Type (or a TypeImpl, whatever
>> happens of my
>> suggestion above) here.
>
> The Type is not public. It's a dynamic value and unless we introduce a
> _get_type() function (which would create a dependency problem), there's
> no easy way to do it.

True, we need to keep types as strings, but we can do some kind of lazy 
initialization.  See IRC conversation + later.

> Symbolic names really help simplify things by allowing dynamic
> dependency resolution.

Yes, I understand this now.  But once we're out of the initialization 
path we should be able to avoid them in hot paths.
>> At the very least provide a function that takes a string and one that
>> takes a Type/TypeImpl, and always use the latter when you tail call.
>
> You're concerned about performance?

Yes.  At least for a simple subclass of Object, object_new should not be 
_that_ much slower than a g_malloc.

>> Typo, you want deinit. And again, let's avoid type names. This is C,
>> not BASIC.
>
> Ack on the deinit. But see above re: type names.

Yeah, I see now the problem with dependencies, but I'm pretty sure we'll 
reach a compromise. :)

>>> +typedef uint64_t Type;
>>
>> struct TypeImpl;
>> typedef struct TypeImpl *Type;
>
> Not so sure on this.

It doesn't really matter, it can be refactored away later.  But on IRC 
you said it worked out nicely.

The point is when to use strings and when to use type handles.  It 
doesn't matter whether the handles are direct pointers or indices into a 
registry.

>>
>>> +typedef struct ObjectClass ObjectClass;
>>> +typedef struct Object Object;
>>> +
>>> +typedef struct TypeInfo TypeInfo;
>>> +
>>> +typedef struct InterfaceClass InterfaceClass;
>>> +typedef struct Interface Interface;
>>> +typedef struct InterfaceInfo InterfaceInfo;
>>> +
>>> +#define TYPE_OBJECT NULL
>>> +
>>> +/**
>>> + * SECTION:object.h
>>> + * @title:Base Object Type System
>>> + * @short_description: interfaces for creating new types and objects
>>> + *
>>> + * The QEMU Object Model provides a framework for registering user
>>> creatable
>>> + * types and instantiating objects from those types. QOM provides
>>> the following
>>> + * features:
>>> + *
>>> + * - System for dynamically registering types
>>> + * - Support for single-inheritance of types
>>> + * - Multiple inheritance of stateless interfaces
>>> + *
>>> + *<example>
>>> + *<title>Creating a minimal type</title>
>>> + *<programlisting>
>>> + * #include "qdev.h"
>>> + *
>>> + * #define TYPE_MY_DEVICE "my-device"
>>
>> #define TYPE_MY_DEVICE my_device_get_type()
>
> This makes things pretty ugly.

Yes, indeed.  Let's add a fast path for object_new and object_initialize 
that takes a Type value.  To use these you use a get_type() function or 
fetch the Type from a static variable.

Another reason why I'd like you to provide this fast path from the 
beginning, is because you're doing a lot of type_get_by_name() even 
though the type has been found already.  Having the fast paths would 
make you more honest about what needs to do the lookup and what doesn't. 
  Basically only the toplevel calls need to.

Of course this makes this comment moot too:

>>> +#define TYPE_INTERFACE "interface"
>>
>> Let's make TYPE_* constants pointers, not strings.

Thanks,

Paolo

  reply	other threads:[~2011-12-21 15:28 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-12-20 16:51 [Qemu-devel] [PATCH 00/27] qom: add QEMU Object Model type hierarchy to qdev Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 01/27] qom: add the base Object class Anthony Liguori
2011-12-21 13:35   ` Paolo Bonzini
2011-12-21 14:35     ` Anthony Liguori
2011-12-21 15:28       ` Paolo Bonzini [this message]
2011-12-22 17:25       ` Kevin O'Connor
2011-12-22 17:41         ` Anthony Liguori
2011-12-22 18:00           ` Kevin O'Connor
2011-12-22 19:57             ` Anthony Liguori
2012-01-02 23:01               ` Andreas Färber
2012-01-03  0:56                 ` Anthony Liguori
2011-12-22 20:25         ` Paolo Bonzini
2012-01-02 17:59   ` Paolo Bonzini
2012-01-03  1:18     ` Anthony Liguori
2012-01-03  8:57       ` Paolo Bonzini
2011-12-20 16:51 ` [Qemu-devel] [PATCH 02/27] qdev: integrate with QEMU Object Model Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 03/27] qdev: move qdev->info to class Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 04/27] qdev: don't access name through info Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 05/27] qdev: use a wrapper to access reset and promote reset to a class method Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 06/27] pci: check for an initialized QOM object instead of looking for an info link Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 07/27] qdev: add a interface to register subclasses Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 08/27] qdev: add class_init to DeviceInfo Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 09/27] qdev: prepare source tree for code conversion Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 10/27] not-for-upstream: disable non-qdev pci devices Anthony Liguori
2012-01-02 22:55   ` Andreas Färber
2012-01-03  0:55     ` Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 11/27] isa: convert to QEMU Object Model Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 12/27] usb: " Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 13/27] ccid: " Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 14/27] ssi: " Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 15/27] i2c: rename i2c_slave -> I2CSlave Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 16/27] i2c: smbus: convert to QEMU Object Model Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 17/27] hda-codec: " Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 18/27] ide: " Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 19/27] scsi: " Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 20/27] not-for-upstream: spapr: break default console Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 21/27] spapr: convert to QEMU Object Model Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 22/27] not-for-upstream: virtio-serial: stub out a strange hack Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 23/27] virtio-serial: convert to QEMU Object Model Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 24/27] grackle: remove broken pci device Anthony Liguori
2012-01-02 22:41   ` Andreas Färber
2012-01-03  0:53     ` Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 25/27] unin_pci: remove phantom qdev devices in unin_pci Anthony Liguori
2012-01-02 22:44   ` Andreas Färber
2011-12-20 16:51 ` [Qemu-devel] [PATCH 26/27] pci: convert to QEMU Object Model Anthony Liguori
2011-12-20 16:51 ` [Qemu-devel] [PATCH 27/27] sysbus: " Anthony Liguori
2011-12-20 16:55 ` [Qemu-devel] [PATCH 00/27] qom: add QEMU Object Model type hierarchy to qdev Anthony Liguori

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=4EF1FB29.40504@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=aliguori@us.ibm.com \
    --cc=armbru@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).