11
11
#include < qlist.h>
12
12
#include < qlogging.h>
13
13
#include < qloggingcategory.h>
14
+ #include < qnamespace.h>
14
15
#include < qobject.h>
15
16
#include < qqmlcontext.h>
16
17
#include < qqmlengine.h>
@@ -238,23 +239,24 @@ void EngineGeneration::onDirectoryChanged() {
238
239
void EngineGeneration::registerIncubationController (QQmlIncubationController* controller) {
239
240
// We only want controllers that we can swap out if destroyed.
240
241
// 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) {
249
244
qCWarning (logIncubator) << " Could not register incubation controller as it is not a QObject"
250
245
<< controller;
251
246
252
247
return ;
253
248
}
254
249
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 ;
258
260
259
261
// This function can run during destruction.
260
262
if (this ->engine == nullptr ) return ;
@@ -264,21 +266,25 @@ void EngineGeneration::registerIncubationController(QQmlIncubationController* co
264
266
}
265
267
}
266
268
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.
267
272
void 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) {
271
275
qCCritical (logIncubator) << " Deregistering incubation controller which is not a QObject, "
272
276
" however only QObject controllers should be registered." ;
273
277
}
274
278
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"
277
285
<< this << " as it was not registered to begin with" ;
278
286
qCCritical (logIncubator) << " Current registered incuabation controllers"
279
287
<< this ->incubationControllers ;
280
- } else {
281
- qCDebug (logIncubator) << " Deregistered incubation controller" << controller << " from" << this ;
282
288
}
283
289
284
290
// This function can run during destruction.
@@ -293,22 +299,12 @@ void EngineGeneration::deregisterIncubationController(QQmlIncubationController*
293
299
294
300
void EngineGeneration::incubationControllerDestroyed () {
295
301
auto * sender = this ->sender ();
296
- auto * controller = dynamic_cast <QQmlIncubationController*>(sender);
297
302
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"
309
305
<< this ;
310
306
} else {
311
- qCCritical (logIncubator) << " Destroyed incubation controller" << controller
307
+ qCCritical (logIncubator) << " Destroyed incubation controller" << sender
312
308
<< " was not registered, but its destruction was observed by" << this ;
313
309
314
310
return ;
@@ -317,7 +313,7 @@ void EngineGeneration::incubationControllerDestroyed() {
317
313
// This function can run during destruction.
318
314
if (this ->engine == nullptr ) return ;
319
315
320
- if (this ->engine ->incubationController () == controller ) {
316
+ if (dynamic_cast <QObject*>( this ->engine ->incubationController ()) == sender ) {
321
317
qCDebug (logIncubator
322
318
) << " Destroyed incubation controller was currently active, reassigning from pool" ;
323
319
this ->assignIncubationController ();
@@ -371,7 +367,7 @@ void EngineGeneration::assignIncubationController() {
371
367
if (this ->incubationControllersLocked || this ->incubationControllers .isEmpty ()) {
372
368
controller = &this ->delayedIncubationController ;
373
369
} else {
374
- controller = this ->incubationControllers .first ();
370
+ controller = dynamic_cast <QQmlIncubationController*>( this ->incubationControllers .first () );
375
371
}
376
372
377
373
qCDebug (logIncubator) << " Assigning incubation controller" << controller << " to generation"
0 commit comments