Why should you avoid nesting QEventLoops?

In his Qt event loop, a discussion of networks and I / O interfaces , Thiago Masiera mentions that QEventLoop nesting should be avoided:

QEventLoop - for nesting event loops ... Avoid it if you can, because it creates a number of problems: everything can happen again, new activations of sockets or timers that you did not expect.

Can someone expand what they mean? I support a lot of code that uses modal dialogs that internally set up a new event loop when exec() called, so I'm very interested to know what problems can do this.

+8
qt
source share
2 answers
  1. The nested event loop costs you 1–2 KB of the stack. It occupies 5% of the L1 data cache on typical 32 kilobyte L1 cache, give or take processors.

  2. It is able to re-enter any code already on the call stack. There is no guarantee that any of these codes has been designed for reuse. I'm talking about your code, not Qt code. It can re-enter the code that triggered this event loop, and if you do not explicitly control this recursion, there is no guarantee that you will not run out of stack space in the end.

  3. There are two places in current Qt where, due to long-standing API errors or platform inconsistencies, you should use exec nested dialogs: QDrag and the platform file (on some platforms). You just don't need to use it anywhere else. You do not need a nested event loop for non-platform modal dialogs.

  4. Re-entering the event loop is usually caused by writing pseudo-synchronous code in which someone complains about the alleged absence of yield() ( co_yield and co_await fell into C ++!), Hides one head in the sand and uses exec() instead. Such code usually ends with spaghetti with little taste and is not needed.

    For modern C ++, using C ++ 20 coroutines makes sense; there are several Qt-based experiments around that are easy to build.

    There are implementations of stack coroutines built into Qt: Skycoder42 / QtCoroutings is a recent project and an older ckamm / qt-coroutine . I'm not sure how recent the latest code is. It all seemed to work at some point.

    Pure writing of asynchronous code without coroutines is usually done using QStateMachine machines, see this answer for an example and the QP framework for an implementation other than QStateMachine .

Personal joke: I couldn’t wait for C ++ coroutines to be ready to work, and now I am writing an asynchronous communication code in golang and statically linking it to the Qt application. Works great, the garbage collector is invisible, and the code is much easier to read and write than C ++ with coroutines. I had a lot of code written using TS C ++ coroutines, but I moved it to golang and I do not regret it.

+9
source share

A nested event loop will order the inversion. (at least on qt4)

Suppose you have the following sequence of events:

 enqueued in outer loop: 1,2,3 processing 1 => spawn inner loop enqueue 4 in inner loop processing 4 exit inner loop processing 2 

So you see that the processing order: 1,4,2,3.

I speak from experience, and this usually led to a crash in my code.

0
source share

All Articles