summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBogDan Vatra <bogdan@kdab.com>2018-10-05 14:13:51 +0300
committerMichael Brasser <michael.brasser@live.com>2018-10-09 15:48:02 +0000
commit09a6746ec6d2a21415f8e0b0a8817510f1b8b2e9 (patch)
tree73e0309917848d0cedb4d9e23bda12623cc148bc
parent0ebd459bf781ff22a4a0aac460c230874cc0fe52 (diff)
Unregister types that are not neededv5.12.0-beta3v5.12.0-beta2
Change-Id: I370e462780e25b788afc599f03ef2189e41d6476 Reviewed-by: Michael Brasser <michael.brasser@live.com> Reviewed-by: Brett Stottlemyer <bstottle@ford.com>
-rw-r--r--src/remoteobjects/qremoteobjectnode.cpp48
-rw-r--r--src/remoteobjects/qremoteobjectnode_p.h2
-rw-r--r--tests/auto/integration_multiprocess/client/main.cpp19
3 files changed, 51 insertions, 18 deletions
diff --git a/src/remoteobjects/qremoteobjectnode.cpp b/src/remoteobjects/qremoteobjectnode.cpp
index d80cb15..424c837 100644
--- a/src/remoteobjects/qremoteobjectnode.cpp
+++ b/src/remoteobjects/qremoteobjectnode.cpp
@@ -62,6 +62,7 @@ using GadgetType = QVector<QVariant>;
using RegisteredType = QPair<GadgetType, std::shared_ptr<QMetaObject>>;
static QMutex s_managedTypesMutex;
static QHash<int, RegisteredType> s_managedTypes;
+static QHash<int, QSet<IoDeviceBase*>> s_trackedConnections;
static void GadgetsStaticMetacallFunction(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
@@ -628,12 +629,38 @@ const QMetaObject *QRemoteObjectMetaObjectManager::metaObjectForType(const QStri
return dynamicTypes.value(type);
}
-static int registerGadget(QRemoteObjectPackets::GadgetsData &gadgets, QByteArray typeName)
+static void trackConnection(int typeId, IoDeviceBase *connection)
+{
+ QMutexLocker lock(&s_managedTypesMutex);
+ if (s_trackedConnections[typeId].contains(connection))
+ return;
+ s_trackedConnections[typeId].insert(connection);
+ auto unregisterIfNotUsed = [typeId, connection]{
+ QMutexLocker lock(&s_managedTypesMutex);
+ Q_ASSERT(s_trackedConnections.contains(typeId));
+ Q_ASSERT(s_trackedConnections[typeId].contains(connection));
+ s_trackedConnections[typeId].remove(connection);
+ if (s_trackedConnections[typeId].isEmpty()) {
+ s_trackedConnections.remove(typeId);
+ s_managedTypes.remove(typeId);
+ QMetaType::unregisterType(typeId);
+ }
+ };
+
+ // Unregister the type only when the connection is destroyed
+ // Do not unregister types when the connections is discconected, because
+ // if it gets reconnected it will not register the types again
+ QObject::connect(connection, &IoDeviceBase::destroyed, unregisterIfNotUsed);
+}
+
+static int registerGadget(IoDeviceBase *connection, QRemoteObjectPackets::GadgetsData &gadgets, QByteArray typeName)
{
const auto &properties = gadgets.take(typeName);
int typeId = QMetaType::type(typeName);
- if (typeId != QMetaType::UnknownType)
+ if (typeId != QMetaType::UnknownType) {
+ trackConnection(typeId, connection);
return typeId;
+ }
QMetaObjectBuilder gadgetBuilder;
gadgetBuilder.setClassName(typeName);
@@ -642,7 +669,7 @@ static int registerGadget(QRemoteObjectPackets::GadgetsData &gadgets, QByteArray
for (const auto &prop : properties) {
int propertyType = QMetaType::type(prop.type);
if (!propertyType && gadgets.contains(prop.type))
- propertyType = registerGadget(gadgets, prop.type);
+ propertyType = registerGadget(connection, gadgets, prop.type);
gadgetType.push_back(QVariant(QVariant::Type(propertyType)));
auto dynamicProperty = gadgetBuilder.addProperty(prop.name, prop.type);
dynamicProperty.setWritable(true);
@@ -651,25 +678,26 @@ static int registerGadget(QRemoteObjectPackets::GadgetsData &gadgets, QByteArray
auto meta = gadgetBuilder.toMetaObject();
meta->d.static_metacall = &GadgetsStaticMetacallFunction;
meta->d.superdata = nullptr;
- const auto flags = QMetaType::WasDeclaredAsMetaType | QMetaType::IsGadget | QMetaType::NeedsConstruction | QMetaType::NeedsDestruction;
+ const auto flags = QMetaType::IsGadget | QMetaType::NeedsConstruction | QMetaType::NeedsDestruction;
int gadgetTypeId = QMetaType::registerType(typeName.constData(),
&GadgetTypedDestructor,
&GadgetTypedConstructor,
sizeof(GadgetType),
flags, meta);
QMetaType::registerStreamOperators(gadgetTypeId, &GadgetSaveOperator, &GadgetLoadOperator);
+ trackConnection(gadgetTypeId, connection);
QMutexLocker lock(&s_managedTypesMutex);
s_managedTypes[gadgetTypeId] = qMakePair(gadgetType, std::shared_ptr<QMetaObject>{meta, [](QMetaObject *ptr){ ::free(ptr); }});
return gadgetTypeId;
}
-static void registerAllGadgets(QRemoteObjectPackets::GadgetsData &gadgets)
+static void registerAllGadgets(IoDeviceBase *connection, QRemoteObjectPackets::GadgetsData &gadgets)
{
while (!gadgets.isEmpty())
- registerGadget(gadgets, gadgets.constBegin().key());
+ registerGadget(connection, gadgets, gadgets.constBegin().key());
}
-QMetaObject *QRemoteObjectMetaObjectManager::addDynamicType(QDataStream &in)
+QMetaObject *QRemoteObjectMetaObjectManager::addDynamicType(IoDeviceBase *connection, QDataStream &in)
{
QMetaObjectBuilder builder;
builder.setClassName("QRemoteObjectDynamicReplica");
@@ -724,7 +752,7 @@ QMetaObject *QRemoteObjectMetaObjectManager::addDynamicType(QDataStream &in)
properties.push_back(prop);
}
}
- registerAllGadgets(gadgets);
+ registerAllGadgets(connection, gadgets);
int curIndex = 0;
@@ -1102,7 +1130,7 @@ void QRemoteObjectNodePrivate::onClientRead(QObject *obj)
case InitDynamicPacket:
{
qROPrivDebug() << "InitDynamicPacket-->" << rxName << this;
- const QMetaObject *meta = dynamicTypeManager.addDynamicType(connection->stream());
+ const QMetaObject *meta = dynamicTypeManager.addDynamicType(connection, connection->stream());
deserializeInitPacket(connection->stream(), rxArgs);
QSharedPointer<QConnectedReplicaImplementation> rep = qSharedPointerCast<QConnectedReplicaImplementation>(replicas.value(rxName).toStrongRef());
if (rep)
@@ -1754,7 +1782,7 @@ QVariant QRemoteObjectNodePrivate::handlePointerToQObjectProperty(QConnectedRepl
childRep->setDynamicMetaObject(dynamicTypeManager.metaObjectForType(childInfo.typeName));
else {
QDataStream in(childInfo.classDefinition);
- childRep->setDynamicMetaObject(dynamicTypeManager.addDynamicType(in));
+ childRep->setDynamicMetaObject(dynamicTypeManager.addDynamicType(rep->connectionToSource, in));
}
handlePointerToQObjectProperties(childRep.data(), childInfo.parameters);
childRep->setDynamicProperties(childInfo.parameters);
diff --git a/src/remoteobjects/qremoteobjectnode_p.h b/src/remoteobjects/qremoteobjectnode_p.h
index 41d8562..2f30fc1 100644
--- a/src/remoteobjects/qremoteobjectnode_p.h
+++ b/src/remoteobjects/qremoteobjectnode_p.h
@@ -90,7 +90,7 @@ public:
~QRemoteObjectMetaObjectManager();
const QMetaObject *metaObjectForType(const QString &type);
- QMetaObject *addDynamicType(QDataStream &in);
+ QMetaObject *addDynamicType(IoDeviceBase* connection, QDataStream &in);
void addFromReplica(QConnectedReplicaImplementation *rep);
private:
diff --git a/tests/auto/integration_multiprocess/client/main.cpp b/tests/auto/integration_multiprocess/client/main.cpp
index 37812e9..b60a48a 100644
--- a/tests/auto/integration_multiprocess/client/main.cpp
+++ b/tests/auto/integration_multiprocess/client/main.cpp
@@ -39,8 +39,9 @@ class tst_Client_Process : public QObject
private Q_SLOTS:
void initTestCase()
{
- m_repNode.connectToNode(QUrl(QStringLiteral("tcp://127.0.0.1:65213")));
- m_rep.reset(m_repNode.acquire<MyInterfaceReplica>());
+ m_repNode.reset(new QRemoteObjectNode);
+ m_repNode->connectToNode(QUrl(QStringLiteral("tcp://127.0.0.1:65213")));
+ m_rep.reset(m_repNode->acquire<MyInterfaceReplica>());
QVERIFY(m_rep->waitForSource());
}
@@ -65,7 +66,7 @@ private Q_SLOTS:
void testEnumDetails()
{
QHash<QByteArray, int> kvs = {{"First", 0}, {"Second", 1}, {"Third", 2}};
- QScopedPointer<QRemoteObjectDynamicReplica> rep(m_repNode.acquireDynamic("MyInterface"));
+ QScopedPointer<QRemoteObjectDynamicReplica> rep(m_repNode->acquireDynamic("MyInterface"));
QVERIFY(rep->waitForSource());
auto mo = rep->metaObject();
@@ -92,7 +93,7 @@ private Q_SLOTS:
void testMethodSignalParamDetails()
{
- QScopedPointer<QRemoteObjectDynamicReplica> rep(m_repNode.acquireDynamic("MyInterface"));
+ QScopedPointer<QRemoteObjectDynamicReplica> rep(m_repNode->acquireDynamic("MyInterface"));
QVERIFY(rep->waitForSource());
auto mo = rep->metaObject();
@@ -140,7 +141,7 @@ private Q_SLOTS:
void testMethodSignal()
{
QScopedPointer<MyInterfaceReplica> rep(new MyInterfaceReplica());
- rep->setNode(&m_repNode);
+ rep->setNode(m_repNode.get());
QVERIFY(rep->waitForSource());
rep->testEnumParamsInSlots(MyInterfaceReplica::Second, false, 74);
@@ -154,7 +155,7 @@ private Q_SLOTS:
void testPod()
{
- QScopedPointer<QRemoteObjectDynamicReplica> podRep(m_repNode.acquireDynamic("PodInterface"));
+ QScopedPointer<QRemoteObjectDynamicReplica> podRep(m_repNode->acquireDynamic("PodInterface"));
QVERIFY(podRep->waitForSource());
QVariant value = podRep->property("myPod");
const QMetaObject *mo = QMetaType::metaObjectForType(value.userType());
@@ -177,10 +178,14 @@ private Q_SLOTS:
{
auto reply = m_rep->quit();
QVERIFY(reply.waitForFinished());
+ m_rep.reset();
+ QVERIFY(QMetaType::type("MyPOD") != QMetaType::UnknownType);
+ m_repNode.reset();
+ QVERIFY(QMetaType::type("MyPOD") == QMetaType::UnknownType);
}
private:
- QRemoteObjectNode m_repNode;
+ QScopedPointer<QRemoteObjectNode> m_repNode;
QScopedPointer<MyInterfaceReplica> m_rep;
};