qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Christophe de Dinechin <dinechin@redhat.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Kevin Wolf" <kwolf@redhat.com>,
	"Peter Maydell" <peter.maydell@linaro.org>,
	"\"Daniel P. Berrangé\"" <berrange@redhat.com>,
	"Denis V. Lunev" <den@virtuozzo.com>,
	"Stefan Hajnoczi" <stefanha@gmail.com>,
	"Markus Armbruster" <armbru@redhat.com>,
	qemu-devel <qemu-devel@nongnu.org>,
	"Marc-André Lureau" <marcandre.lureau@gmail.com>,
	"John Snow" <jsnow@redhat.com>,
	"Dominik Csapak" <d.csapak@proxmox.com>
Subject: Re: Integrating QOM into QAPI
Date: Mon, 27 Jan 2020 20:05:13 +0100	[thread overview]
Message-ID: <82B69BF4-B34B-4B76-81AD-2DE789C9F9EA@redhat.com> (raw)
In-Reply-To: <0e08d426-dc2a-d373-86f3-f2cc22694b74@redhat.com>



> On 26 Jan 2020, at 17:47, Paolo Bonzini <pbonzini@redhat.com> wrote:
> 
> On 26/01/20 10:11, Marc-André Lureau wrote:
>>> I’m still puzzled as to why anybody would switch to something like
>>> GObject when there is C++.
>> C++ is another level of complexity.
>> 
>> Replacing QOM with GObject would mainly bring us a more solid type
>> system with better tooling/features, gobject-introspection support,
>> and remove the burden of having our own OO from QEMU code base.
> 
> In fact, C++ doesn't solve any of the problems that either QOM or
> GObject try to solve.  (Neither does Rust for that matter).

It does not solve all of them _easily_. I do believe that any solution
to these problems can be engineered in C++, if only because C++
is essentially a superset of C. The question is whether the result can
be made easier / safer to use and generally more elegant. I believe
that the answer is yes, see proof at end of mail.

However, before going further, glib offers way more than gobject.
So there’s that too… And I’m not saying migrating to C++ is a good
idea, I’m just trying to evaluate the various options fairly.


> Nevertheless, there is no stupid question, only stupid answers, and I
> think Christophe's remark is an example of a common misconception.  In
> the hope of not making this a stupid answer, let my try to formulate
> succinctly what I think the differences are between QOM, GObject and the
> C++ object model:

Thank you for this remarkably non-stupid answer ;-) You have really
isolated, in very clear terms, the essence of the discussion.

> 
> - the C++ object model (at least "old-style" C++ with virtual functions
> and the like) provides you with _the intersection_ of what QOM and
> GObject try to solve.  This is what Marc-André calls "OO", and it's
> essentially virtual functions and dynamic casts.  It's a relatively
> small part of both QOM and GObject, and unfortunately a wheel that
> almost every large C program ends up reinventing.

This was the part I was pointing to in my initial comment.

C++ solves that basic “OO” stuff well, and goes a little beyond QOM
or GObject in offering IMO many other benefits, e.g. wrt type safety.

> 
> - Marc-André also described above what GObject provides: a fully
> introspectable type system and the tools so that _libraries_ can define
> _types that will be used from multiple programming languages_.

This kind of things has existed for a very long time. CORBA dates back
to 1991. Also, I’m not sure how important multiple programming languages
are for the qemu use-case. I believe that what matters more is remotely
accessible objects (e.g. over a socket), which in turn makes it almost
trivial to call from another language as long as you accept some kind
of serialization / deserialization process along the way.

GObject only seems marginally better for the “in same process” use case,
in the sense that it makes “objects” that can be used from any language,
indeed, but at the cost of being somewhat foreign and weird in all languages,
including C.

Look at the GClosure marshalling, for example, and compare it with the
example I give you at end of this email, and you tell me which one looks
easier and safer to use.

> 
> - QOM also provides a fully introspectable type system, but with a
> different focus: it's so that _objects_ can expose _properties that will
> be accessed from multiple channels_.

Exposing the properties and making them introspectable are the
fundamental feature we need to discuss. So agreement here.

What you have not explained to my satisfaction
yet is how GObject is a better starting point for re-creating a new
externally-accessible API than some kind of wrapper built in C++
and taking advantage of modern C++ features.


