qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] Issues around TYPE_INTERFACE


From: Daniel P . Berrangé
Subject: Re: [Qemu-devel] Issues around TYPE_INTERFACE
Date: Mon, 18 Mar 2019 11:54:07 +0000
User-agent: Mutt/1.11.3 (2019-02-01)

On Tue, Mar 12, 2019 at 11:50:54AM +0100, Markus Armbruster wrote:
> We have two separate type trees, object types rooted at TYPE_OBJECT, and
> interface types at TYPE_INTERFACE.
> 
> Object types are fore defining ultimately concrete types, i.e. any
> concrete type is a descendant of TYPE_OBJECT.  Interior nodes of the
> TYPE_OBJECT tree are commonly abstract, with a few exceptions.  Leaves
> need to be concrete to be of any use.
> 
> Interface types are for defining interfaces object types provide (by
> listing them in a type's .interfaces).  TYPE_INTERFACE and all its
> descendants are abstract.
> 
> Issue #1: INTERFACE_CLASS()
> 
>     #define OBJECT_CLASS(class) \
>         ((ObjectClass *)(class))
> 
>     #define OBJECT_CLASS_CHECK(class_type, class, name) \
>         ((class_type *)object_class_dynamic_cast_assert(OBJECT_CLASS(class), 
> (name), \
>                                                    __FILE__, __LINE__, 
> __func__))
> 
>     #define INTERFACE_CLASS(klass) \
>         OBJECT_CLASS_CHECK(InterfaceClass, klass, TYPE_INTERFACE)
> 
> Shouldn't INTERFACE_CLASS() be named INTERFACE_CLASS_CHECK() for
> consistency?

I actually wonder why we even need "OBJECT_CLASS" as it exists here
at all.

$ git grep 'OBJECT_CLASS\b' | wc -l
38
$ git grep 'OBJECT_CLASS_CHECK\b' | wc -l
196

There's no obvious pattern in why OBJECT_CLASS is being favoured.
The only compelling benefit of it is that it is faster since it
avoids checking anything.


What if we include sub-classes

  $ git grep '_CLASS('  | grep -v GET_CLASS | wc -l
  1946

It looks like ${FOO}_CLASS is the popular syntax, but this is misleading
as sub-classes don't follow the same convention - they all appear to make
their ${FOO}_CLASS macro call OBJECT_CLASS_CHECK, as this is what object.h
recommands as the pattern :-)

#define MACHINE_CLASS(klass) \
    OBJECT_CLASS_CHECK(MachineClass, (klass), TYPE_MACHINE)


IOW, I think we could/should remove OBJECT_CLASS and rename
OBJECT_CLASS_CHECK to OBJECT_CLASS.

If there are some callers that absolutely need the performance
of doing a cast without safety checks, they can just do a
direct cast with normal C syntax - no need for a macro.


> Rename would be trivial, as there are no uses.

Renaming INTERFACE_CLASS becomes redundant if we fix OBJECT_CLASS

> 
> Issue #2: INTERFACE_CHECK()
> 
>     #define OBJECT_CHECK(type, obj, name) \
>         ((type *)object_dynamic_cast_assert(OBJECT(obj), (name), \
>                                             __FILE__, __LINE__, __func__))
> 
>     #define INTERFACE_CHECK(interface, obj, name) \
>         ((interface *)object_dynamic_cast_assert(OBJECT((obj)), (name), \
>                                                  __FILE__, __LINE__, 
> __func__))
> 
> The two are identical (except the former lacks parenthesis around obj,
> which is a minor bug).
> 
> Obvious question: shouldn't we de-duplicate the code?
> 
> There's a more interesting question, however.  Since two two are
> identical, they can be used interchangeably.  And since we can, we do;
> for instance
> 
>     #define QAUTHZ(obj) \
>          INTERFACE_CHECK(QAuthZ, (obj), \
>                          TYPE_QAUTHZ)
> 
> even though TYPE_QAUTHZ is a sub-type of TYPE_OBJECT, not
> TYPE_INTERFACE.  Shouldn't we prevent that somehow?  Or maybe embrace
> they're the same and just get rid of INTERFACE_CHECK() entirely?

If we wanted to keep INTERFACE_CHECK then I agree we should make it fail
when not given an interface type, but i'm not really convinced it is
worth it. Code is inevitably going to get these mixed up, as this QAUTHZ
example shows. So doing a stronger check will just turn currently working
code into broken code at runtime.

I'd vote for removing INTERFACE_CHECK and using OBJECT_CHECK universally.

> Issue #3: Inconsistent naming (surprise, surprise)
> 
> The confusion between object and interface types is of course aggravated
> by our usual lack of discipline in naming.  I recognize no less than
> three naming conventions:
> 
>     INTERFACE_CONVENTIONAL_PCI_DEVICE
>     INTERFACE_PCIE_DEVICE

Definitely cull this convention - not having TYPE_ is a gratuitous
diversion from the norm.

> 
>     TYPE_ACPI_DEVICE_IF
>     TYPE_ARM_LINUX_BOOT_IF
>     TYPE_TEST_IF
>     TYPE_TPM_IF
> 
>     TYPE_IDAU_INTERFACE
>     TYPE_IPMI_INTERFACE
>     TYPE_PNV_XSCOM_INTERFACE

I'm not so bothered by these, though they are pointless unless
perhaps it is to avoid clash with a similarly named object
type

> 
> Yet they're used for less than half of the interface names:
> 
>     TYPE_FW_PATH_PROVIDER
>     TYPE_HOTPLUG_HANDLER
>     TYPE_INTERRUPT_STATS_PROVIDER
>     TYPE_ISADMA
>     TYPE_MEMORY_DEVICE
>     TYPE_NMI
>     TYPE_NVRAM
>     TYPE_PPC_VIRTUAL_HYPERVISOR
>     TYPE_STREAM_SLAVE
>     TYPE_USER_CREATABLE
>     TYPE_XICS_FABRIC
>     TYPE_XIVE_NOTIFIER
> 
> Can we agree on one naming convention, and enforce it?


Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



reply via email to

[Prev in Thread] Current Thread [Next in Thread]