Skip to content

Commit

Permalink
core/reloader: fix incubator warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
outfoxxed committed Nov 29, 2024
1 parent 8882f7c commit cb05e9a
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 48 deletions.
98 changes: 52 additions & 46 deletions src/core/generation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ void EngineGeneration::onReload(EngineGeneration* old) {
if (old != nullptr) {
// if the old generation holds the window incubation controller as the
// new generation acquires it then incubators will hang intermittently
old->incubationControllers.clear();
qCDebug(logIncubator) << "Locking incubation controllers of old generation" << old;
old->incubationControllersLocked = true;
old->assignIncubationController();
}

Expand Down Expand Up @@ -200,27 +201,25 @@ void EngineGeneration::onDirectoryChanged() {
}

void EngineGeneration::registerIncubationController(QQmlIncubationController* controller) {
auto* obj = dynamic_cast<QObject*>(controller);

// We only want controllers that we can swap out if destroyed.
// This happens if the window owning the active controller dies.
if (obj == nullptr) {
qCDebug(logIncubator) << "Could not register incubation controller as it is not a QObject"
<< controller;
if (auto* obj = dynamic_cast<QObject*>(controller)) {
QObject::connect(
obj,
&QObject::destroyed,
this,
&EngineGeneration::incubationControllerDestroyed
);
} else {
qCWarning(logIncubator) << "Could not register incubation controller as it is not a QObject"
<< controller;

return;
}

this->incubationControllers.push_back({controller, obj});

QObject::connect(
obj,
&QObject::destroyed,
this,
&EngineGeneration::incubationControllerDestroyed
);

qCDebug(logIncubator) << "Registered incubation controller" << controller;
this->incubationControllers.push_back(controller);
qCDebug(logIncubator) << "Registered incubation controller" << controller << "to generation"
<< this;

// This function can run during destruction.
if (this->engine == nullptr) return;
Expand All @@ -231,22 +230,20 @@ void EngineGeneration::registerIncubationController(QQmlIncubationController* co
}

void EngineGeneration::deregisterIncubationController(QQmlIncubationController* controller) {
QObject* obj = nullptr;
this->incubationControllers.removeIf([&](QPair<QQmlIncubationController*, QObject*> other) {
if (controller == other.first) {
obj = other.second;
return true;
} else return false;
});

if (obj == nullptr) {
qCWarning(logIncubator) << "Failed to deregister incubation controller" << controller
<< "as it was not registered to begin with";
qCWarning(logIncubator) << "Current registered incuabation controllers"
<< this->incubationControllers;
} else {
if (auto* obj = dynamic_cast<QObject*>(controller)) {
QObject::disconnect(obj, nullptr, this, nullptr);
qCDebug(logIncubator) << "Deregistered incubation controller" << controller;
} else {
qCCritical(logIncubator) << "Deregistering incubation controller which is not a QObject, "
"however only QObject controllers should be registered.";
}

if (!this->incubationControllers.removeOne(controller)) {
qCCritical(logIncubator) << "Failed to deregister incubation controller" << controller << "from"
<< this << "as it was not registered to begin with";
qCCritical(logIncubator) << "Current registered incuabation controllers"
<< this->incubationControllers;
} else {
qCDebug(logIncubator) << "Deregistered incubation controller" << controller << "from" << this;
}

// This function can run during destruction.
Expand All @@ -261,22 +258,25 @@ void EngineGeneration::deregisterIncubationController(QQmlIncubationController*

void EngineGeneration::incubationControllerDestroyed() {
auto* sender = this->sender();
QQmlIncubationController* controller = nullptr;

this->incubationControllers.removeIf([&](QPair<QQmlIncubationController*, QObject*> other) {
if (sender == other.second) {
controller = other.first;
return true;
} else return false;
});
auto* controller = dynamic_cast<QQmlIncubationController*>(sender);

if (controller == nullptr) {
qCCritical(logIncubator) << "Destroyed incubation controller" << this->sender()
<< "could not be identified, this may cause memory corruption";
qCCritical(logIncubator) << "Destroyed incubation controller" << sender << "is not known to"
<< this << ", this may cause memory corruption";
qCCritical(logIncubator) << "Current registered incuabation controllers"
<< this->incubationControllers;

return;
}

if (this->incubationControllers.removeOne(controller)) {
qCDebug(logIncubator) << "Destroyed incubation controller" << controller << "deregistered from"
<< this;
} else {
qCDebug(logIncubator) << "Destroyed incubation controller" << controller << "deregistered";
qCCritical(logIncubator) << "Destroyed incubation controller" << controller
<< "was not registered, but its destruction was observed by" << this;

return;
}

// This function can run during destruction.
Expand Down Expand Up @@ -314,10 +314,15 @@ void EngineGeneration::exit(int code) {

void EngineGeneration::assignIncubationController() {
QQmlIncubationController* controller = nullptr;
if (this->incubationControllers.isEmpty()) controller = &this->delayedIncubationController;
else controller = this->incubationControllers.first().first;

qCDebug(logIncubator) << "Assigning incubation controller to engine:" << controller
if (this->incubationControllersLocked || this->incubationControllers.isEmpty()) {
controller = &this->delayedIncubationController;
} else {
controller = this->incubationControllers.first();
}

qCDebug(logIncubator) << "Assigning incubation controller" << controller << "to generation"
<< this
<< "fallback:" << (controller == &this->delayedIncubationController);

this->engine->setIncubationController(controller);
Expand All @@ -334,7 +339,8 @@ EngineGeneration* EngineGeneration::findEngineGeneration(const QQmlEngine* engin
}

EngineGeneration* EngineGeneration::findObjectGeneration(const QObject* object) {
if (g_generations.size() == 1) return EngineGeneration::currentGeneration();
// Objects can still attempt to find their generation after it has been destroyed.
// if (g_generations.size() == 1) return EngineGeneration::currentGeneration();

while (object != nullptr) {
auto* context = QQmlEngine::contextForObject(object);
Expand Down
4 changes: 2 additions & 2 deletions src/core/generation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <qfilesystemwatcher.h>
#include <qhash.h>
#include <qobject.h>
#include <qpair.h>
#include <qqmlengine.h>
#include <qqmlincubator.h>
#include <qtclasshelpermacros.h>
Expand Down Expand Up @@ -84,7 +83,8 @@ private slots:
private:
void postReload();
void assignIncubationController();
QVector<QPair<QQmlIncubationController*, QObject*>> incubationControllers;
QVector<QQmlIncubationController*> incubationControllers;
bool incubationControllersLocked = false;
QHash<const void*, EngineGenerationExt*> extensions;

bool destroying = false;
Expand Down

0 comments on commit cb05e9a

Please sign in to comment.