@@ -117,7 +117,8 @@ void EngineGeneration::onReload(EngineGeneration* old) {
117
117
if (old != nullptr ) {
118
118
// if the old generation holds the window incubation controller as the
119
119
// new generation acquires it then incubators will hang intermittently
120
- old->incubationControllers .clear ();
120
+ qCDebug (logIncubator) << " Locking incubation controllers of old generation" << old;
121
+ old->incubationControllersLocked = true ;
121
122
old->assignIncubationController ();
122
123
}
123
124
@@ -200,27 +201,25 @@ void EngineGeneration::onDirectoryChanged() {
200
201
}
201
202
202
203
void EngineGeneration::registerIncubationController (QQmlIncubationController* controller) {
203
- auto * obj = dynamic_cast <QObject*>(controller);
204
-
205
204
// We only want controllers that we can swap out if destroyed.
206
205
// This happens if the window owning the active controller dies.
207
- if (obj == nullptr ) {
208
- qCDebug (logIncubator) << " Could not register incubation controller as it is not a QObject"
209
- << controller;
206
+ if (auto * obj = dynamic_cast <QObject*>(controller)) {
207
+ QObject::connect (
208
+ obj,
209
+ &QObject::destroyed,
210
+ this ,
211
+ &EngineGeneration::incubationControllerDestroyed
212
+ );
213
+ } else {
214
+ qCWarning (logIncubator) << " Could not register incubation controller as it is not a QObject"
215
+ << controller;
210
216
211
217
return ;
212
218
}
213
219
214
- this ->incubationControllers .push_back ({controller, obj});
215
-
216
- QObject::connect (
217
- obj,
218
- &QObject::destroyed,
219
- this ,
220
- &EngineGeneration::incubationControllerDestroyed
221
- );
222
-
223
- qCDebug (logIncubator) << " Registered incubation controller" << controller;
220
+ this ->incubationControllers .push_back (controller);
221
+ qCDebug (logIncubator) << " Registered incubation controller" << controller << " to generation"
222
+ << this ;
224
223
225
224
// This function can run during destruction.
226
225
if (this ->engine == nullptr ) return ;
@@ -231,22 +230,20 @@ void EngineGeneration::registerIncubationController(QQmlIncubationController* co
231
230
}
232
231
233
232
void EngineGeneration::deregisterIncubationController (QQmlIncubationController* controller) {
234
- QObject* obj = nullptr ;
235
- this ->incubationControllers .removeIf ([&](QPair<QQmlIncubationController*, QObject*> other) {
236
- if (controller == other.first ) {
237
- obj = other.second ;
238
- return true ;
239
- } else return false ;
240
- });
241
-
242
- if (obj == nullptr ) {
243
- qCWarning (logIncubator) << " Failed to deregister incubation controller" << controller
244
- << " as it was not registered to begin with" ;
245
- qCWarning (logIncubator) << " Current registered incuabation controllers"
246
- << this ->incubationControllers ;
247
- } else {
233
+ if (auto * obj = dynamic_cast <QObject*>(controller)) {
248
234
QObject::disconnect (obj, nullptr , this , nullptr );
249
- qCDebug (logIncubator) << " Deregistered incubation controller" << controller;
235
+ } else {
236
+ qCCritical (logIncubator) << " Deregistering incubation controller which is not a QObject, "
237
+ " however only QObject controllers should be registered." ;
238
+ }
239
+
240
+ if (!this ->incubationControllers .removeOne (controller)) {
241
+ qCCritical (logIncubator) << " Failed to deregister incubation controller" << controller << " from"
242
+ << this << " as it was not registered to begin with" ;
243
+ qCCritical (logIncubator) << " Current registered incuabation controllers"
244
+ << this ->incubationControllers ;
245
+ } else {
246
+ qCDebug (logIncubator) << " Deregistered incubation controller" << controller << " from" << this ;
250
247
}
251
248
252
249
// This function can run during destruction.
@@ -261,22 +258,25 @@ void EngineGeneration::deregisterIncubationController(QQmlIncubationController*
261
258
262
259
void EngineGeneration::incubationControllerDestroyed () {
263
260
auto * sender = this ->sender ();
264
- QQmlIncubationController* controller = nullptr ;
265
-
266
- this ->incubationControllers .removeIf ([&](QPair<QQmlIncubationController*, QObject*> other) {
267
- if (sender == other.second ) {
268
- controller = other.first ;
269
- return true ;
270
- } else return false ;
271
- });
261
+ auto * controller = dynamic_cast <QQmlIncubationController*>(sender);
272
262
273
263
if (controller == nullptr ) {
274
- qCCritical (logIncubator) << " Destroyed incubation controller" << this -> sender ()
275
- << " could not be identified , this may cause memory corruption" ;
264
+ qCCritical (logIncubator) << " Destroyed incubation controller" << sender
265
+ << " is not known to " << this << " , this may cause memory corruption" ;
276
266
qCCritical (logIncubator) << " Current registered incuabation controllers"
277
267
<< this ->incubationControllers ;
268
+
269
+ return ;
270
+ }
271
+
272
+ if (this ->incubationControllers .removeOne (controller)) {
273
+ qCDebug (logIncubator) << " Destroyed incubation controller" << controller << " deregistered from"
274
+ << this ;
278
275
} else {
279
- qCDebug (logIncubator) << " Destroyed incubation controller" << controller << " deregistered" ;
276
+ qCCritical (logIncubator) << " Destroyed incubation controller" << controller
277
+ << " was not registered, but its destruction was observed by" << this ;
278
+
279
+ return ;
280
280
}
281
281
282
282
// This function can run during destruction.
@@ -314,11 +314,16 @@ void EngineGeneration::exit(int code) {
314
314
315
315
void EngineGeneration::assignIncubationController () {
316
316
QQmlIncubationController* controller = nullptr ;
317
- if (this ->incubationControllers .isEmpty ()) controller = &this ->delayedIncubationController ;
318
- else controller = this ->incubationControllers .first ().first ;
319
317
320
- qCDebug (logIncubator) << " Assigning incubation controller to engine:" << controller
321
- << " fallback:" << (controller == &this ->delayedIncubationController );
318
+ if (this ->incubationControllersLocked || this ->incubationControllers .isEmpty ()) {
319
+ controller = &this ->delayedIncubationController ;
320
+ } else {
321
+ controller = this ->incubationControllers .first ();
322
+ }
323
+
324
+ qCDebug (logIncubator) << " Assigning incubation controller" << controller << " to generation"
325
+ << this
326
+ << " fallback:" << (controller == &this ->delayedIncubationController );
322
327
323
328
this ->engine ->setIncubationController (controller);
324
329
}
@@ -334,7 +339,8 @@ EngineGeneration* EngineGeneration::findEngineGeneration(const QQmlEngine* engin
334
339
}
335
340
336
341
EngineGeneration* EngineGeneration::findObjectGeneration (const QObject* object) {
337
- if (g_generations.size () == 1 ) return EngineGeneration::currentGeneration ();
342
+ // Objects can still attempt to find their generation after it has been destroyed.
343
+ // if (g_generations.size() == 1) return EngineGeneration::currentGeneration();
338
344
339
345
while (object != nullptr ) {
340
346
auto * context = QQmlEngine::contextForObject (object);
0 commit comments