All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Daniel P. Berrangé" <berrange@redhat.com>
To: Eric Blake <eblake@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	qemu-devel@nongnu.org, Eduardo Habkost <ehabkost@redhat.com>
Subject: Re: [PATCH 2/4] qom: provide convenient macros for declaring and defining types
Date: Fri, 24 Jul 2020 10:11:43 +0100	[thread overview]
Message-ID: <20200724091143.GB3146350@redhat.com> (raw)
In-Reply-To: <2e34d495-b98a-2dd3-2ae6-7ecef14f0d3e@redhat.com>

On Thu, Jul 23, 2020 at 02:23:54PM -0500, Eric Blake wrote:
> On 7/23/20 1:14 PM, Daniel P. Berrangé wrote:
> > When creating new QOM types, there is a lot of boilerplate code that
> > must be repeated using a standard pattern. This is tedious to write
> > and liable to suffer from subtle inconsistencies. Thus it would
> > benefit from some simple automation.
> > 
> > QOM was loosely inspired by GLib's GObject, and indeed GObject suffers
> > from the same burden of boilerplate code, but has long provided a set of
> > macros to eliminate this burden in the source implementation. More
> > recently it has also provided a set of macros to eliminate this burden
> > in the header declaration.
> > 
> > In GLib there are the G_DECLARE_* and G_DEFINE_* family of macros
> > for the header declaration and source implementation respectively:
> > 
> >    https://developer.gnome.org/gobject/stable/chapter-gobject.html
> >    https://developer.gnome.org/gobject/stable/howto-gobject.html
> > 
> > This patch takes inspiration from GObject to provide the equivalent
> > functionality for QOM.
> > 
> 
> > 
> > IOW, in both cases the maintainer now only has to think about the
> > interesting part of the code which implements useful functionality
> > and avoids much of the boilerplate.
> > 
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > ---
> >   include/qom/object.h | 277 +++++++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 277 insertions(+)
> > 
> > diff --git a/include/qom/object.h b/include/qom/object.h
> > index 1f8aa2d48e..be64421089 100644
> > --- a/include/qom/object.h
> > +++ b/include/qom/object.h
> > @@ -304,6 +304,119 @@ typedef struct InterfaceInfo InterfaceInfo;
> >    *
> >    * The first example of such a QOM method was #CPUClass.reset,
> >    * another example is #DeviceClass.realize.
> > + *
> > + * # Standard type declaration and definition macros #
> > + *
> > + * A lot of the code outlined above follows a standard pattern and naming
> > + * convention. To reduce the amount of boilerplate code that needs to be
> > + * written for a new type there are two sets of macros to generate the
> > + * common parts in a standard format.
> > + *
> > + * A type is declared using the OBJECT_DECLARE macro family. In types
> > + * which do not require any virtual functions in the class, the
> > + * OBJECT_DECLARE_SIMPLE_TYPE macro is suitable, and is commonly placed
> > + * in the header file:
> > + *
> > + * <example>
> > + *   <title>Declaring a simple type</title>
> > + *   <programlisting>
> > + *     OBJECT_DECLARE_SIMPLE_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE)
> 
> How sensitive is this macro to trailing semicolon?  Must the user omit it
> (as shown here), supply it (by tweaking the macro to be a syntax error if
> one is not supplied), or is it optional?  I guess whatever glib does is fine
> to copy, though.

Testing it appears it tolerates a ";" but GLib doesn't use it typically
in this case.

> 
> Hmm. I think you meant to use s/ DEVICE/ Device/ here...

Yes.

