I recently discovered [1] that Loader defers deletion of items via deleteLater(). Up until that point, I had been treating certain operations in my program as synchronous (as I haven't introduced threads yet). Now that I can't safely assume that UI items will be instantly destroyed, I have to convert these operations into asynchronous ones.
For example, previously, I had this code: game.quitGame(); My idea is to turn it into this: game.requestQuitGame(); Within this function, the Game object would set its "ready" property to false, emitting its associated property change signal so that Loaders can set active to false. Then, QMetaObject::invoke would be called with Qt::QueuedConnection to ensure that the Loader's deleteLater() calls would have been carried out *before* tearing down the game and its objects. In order to confirm that invokeMethod() works the way I thought it did, I added the following debug statements to QEventLoop: diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp index dca25ce..7dae9d0 100644 --- a/src/corelib/kernel/qeventloop.cpp +++ b/src/corelib/kernel/qeventloop.cpp @@ -151,6 +151,7 @@ bool QEventLoop::processEvents(ProcessEventsFlags flags) \sa QCoreApplication::quit(), exit(), processEvents() */ +#include <QDebug> int QEventLoop::exec(ProcessEventsFlags flags) { Q_D(QEventLoop); @@ -200,8 +201,11 @@ int QEventLoop::exec(ProcessEventsFlags flags) if (app && app->thread() == thread()) QCoreApplication::removePostedEvents(app, QEvent::Quit); - while (!d->exit.loadAcquire()) + while (!d->exit.loadAcquire()) { + qDebug() << Q_FUNC_INFO << "--- beginning event loop"; processEvents(flags | WaitForMoreEvents | EventLoopExec); + qDebug() << Q_FUNC_INFO << "--- ending event loop"; + } ref.exceptionCaught = false; return d->returnCode.load(); It turns out that I misunderstood the documentation; it only says that the slot is invoked when control returns to the event loop of the receiver's thread. So, as I understand it, it's possible that the invocation could happen *before* the deferred deletion of the Loaders' items. As the documentation doesn't specify the order between these two things, I should probably assume that it's not safe to assume anything. So, I'm left with the problem of how to ensure that a slot is invoked after the Loaders' items have been destroyed. My only thought is to use a zero-second single-shot timer. The question is: is this guaranteed to happen *after* deferred deletion for a given iteration of an event loop? I can't see such a guarantee in the documentation. I even checked the source code of e.g. qeventdispatcher_win.cpp to see if I could find anything, without success. Another question that's in the back of my mind is: is there a better way to do this? [1] https://bugreports.qt.io/browse/QTBUG-51995 [2] http://doc.qt.io/qt-5/qt.html#ConnectionType-enum _______________________________________________ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest