On 3/14/22 15:07, Stefan Hajnoczi wrote:
If we can reach a consensus about C++ language usage in QEMU then I'm in
favor of using C++ coroutines. It's probably not realistic to think we
can limit C++ language usage to just coroutines forever. Someone finds
another C++ feature they absolutely need and over time the codebase
becomes C++ - with both its advantages and disadvantages.
[...] although you can write C in C++, it's not idiomatic modern C++.
The language lends itself to a different style of programming that
some will embrace while others will not.
Yes, this is an important aspect to discuss. I think coroutines provide
a good blueprint for how QEMU might use C++.
I totally agree that, if we go this way, the genie is out of the bottle
and other uses of C++ will pop up with 100% probability. But the
important thing to note is that our dialect of C is already not standard
C, and that some of our or GLib's "innovations" are actually based on
experience with C++. We can keep on writing "QEMU's C" if we think of
C++ as a supercharged way of writing these quality-of-life improvements
that we already write. In some sense coroutines are an extreme example
of this idea.
In fact, a C API would have to remain unless all source files are
changed to C++, so QEMU would remain mostly a C project with C idioms,
but that doesn't prevent _abstracting_ the use of C++ features (written
in modern, idiomatic C++) behind an API that C programmers have no
problems learning. Again, coroutines are an example of this of keeping
the familiar create/enter/yield API and hiding the "magic" of C++
coroutines (and when they don't, that had better be an improvement).
In the end, C++ is a tool that you can use if it leads to better code.
For example, I don't see much use of C++ for devices for example, and
the storage devices in particular do not even need coroutines because
they use the callback-based interface. But perhaps someone will try to
use templates to replace repeated inclusion (which is common in
hw/display) and others will follow suit. Or perhaps not.
One example that was brought up on IRC is type-safe operations on things
such as hwaddr (i.e. hwaddr+int is allowed but hwaddr-hwaddr gives back
an int64_t and might even check for overflow). These would be opt in
(you get them just by changing a file from .c to .cc), but the actual
C++ code would still look very much like C code that uses hwaddr with no
type checking. All the operator overloading gunk would be in include/.
A different topic is what would happen if all of QEMU could be compiled
as C++, and could inform our selection of C++ idioms even long before we
get there. For example, I'm fine with GLib and our type-safe intrusive
lists, so I don't have much interest in STL containers and I would
prefer _not_ to use STL containers even in .cc files[1]. However,
perhaps QEMU's home-grown lock guard might be replaced by something that
uses C++ destructors instead of g_autoptr, so perhaps we should consider
using std::lock_guard<>, or something like that, instead of
QEMU_LOCK_GUARD. It may be interesting to pass down lock_guards as
arguments to enforce "this lock is taken" invariants.
But really, coroutines would be enough work so my dish would be full for
some time and I wouldn't really have time to look at any of this. :)
Thanks,
Paolo
[1] One big advantage of STL containers for example is that
std::vector<> automatically constructs objects instead of just filling
memory with zero (or leaving it uninitialized). But that doesn't really
matter if we don't use classes with constructors.