[Development] QFuture and C++20

Ville Voutilainen ville.voutilainen at gmail.com
Thu Mar 4 14:37:01 CET 2021

On Thu, 4 Mar 2021 at 02:03, Jason H <jhihn at gmx.com> wrote:

> > The language parts are there in C++20; what's missing from the standard
> > library are "ready-made" coroutines types (task, generator, ...),
> > awaitable types, utility functions for scheduling execution, etc.
> >
> > I've been wondering for a little while how to integrate
> > signal/slots/exec()/etc. with coroutines.
> Really glad to hear that you're looking into it! I don't think Qt needs the ready-made types to target the async stuff?

We don't, we can write our own. Some thoughts:

1) if by "exec()" you mean things like QDialog::exec(), the problem
there is that It's Already A Coroutine. It's a stackful
coroutine. I don't know how to make it both stackful and stackless.
Suppose that we change it to return a type
that optionally suspends a coroutine. Then we have the following problem:

auto&& x = mah_dialog.exec();
co_await x;

There's about a billion things wrong there. The exec() should suspend
the fiber, but if it does, it can't be co_awaited
later. If it doesn't suspend the fiber, code following it will
continue to run, when it might expect exec() to suspend the fiber.
I don't know how to hack this into the hypothetical return type of
exec(), because the decision to suspend the fiber
shouldn't wait until there's an initial_suspend or destruction
happening. So that decision would be postponed to be too
late, or would happen too early. There's no winning this, so an
awaitable exec() needs to be await_exec() or async_exec(),
name it what you want, but make it separate.

2) co_awaiting signals shouldn't be too hard. At least in theory, I
haven't tried implementing it. You basically make your promise
type a slot, and connect it to the signal, and then suspend. And when
the slot is called, you resume the coroutine, and suspend again.
This seems eminently doable. It does require additional wrapping; you
can't just co_await a pointer-to-member-function, you need
to wrap it in this promise type and then co_await on that, but that
wrapping should be fairly simple, it just needs both the object
and the signal.

More information about the Development mailing list