1111#include < qlist.h>
1212#include < qlogging.h>
1313#include < qloggingcategory.h>
14+ #include < qnamespace.h>
1415#include < qobject.h>
1516#include < qqmlcontext.h>
1617#include < qqmlengine.h>
@@ -238,23 +239,24 @@ void EngineGeneration::onDirectoryChanged() {
238239void EngineGeneration::registerIncubationController (QQmlIncubationController* controller) {
239240 // We only want controllers that we can swap out if destroyed.
240241 // This happens if the window owning the active controller dies.
241- if (auto * obj = dynamic_cast <QObject*>(controller)) {
242- QObject::connect (
243- obj,
244- &QObject::destroyed,
245- this ,
246- &EngineGeneration::incubationControllerDestroyed
247- );
248- } else {
242+ auto * obj = dynamic_cast <QObject*>(controller);
243+ if (!obj) {
249244 qCWarning (logIncubator) << " Could not register incubation controller as it is not a QObject"
250245 << controller;
251246
252247 return ;
253248 }
254249
255- this ->incubationControllers .push_back (controller);
256- qCDebug (logIncubator) << " Registered incubation controller" << controller << " to generation"
257- << this ;
250+ QObject::connect (
251+ obj,
252+ &QObject::destroyed,
253+ this ,
254+ &EngineGeneration::incubationControllerDestroyed,
255+ Qt::UniqueConnection
256+ );
257+
258+ this ->incubationControllers .push_back (obj);
259+ qCDebug (logIncubator) << " Registered incubation controller" << obj << " to generation" << this ;
258260
259261 // This function can run during destruction.
260262 if (this ->engine == nullptr ) return ;
@@ -264,21 +266,25 @@ void EngineGeneration::registerIncubationController(QQmlIncubationController* co
264266 }
265267}
266268
269+ // Multiple controllers may be destroyed at once. Dynamic casts must be performed before working
270+ // with any controllers. The QQmlIncubationController destructor will already have run by the
271+ // point QObject::destroyed is called, so we can't cast to that.
267272void EngineGeneration::deregisterIncubationController (QQmlIncubationController* controller) {
268- if (auto * obj = dynamic_cast <QObject*>(controller)) {
269- QObject::disconnect (obj, nullptr , this , nullptr );
270- } else {
273+ auto * obj = dynamic_cast <QObject*>(controller);
274+ if (!obj) {
271275 qCCritical (logIncubator) << " Deregistering incubation controller which is not a QObject, "
272276 " however only QObject controllers should be registered." ;
273277 }
274278
275- if (!this ->incubationControllers .removeOne (controller)) {
276- qCCritical (logIncubator) << " Failed to deregister incubation controller" << controller << " from"
279+ QObject::disconnect (obj, nullptr , this , nullptr );
280+
281+ if (this ->incubationControllers .removeOne (obj)) {
282+ qCDebug (logIncubator) << " Deregistered incubation controller" << obj << " from" << this ;
283+ } else {
284+ qCCritical (logIncubator) << " Failed to deregister incubation controller" << obj << " from"
277285 << this << " as it was not registered to begin with" ;
278286 qCCritical (logIncubator) << " Current registered incuabation controllers"
279287 << this ->incubationControllers ;
280- } else {
281- qCDebug (logIncubator) << " Deregistered incubation controller" << controller << " from" << this ;
282288 }
283289
284290 // This function can run during destruction.
@@ -293,22 +299,12 @@ void EngineGeneration::deregisterIncubationController(QQmlIncubationController*
293299
294300void EngineGeneration::incubationControllerDestroyed () {
295301 auto * sender = this ->sender ();
296- auto * controller = dynamic_cast <QQmlIncubationController*>(sender);
297302
298- if (controller == nullptr ) {
299- qCCritical (logIncubator) << " Destroyed incubation controller" << sender << " is not known to"
300- << this << " , this may cause memory corruption" ;
301- qCCritical (logIncubator) << " Current registered incuabation controllers"
302- << this ->incubationControllers ;
303-
304- return ;
305- }
306-
307- if (this ->incubationControllers .removeOne (controller)) {
308- qCDebug (logIncubator) << " Destroyed incubation controller" << controller << " deregistered from"
303+ if (this ->incubationControllers .removeAll (sender) != 0 ) {
304+ qCDebug (logIncubator) << " Destroyed incubation controller" << sender << " deregistered from"
309305 << this ;
310306 } else {
311- qCCritical (logIncubator) << " Destroyed incubation controller" << controller
307+ qCCritical (logIncubator) << " Destroyed incubation controller" << sender
312308 << " was not registered, but its destruction was observed by" << this ;
313309
314310 return ;
@@ -317,7 +313,7 @@ void EngineGeneration::incubationControllerDestroyed() {
317313 // This function can run during destruction.
318314 if (this ->engine == nullptr ) return ;
319315
320- if (this ->engine ->incubationController () == controller ) {
316+ if (dynamic_cast <QObject*>( this ->engine ->incubationController ()) == sender ) {
321317 qCDebug (logIncubator
322318 ) << " Destroyed incubation controller was currently active, reassigning from pool" ;
323319 this ->assignIncubationController ();
@@ -371,7 +367,7 @@ void EngineGeneration::assignIncubationController() {
371367 if (this ->incubationControllersLocked || this ->incubationControllers .isEmpty ()) {
372368 controller = &this ->delayedIncubationController ;
373369 } else {
374- controller = this ->incubationControllers .first ();
370+ controller = dynamic_cast <QQmlIncubationController*>( this ->incubationControllers .first () );
375371 }
376372
377373 qCDebug (logIncubator) << " Assigning incubation controller" << controller << " to generation"
0 commit comments