From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:41847) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RXVEB-0006Yk-Nb for qemu-devel@nongnu.org; Mon, 05 Dec 2011 04:52:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RXVEA-00032D-3N for qemu-devel@nongnu.org; Mon, 05 Dec 2011 04:52:51 -0500 Received: from mail-iy0-f173.google.com ([209.85.210.173]:58943) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RXVE9-000323-Pz for qemu-devel@nongnu.org; Mon, 05 Dec 2011 04:52:50 -0500 Received: by iakk32 with SMTP id k32so9623993iak.4 for ; Mon, 05 Dec 2011 01:52:48 -0800 (PST) Sender: Paolo Bonzini Message-ID: <4EDC946A.3090702@redhat.com> Date: Mon, 05 Dec 2011 10:52:42 +0100 From: Paolo Bonzini MIME-Version: 1.0 References: <4ED98C06.5040405@codemonkey.ws> <4EDA3104.8030304@redhat.com> <4EDA95ED.6030706@codemonkey.ws> <4EDBDFC7.3090206@codemonkey.ws> In-Reply-To: <4EDBDFC7.3090206@codemonkey.ws> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH v2 00/18] qom: dynamic properties and composition tree (v2) List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Anthony Liguori Cc: qemu-devel@nongnu.org On 12/04/2011 10:01 PM, Anthony Liguori wrote: >> > > I've begun the work of introducing proper inheritance. There's a > lot going on but the basic idea is: > > 1) introduce QOM base type (Object), make qdev inherit from it > > 2) create a dynamic typeinfo based DeviceInfo, make device class > point to deviceinfo > > 3) model qdev hierarchy in QOM > > 4) starting from the bottom of the hierarchy, remove DeviceInfo > subclass and push that functionality into QOM classes Ok, now we're talking. I looked at the SCSI bits and it looks sane---though I still don't understand your loathe for static initializers (which also causes a lot of code churn). > I do want to get rid of qdev busses but I'm in no rush at all. We > can do 95% of the necessary refactoring without touching busses and > hot plug and I think that's the right strategy. Yes, as long as you have a plan for them. Some of the buses have data so they will have to become objects of their own, with a bidirectional link between them and the parent device. (Because I'm not going to write code like this for each HBA: void lsi_set_unit_attention(Device *dev, SCSISense sense) { LSIDevice *lsi = LSI_DEVICE(dev); lsi->unit_attention = sense; } No, I'm not. Over my dead body). >> Right now I can hardly understand how the composition tree will >> work, for example: how do you constrain children to be subclasses >> of some class (or to implement some interface)? > > Composition never involves subclasses. The tree I point you to above > is about as complete as it can be right now without doing more qdev > conversions. It should answer all of your questions re: composition. All except one: why can't child (and link too IIRC) properties be created with a NULL value? >> And how do they? How much code churn does that entail, in the >> devices and in general? In fact, why do they need conversion at >> all? Static properties are special enough to warrant something >> special. > > They can stay around forever (or until someone needs non-static > properties) but I strongly suspect that we'll get rid of most of them > as part of refactoring. > > An awful lot of properties deal with connecting to back ends and/or > bus addressing. None of that will be needed anymore. True for PCI, but what about ISA or MMIO devices? They do their own address/IRQ decoding. You don't see those properties in many cases because they're hidden beneath sysbus magic, but there are hundreds. >> Let's write documentation on that already. > > I have written lots of documentation. Just take a look at the wiki. It's down. :( >> Once the type is written as child, you've lost all info >> on it. Each property type should have its own representation for >> types (it can be implicit, or it can be an enum, or it can be a >> DeviceInfo), with a method to pretty-print it. > > I don't know what you mean by "lost all info on it" but I'm strongly > opposed to a "pretty-print" method. Having the pretty printing > information in the type is almost never what you want. I agree---I was talking about pretty-printing *the type itself*. The type falls outside the visitor model, which is only concerned about the contents. >>> You may find it odd to hear me say this, but I grow weary of >>> adding too much class hierarchy and inheritance with properties. >>> Yes, we could make it very sophisticated but in practice it >>> doesn't have to be. Properties should be one of two things: >>> primitive types or link/childs. >> >> ... and interfaces. Accessing them by name as a property should >> work well. > > No, not interfaces. The object *is-a* interface. It doesn't has-a > interface.> > > We've gone through this debate multiple times. You misunderstood (and I wasn't clear enough). The is-a/has-a debate is indeed settled for things such as PCI-ness where we'll keep the current three-level class hierarchy (two abstract, one concrete): Device PCIDevice ... concrete PCI devices ... ISADevice ... concrete ISA devices ... The problem is that, in addition to the is-a class hierarchy, you have the interface hierarchy. Here, C-level struct "inheritance" does not help you because you do not have a fixed place for the vtable. So, for example, instead of struct SCSIBusInfo { .command_complete = lsi_command_complete, ... }; I'll have something like this: Interface *interface; SCSIBusIface *sbi; interface = qdev_add_interface(&dev->qdev, TYPE_SCSI_BUS_INTERFACE); sbi = SCSI_BUS_INTERFACE(interface); sbi->command_complete = lsi_command_complete; ... Right? Then I create the SCSIBus object with something as simple as: struct LSIDevice { ... SCSIBus *bus; } dev->bus = scsi_bus_new(&dev->qdev); and scsi_bus_new will do something like Interface *interface; interface = qdev_get_interface(dev, TYPE_SCSI_BUS_INTERFACE); scsi_bus->sbi = SCSI_BUS_INTERFACE(interface); Perhaps hidden with some macro that lets me just write SCSI_BUS_INTERFACE(dev), but that's the idea; such a lookup function is pretty much what all object models do. GObject has G_TYPE_INSTANCE_GET_INTERFACE, COM/XPCOM has QueryInterface, etc. If I understood everything so far, then here is my question. Are interfaces properties? I'm starting to understand now that the answer is probably "no because interfaces have nothing to do with visitors", and that's fine. Then I suppose you'll have another list to lookup besides properties, no problem with that. >>> This is where qdev goes very wrong. It mixes up user interface >>> details (how to format an integer on the command line) with >>> implementation details. There's no reason we should be indicating >>> whether a property should be display in hex or decimal in the >>> device itself. >> >> That's totally true. But there's no reason why qdev properties >> cannot be split in two parts, a sane one and a legacy one. > > Bingo! Hence, the 'legacy<>' namespace. If you want to do a > declare, struct member based syntax that encodes/decodes as primitive > types to a Visitor, be my guest That's not what I meant. The legacy<> namespace splits the set of QOM properties in two parts, sane ones and legacy ones. That's wrong, because the old broken interface remains there. Worse, it remains there as user-visible API in the JSON etc., and it will remain forever since we cannot get rid of -device overnight. What I suggested is to provide two implementations for each old-style property: an old string-based one (used for -device etc.) and a modern visitor-based one (used for qom_*). In other words, old-style properties would expose both a print/parse legacy interface, and a sane get/set visitor interface. No need for a legacy<> namespace, because new-style consumers would not see the old-style string ABI. >> I was thinking of one-off types such as rtc's struct tm. > > I'd really like to get to a point where these type visitors were > being generated. Yeah, long term that'd be great. Paolo