diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2025-11-18 10:53:09 +0100 |
|---|---|---|
| committer | Ulf Hermann <ulf.hermann@qt.io> | 2025-11-28 15:41:49 +0100 |
| commit | e4db77906b3f8bdcbe2ee20ff62ad818c6817e24 (patch) | |
| tree | e924c17f3aa8e9fa07c168e50553e013740c0848 /src/qmlmodels/qqmltableinstancemodel.cpp | |
| parent | 985ff60882d8c1e461f387464ac3c29083088750 (diff) | |
QmlModels: Split QQmlDelegateModelItem::m_objectRef
We need strong references for the cases where we place guards on the
stack to prevent the deletion of the objects, and weak references we
hand out to the view. The views don't systematically track the objects
they hold and generally use a QPointer as second line of defence. In
certain cases we cannot avoid deleting objects that are in fact still
referenced as the clearObjectWeakReferences() call shows. If the
QQmlDelegateModel itself is deleted while some view still holds a weak
reference to an object, we cannot avoid deleting that object, no matter
if the view agrees.
Also, we can do with 16bit numbers for the references. The guards on the
stack are rather few and you'll overflow the stack before you hit the
16bit maximum. The references handed out to the views are generally one
or two per item.
Task-number: QTBUG-141963
Change-Id: Ifb79e993abcaf4c169b08641ebc2a6378e0a4776
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qmlmodels/qqmltableinstancemodel.cpp')
| -rw-r--r-- | src/qmlmodels/qqmltableinstancemodel.cpp | 25 |
1 files changed, 11 insertions, 14 deletions
diff --git a/src/qmlmodels/qqmltableinstancemodel.cpp b/src/qmlmodels/qqmltableinstancemodel.cpp index 5cd5d4be15..7c38ff4116 100644 --- a/src/qmlmodels/qqmltableinstancemodel.cpp +++ b/src/qmlmodels/qqmltableinstancemodel.cpp @@ -59,7 +59,8 @@ QQmlTableInstanceModel::~QQmlTableInstanceModel() // No item in m_modelItems should be referenced at this point. The view // should release all its items before it deletes this model. Only model items // that are still being incubated should be left for us to delete. - Q_ASSERT(modelItem->objectRef() == 0); + // We can't rely on that, though. So we only check the strong ref. + Q_ASSERT(modelItem->objectStrongRef() == 0); Q_ASSERT(modelItem->incubationTask()); // Check that we are not being deleted while we're // in the process of e.g emitting a created signal. @@ -130,12 +131,10 @@ QObject *QQmlTableInstanceModel::object(int index, QQmlIncubator::IncubationMode if (!modelItem) return nullptr; - if (QObject *object = modelItem->object()) { - // The model item has already been incubated. So - // just bump the ref-count and return it. - modelItem->referenceObject(); - return object; - } + // The model item has already been incubated. So + // just bump the ref-count and return it. + if (modelItem->object()) + return modelItem->referenceObjectWeak(); // The object is not ready, and needs to be incubated incubateModelItem(modelItem, incubationMode); @@ -145,11 +144,9 @@ QObject *QQmlTableInstanceModel::object(int index, QQmlIncubator::IncubationMode // Incubation is done, so the task should be removed Q_ASSERT(!modelItem->incubationTask()); - if (QObject *object = modelItem->object()) { - // Incubation was completed sync and successful - modelItem->referenceObject(); - return object; - } + // Incubation was completed sync and successful + if (modelItem->object()) + return modelItem->referenceObjectWeak(); // The object was incubated synchronously (otherwise we would return above). But since // we have no object, the incubation must have failed. And when we have no object, there @@ -171,7 +168,7 @@ QQmlInstanceModel::ReleaseFlags QQmlTableInstanceModel::release(QObject *object, Q_ASSERT(m_modelItems.contains(modelItem->modelIndex())); Q_ASSERT(m_modelItems[modelItem->modelIndex()]->object() == object); - if (!modelItem->releaseObject()) + if (!modelItem->releaseObjectWeak()) return QQmlDelegateModel::Referenced; if (modelItem->isScriptReferenced()) { @@ -213,7 +210,7 @@ void QQmlTableInstanceModel::dispose(QObject *object) auto modelItem = qvariant_cast<QQmlDelegateModelItem *>(object->property(kModelItemTag)); Q_ASSERT(modelItem); - modelItem->releaseObject(); + modelItem->releaseObjectWeak(); // The item is not referenced by anyone Q_ASSERT(!modelItem->isObjectReferenced()); |