> Everything else in both GObject and QOM follows from this core purpose,
> and the differences between the two follow from the differences.  For
> example:
> 
> - GObject's focus on multiple programming languages:
> gobject-introspection, GClosure, support for non-object types (scalar
> and GBoxed)

How much of that is actually useful to create a new usable qemu API?

> 
> - QOM's focus on objects: dynamic properties, object tree, all types are
> classes

That, to me, looks fundamental, since not having it would require
a total re-architecture of the rest of qemu.

But it looks also somewhat trivial to implement in C++.
For example, obj[“id”] could return a PropertyAccessor<T>
that lets you read or write the object knowing that it is of type
T, so you could write:

	if (my_object[“id”] < 3) // Automatically checks the type

or 

	my_object[“id”] = 42;

The latter would call PropertyAccessor<int>::operator=(int), which
in turn would check if property “id” exists in my_object, if it has type
“int”, and so on.

Implementation-wise, a simple std::map of BaseProperty pointers,
where each would be an instance of some

	template<class T>
	class Property : public BaseProperty
	{
		operator T(); // get
		T& operator=(const T&); // set
	};

	template<class T, class Index>
	class PropertyAccessor
	{
		PropertyAccessor(PropertyOwner<T> &owner, Index &index) : owner(owner), index(index) {}
		operator T() { return owner[index]; }
		T& operator =(const T&val) { return owner[index] = val; }
	};

> - QOM's focus on properties: no introspection of methods

OK. So I’m giving a bad example below, because I’m introspecting
a method, but… ;-)

> - QOM's support for multiple channels: visitors

How different are visitors from iterators in C++? Sorry, showing my
ignorance here… 


I do not fully understand all the subtleties of QOM, nor all its use cases.
However, my own experience with “modern” C++ shows that it’s pretty
straightforward to get it to do extremely interesting introspective work.

