diff options
author | BogDan Vatra <bogdan@kdab.com> | 2018-10-05 14:13:51 +0300 |
---|---|---|
committer | Michael Brasser <michael.brasser@live.com> | 2018-10-09 15:48:02 +0000 |
commit | 09a6746ec6d2a21415f8e0b0a8817510f1b8b2e9 (patch) | |
tree | 73e0309917848d0cedb4d9e23bda12623cc148bc | |
parent | 0ebd459bf781ff22a4a0aac460c230874cc0fe52 (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.cpp | 48 | ||||
-rw-r--r-- | src/remoteobjects/qremoteobjectnode_p.h | 2 | ||||
-rw-r--r-- | tests/auto/integration_multiprocess/client/main.cpp | 19 |
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; }; |