> 
> > + *   </programlisting>
> > + * </example>
> > + *
> > + * This is equivalent to the following:
> > + *
> > + * <example>
> > + *   <title>Expansion from declaring a simple type</title>
> > + *   <programlisting>
> > + *     typedef struct MyDevice MyDevice;
> > + *     typedef struct MyDeviceClass MyDeviceClass;
> > + *
> > + *     G_DEFINE_AUTOPTR_CLEANUP_FUNC(MyDeviceClass, object_unref)
> > + *
> > + *     #define MY_DEVICE_GET_CLASS(void *obj) \
> > + *             OBJECT_GET_CLASS(MyDeviceClass, obj, TYPE_MY_DEVICE)
> 
> How'd you manage to invoke #define inside the OBJECT_DECLARE_SIMPLE_TYPE
> macro expansion?
> 
> /me reads ahead
> 
> Oh, you didn't; you used a static inline function instead.  But the effect
> is the same, so claiming the equivalence here, while slightly misleading, is
> not horrible.

Yes, I was in two minds here, whether to illustrate the real inline
function, or the macro. I choose the macro to make it clear what kind
of code is being replaced, rather than what kind of code it strictly
produces.

> > + *     #define MY_DEVICE_CLASS(void *klass) \
> > + *             OBJECT_CLASS_CHECK(MyDeviceClass, klass, TYPE_MY_DEVICE)
> > + *     #define MY_DEVICE(void *obj)
> > + *             OBJECT_CHECK(MyDevice, obj, TYPE_MY_DEVICE)
> > + *
> > + *     struct MyDeviceClass {
> > + *         DeviceClass parent_class;
> 
> ...given that this line is constructed as arg4##Class, and the fact that we
> have DeviceClass, not DEVICEClass.
> 
> > + *     };
> > + *   </programlisting>
> > + * </example>
> > + *
> > + * The 'struct MyDevice' needs to be declared separately.
> > + * If the type requires virtual functions to be declared in the class
> > + * struct, then the alternative OBJECT_DECLARE_TYPE() macro can be
> > + * used. This does the same as OBJECT_DECLARE_SIMPLE_TYPE(), but without
> > + * the 'struct MyDeviceClass' definition.
> > + *
> > + * To implement the type, the OBJECT_DEFINE macro family is available.
> > + * In the simple case the OBJECT_DEFINE_TYPE macro is suitable:
> > + *
> > + * <example>
> > + *   <title>Defining a simple type</title>
> > + *   <programlisting>
> > + *     OBJECT_DEFINE_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE)
> 
> Unlike the declare, here, using DEVICE looks correct...

Yes.


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	other threads:[~2020-07-24  9:14 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-23 18:14 [PATCH 0/4] qom: reduce boilerplate required for declaring and defining objects Daniel P. Berrangé
2020-07-23 18:14 ` [PATCH 1/4] qom: make object_ref/unref use a void * instead of Object * Daniel P. Berrangé
2020-07-23 19:04   ` Eric Blake
2020-07-24  9:06     ` Daniel P. Berrangé
2020-07-23 18:14 ` [PATCH 2/4] qom: provide convenient macros for declaring and defining types Daniel P. Berrangé
2020-07-23 19:23   ` Eric Blake
2020-07-24  9:11     ` Daniel P. Berrangé [this message]
2020-08-09  4:21   ` Eduardo Habkost
2020-08-11 18:22   ` Eduardo Habkost
2020-07-23 18:14 ` [PATCH 3/4] crypto: use QOM macros for declaration/definition of secret types Daniel P. Berrangé
2020-07-23 18:50   ` Eduardo Habkost
2020-07-24  9:12     ` Daniel P. Berrangé
2020-08-06 18:01       ` Eduardo Habkost
2020-08-07 11:11         ` Daniel P. Berrangé
2020-08-08  1:38           ` Eduardo Habkost
2020-07-23 19:25   ` Eric Blake
2020-07-23 18:14 ` [PATCH 4/4] crypto: use QOM macros for declaration/definition of TLS creds types Daniel P. Berrangé
2020-07-23 19:26   ` Eric Blake

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=20200724091143.GB3146350@redhat.com \
    --to=berrange@redhat.com \
    --cc=eblake@redhat.com \
    --cc=ehabkost@redhat.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.