As an illustration, which happens to be directly related to the problem
of interconnecting with another language, I would like to share the following
tidbit of code (https://github.com/c3d/xl/blob/master/src/runtime.cpp#L73).

Tree *  xl_evaluate(Scope *scope, Tree *tree)
// ----------------------------------------------------------------------------
//   Dispatch evaluation to the main entry point
// ----------------------------------------------------------------------------
{
    return MAIN->Evaluate(scope, tree);
}
XL_NATIVE(evaluate);

With this little XL_NATIVE macro, the compiler automatically makes the
function xl_evaluate available to the XL language as “evaluate”, with
the correct parameter sets. In particular:

- It inserts an object representing xl_evaluate in a list of all native functions
- It generates a function that generates the source-code interface,
  which in XL would look like `evaluate A:scope, B:tree as tree`,
  see record #28601 in the output below. Note that this includes 
  all the required type conversions (e.g. from `Tree *` to `tree`).
- It generates a function that generates a machine-level prototype
  using LLVM, i.e. it automatically all the LLVM calls required to declare
    Tree *xl_evaluate(Scope *scope, Tree *tree);
- It generates a function that acts as a wrapper around it and calls
  the prototype above, doing the necessary type conversions.

Here is an example of output at run-time:
> xl -tnative -O3
[…]
[26809 0.007432] native: Entering prototype for same_text shape 0x111a3f540 [same_text A:tree, B:text as boolean]
[27021 0.007512] native: Shape 1 infix 0x111615d28 [tree] : 0x111ac8838 [A] = 0x111a94af0 [A:tree]
[27213 0.007630] native: Return shape (one) 0x111615d28 [tree]
[27274 0.007651] native: Native shape 1 0x111a94aa8 [A:tree as tree] return 0x111615d28 [tree]
[27447 0.007708] native: Entering prototype for stack_overflow shape 0x111a3f510 [stack_overflow A:tree as tree]
[27595 0.007784] native: Shape 1 infix 0x111615c10 [scope] : 0x111ac87c8 [A] = 0x111a94a60 [A:scope]
[27795 0.007844] native: Shape 2 infix 0x111615d28 [tree] : 0x111ac8790 [B] = 0x111a94a18 [B:tree]
[27991 0.007897] native: Shape 2 (...) 0x111a94a60 [A:scope],0x111a94a18 [B:tree] = 0x111a949d0 [A:scope, B:tree]
[28303 0.007985] native: Return shape (...) 0x111615d28 [tree]
[28364 0.008014] native: Native shape 2 0x111a94988 [A:scope, B:tree as tree] return 0x111615d28 [tree]
[28601 0.008077] native: Entering prototype for evaluate shape 0x111a3f4e0 [evaluate A:scope, B:tree as tree]
[…]

What I believe makes my point is that this is achieved with 476 lines of C++
(admittedly not the simplest C++ on earth, but still not super-complex either)
If you are curious, this is done by https://github.com/c3d/xl/blob/master/include/native.h.

So in 500 lines of C++ code, we have something that automatically turns any C function into
a wrapper object that:
- Gives you introspected type information about the parameters and return type of the function
- Gives you directly-accessible methods that operate on that function in a type-safe way

The same approach could of course offer serialization, construction of objects, etc.

So to me, this proves that introspecting an API in C++ is not just “easy”, it is highly usable.


Cheers,
Christophe

PS: Again, I’m not necessarily advocating we start writing any C++ code.
I’m just trying to understand the value proposition of GObject, QOM, etc,
in order to make a more informed decision before doing anything.

> 
> Paolo
> 



  reply	other threads:[~2020-01-27 19:06 UTC|newest]

Thread overview: 183+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-20 16:13 Making QEMU easier for management tools and applications Stefan Hajnoczi
2019-12-20 21:07 ` Richard W.M. Jones
2020-01-02 11:26   ` Stefan Hajnoczi
2019-12-21  9:02 ` Markus Armbruster
2019-12-23 15:04   ` Michal Prívozník
2020-01-07  9:36     ` Kevin Wolf
2020-01-07 10:55       ` Michal Privoznik
2020-01-07 12:57         ` Kevin Wolf
2020-01-07 17:53           ` Christophe de Dinechin
2019-12-24 13:41   ` Daniel P. Berrangé
2020-01-22 22:28     ` John Snow
2020-01-23  7:19       ` Markus Armbruster
2020-01-23 17:58         ` John Snow
2020-01-23 19:01           ` Daniel P. Berrangé
2020-01-23 21:07             ` John Snow
2020-01-24  7:59               ` Markus Armbruster
2020-01-24 10:27                 ` Daniel P. Berrangé
2020-01-24 14:38                   ` Kevin Wolf
2020-01-24 18:23                     ` John Snow
2020-01-24 18:30                       ` Dr. David Alan Gilbert
2020-01-24 18:48                         ` John Snow
2020-01-24 18:52                           ` Dr. David Alan Gilbert
2020-01-24 18:58                             ` John Snow
2020-01-25 10:18                     ` Markus Armbruster
2020-01-27 10:18                       ` Daniel P. Berrangé
2020-01-27 12:48                         ` Markus Armbruster
2020-01-27 11:56                       ` Kevin Wolf
2020-01-27 12:04                         ` Peter Maydell
2020-01-27 20:11                         ` John Snow
2020-01-27 22:38                           ` Paolo Bonzini
2020-01-28  0:37                             ` John Snow
2020-01-28 10:16                             ` Daniel P. Berrangé
2020-01-28 10:39                               ` Kevin Wolf
2020-01-28 15:36                                 ` Markus Armbruster
2020-01-31 12:25                                   ` Eric Blake
2020-01-28 10:28                           ` Kevin Wolf
2020-01-28 12:36                             ` Markus Armbruster
2020-01-28 12:54                               ` Kevin Wolf
2020-01-28 13:45                                 ` Gerd Hoffmann
2020-01-31  6:50                                 ` Markus Armbruster
2020-01-31  7:48                                   ` Paolo Bonzini
2020-01-31  8:09                                     ` Markus Armbruster
2020-02-03 20:07                                   ` Andrea Bolognani
2020-02-04  9:58                                     ` Markus Armbruster
2020-01-31 12:27                                 ` Eric Blake
2020-02-02  9:21                                   ` Kevin Wolf
2020-02-02 10:44                                     ` Paolo Bonzini
2020-02-03  6:20                                       ` Markus Armbruster
2020-02-03  8:48                                         ` Markus Armbruster
2020-01-27 20:12                         ` Dr. David Alan Gilbert
2020-01-24 20:34                 ` John Snow
2020-01-27  8:35                   ` Gerd Hoffmann
2020-01-27 12:13                     ` Kevin Wolf
2020-01-27 16:18                       ` Gerd Hoffmann
2020-01-24  9:50               ` Daniel P. Berrangé
2020-01-25 11:52                 ` Paolo Bonzini
2020-01-27 10:05                   ` Daniel P. Berrangé
2020-01-27  8:25                 ` Tooling to help humans use JSON (was: Making QEMU easier for management tools and applications) Markus Armbruster
2020-01-27  9:06                 ` Making QEMU easier for management tools and applications Markus Armbruster
2020-01-27 10:00                   ` Daniel P. Berrangé
2020-01-27 14:35                 ` Kevin Wolf
2020-01-27 20:29                   ` Dr. David Alan Gilbert
2020-01-28 10:59                     ` Kevin Wolf
2020-02-05 13:09                       ` Kevin Wolf
2020-02-05 19:09                         ` qmp-shell for GSoC/Outreachy? (Was: Re: Making QEMU easier for management tools and applications) John Snow
2020-02-05 19:49                           ` Dr. David Alan Gilbert
2020-02-06  9:40                             ` qmp-shell for GSoC/Outreachy? Markus Armbruster
2020-02-06 10:09                               ` Daniel P. Berrangé
2020-02-06 12:11                                 ` Markus Armbruster
2020-02-06 12:15                                   ` Daniel P. Berrangé
2020-02-06 18:02                                     ` Dr. David Alan Gilbert
2020-02-07 21:03                                   ` John Snow
2020-02-08  7:17                                     ` Markus Armbruster
2020-02-06 14:21                               ` Kevin Wolf
2020-02-06 18:26                                 ` Dr. David Alan Gilbert
2020-02-07 10:49                                   ` Kevin Wolf
2020-02-07 21:23                                 ` John Snow
2020-02-08  7:25                                   ` Markus Armbruster
2020-02-10 11:59                                     ` Kevin Wolf
2020-02-10 12:26                                   ` Kevin Wolf
2020-02-06 18:18                               ` Dr. David Alan Gilbert
2020-02-07  7:47                                 ` Markus Armbruster
2020-02-07 21:31                                 ` Eric Blake
2020-02-08  7:34                                   ` Markus Armbruster
2020-02-07 21:56                                 ` John Snow
2020-02-07 20:56                               ` John Snow
2020-01-27 20:59                   ` Making QEMU easier for management tools and applications John Snow
2020-01-28 10:16                     ` Markus Armbruster
2020-01-28 19:21                       ` John Snow
2020-01-24  6:38           ` Markus Armbruster
2020-01-25 22:34           ` Christophe de Dinechin
2020-01-25 11:55     ` Paolo Bonzini
2020-01-02 14:47   ` Stefan Hajnoczi
2020-01-16 11:03     ` Kashyap Chamarthy
2020-01-20  9:55       ` Stefan Hajnoczi
2020-01-20 13:57         ` Kashyap Chamarthy
2020-01-25 11:41         ` Paolo Bonzini
2020-01-27 19:41           ` John Snow
2020-01-02 15:05   ` Dr. David Alan Gilbert
2020-01-13 13:44     ` Markus Armbruster
2019-12-24 13:00 ` Daniel P. Berrangé
2020-01-02 14:22   ` Stefan Hajnoczi
2020-01-22 22:42   ` John Snow
2020-01-23  7:21     ` Markus Armbruster
2020-01-23 10:27     ` Daniel P. Berrangé
2020-01-23 18:13       ` John Snow
2020-01-23 19:12         ` Daniel P. Berrangé
2020-01-02 15:10 ` Dr. David Alan Gilbert
2020-01-07 17:11 ` Christophe de Dinechin
2020-01-08 10:43   ` Kevin Wolf
2020-01-08 11:40     ` Christophe de Dinechin
2020-01-08 13:38       ` Kevin Wolf
2020-01-14 13:04         ` Markus Armbruster
2020-01-14 17:31           ` Christophe de Dinechin
2020-01-15  9:20             ` Markus Armbruster
2020-01-15  9:34               ` Christophe de Dinechin
2020-01-15 12:15                 ` Markus Armbruster
2020-01-15 12:19                   ` Daniel P. Berrangé
2020-01-15 14:02                     ` Markus Armbruster
2020-01-30 21:09                       ` Improving QOM documentation [Was: Re: Making QEMU easier for management tools and applications] Kashyap Chamarthy
2020-01-31  6:11                         ` Markus Armbruster
2020-01-31  7:46                           ` Paolo Bonzini
2020-01-31 15:37                             ` Christophe de Dinechin
2020-01-31 16:28                               ` Paolo Bonzini
2020-01-31  9:50                           ` Kashyap Chamarthy
2020-01-31 10:35                           ` Peter Maydell
2020-01-31 11:02                             ` Paolo Bonzini
2020-01-31 15:22                               ` Kashyap Chamarthy
2020-01-31 17:23                                 ` Markus Armbruster
2020-02-03  8:56                                   ` Paolo Bonzini
2020-02-03  9:54                                     ` Markus Armbruster
2020-02-03 15:21                                       ` Paolo Bonzini
2020-02-04  8:42                                         ` Markus Armbruster
2020-01-31 16:39                               ` Markus Armbruster
2020-01-20 10:08                   ` Making QEMU easier for management tools and applications Stefan Hajnoczi
2020-01-21  5:42                     ` Markus Armbruster
2020-01-21 11:32                       ` Stefan Hajnoczi
2020-01-21 12:03                         ` Marc-André Lureau
2020-01-21 13:36                           ` Integrating QOM into QAPI (was: Making QEMU easier for management tools and applications) Markus Armbruster
2020-01-21 14:36                             ` Daniel P. Berrangé
2020-01-21 15:01                               ` Integrating QOM into QAPI Markus Armbruster
2020-01-21 15:11                                 ` Marc-André Lureau
2020-01-21 16:21                                   ` Peter Maydell
2020-01-22  5:16                                     ` Getting whole-tree patches reviewed and merged (was: Integrating QOM into QAPI) Markus Armbruster
2020-02-07 21:53                                       ` Getting whole-tree patches reviewed and merged Eric Blake
2020-02-10 11:26                                         ` Paolo Bonzini
2020-02-10 16:04                                           ` Markus Armbruster
2020-02-10 16:12                                             ` Peter Maydell
2020-01-22 10:50                                   ` Integrating QOM into QAPI Alex Bennée
2020-01-22 12:24                                     ` Markus Armbruster
2020-01-22 12:42                                       ` Marc-André Lureau
2020-01-22 13:28                                         ` Peter Maydell
2020-01-22 13:32                                           ` Marc-André Lureau
2020-01-23  7:37                                         ` Markus Armbruster
2020-01-24 18:32                                         ` Paolo Bonzini
2020-01-25  4:44                                           ` Marc-André Lureau
2020-01-25  9:28                                             ` Paolo Bonzini
2020-01-25 21:25                                               ` Peter Maydell
2020-01-26  8:09                                   ` Christophe de Dinechin
2020-01-26  9:11                                     ` Marc-André Lureau
2020-01-26 16:47                                       ` Paolo Bonzini
2020-01-27 19:05                                         ` Christophe de Dinechin [this message]
2020-01-27 19:05                                       ` Christophe de Dinechin
2020-01-26 15:04                                     ` Peter Maydell
2020-01-27 19:05                                       ` Christophe de Dinechin
2020-01-28  8:00                                         ` Markus Armbruster
2020-01-28 10:03                                         ` Daniel P. Berrangé
2020-01-29 12:42                                           ` Christophe de Dinechin
2020-01-15  9:35               ` Making QEMU easier for management tools and applications Marc-André Lureau
2020-01-15 12:25                 ` Markus Armbruster
2020-01-25 17:18               ` Paolo Bonzini
2020-01-27  9:30                 ` Markus Armbruster
2020-01-13 16:30   ` Stefan Hajnoczi
2020-02-04 15:54 ` Summary of " Markus Armbruster
2020-02-05  6:38   ` Markus Armbruster
2020-02-10 10:56   ` Stefan Hajnoczi
2020-02-10 11:01     ` Peter Maydell
2020-02-10 11:08       ` Daniel P. Berrangé
2020-02-10 11:29         ` Peter Maydell
2020-02-10 11:04     ` Paolo Bonzini
2020-02-10 16:43     ` Markus Armbruster
2020-02-12 13:54       ` Stefan Hajnoczi
2020-02-12 14:03         ` Daniel P. Berrangé

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=82B69BF4-B34B-4B76-81AD-2DE789C9F9EA@redhat.com \
    --to=dinechin@redhat.com \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=d.csapak@proxmox.com \
    --cc=den@virtuozzo.com \
    --cc=jsnow@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=marcandre.lureau@gmail.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@gmail.com \
    /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).