diff options
author | Lars Knoll <lars.knoll@theqtcompany.com> | 2015-04-21 16:42:56 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2015-06-10 07:55:36 +0000 |
commit | 37d02d62d8d14fdaa0884f96f7840661413a95c2 (patch) | |
tree | 8e3f3dd9dafd574b99ca686e657d7e73f8f7eef5 /src/qml/qml/qqmlabstractbinding.cpp | |
parent | eb7db5934b453eea2946ed7ae9a188c44467cf23 (diff) |
Make bindings refcounted
Refcounting our bindings greatly simplifies our memory management
of the objects and ensures we safely clean them all up. In addition,
it allows us to remove the m_mePtr and weak reference handling from
QQmlAbstractBinding as we can safely handle this through the same
mechanism.
Change-Id: If23ebc8be276096146952b0008b62018f5d57faf
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
Diffstat (limited to 'src/qml/qml/qqmlabstractbinding.cpp')
-rw-r--r-- | src/qml/qml/qqmlabstractbinding.cpp | 78 |
1 files changed, 35 insertions, 43 deletions
diff --git a/src/qml/qml/qqmlabstractbinding.cpp b/src/qml/qml/qqmlabstractbinding.cpp index 4a081ae0e8..0d281b7750 100644 --- a/src/qml/qml/qqmlabstractbinding.cpp +++ b/src/qml/qml/qqmlabstractbinding.cpp @@ -40,15 +40,17 @@ QT_BEGIN_NAMESPACE QQmlAbstractBinding::QQmlAbstractBinding() - : m_nextBinding(0) + : m_nextBinding(0), + m_targetIndex(-1), + m_isAddedToObject(false) { + Q_ASSERT(!isAddedToObject()); } QQmlAbstractBinding::~QQmlAbstractBinding() { - Q_ASSERT(isAddedToObject() == false); - Q_ASSERT(nextBinding() == 0); - Q_ASSERT(*m_mePtr == 0); + Q_ASSERT(!ref); + Q_ASSERT(!isAddedToObject()); } /*! @@ -92,12 +94,17 @@ void QQmlAbstractBinding::addToObject() proxy->addToObject(); } - setNextBinding(proxy->m_bindings); + setNextBinding(proxy->m_bindings.data()); proxy->m_bindings = this; } else { setNextBinding(data->bindings); + if (data->bindings) { + data->bindings->ref.deref(); + Q_ASSERT(data->bindings->ref.refCount > 0); + } data->bindings = this; + ref.ref(); data->setBindingBit(obj, coreIndex); } @@ -113,10 +120,16 @@ void QQmlAbstractBinding::removeFromObject() if (!isAddedToObject()) return; + setAddedToObject(false); + QObject *obj = targetObject(); QQmlData *data = QQmlData::get(obj, false); Q_ASSERT(data); + QQmlAbstractBinding::Ptr next; + next = nextBinding(); + setNextBinding(0); + int coreIndex; if (QQmlPropertyData::decodeValueTypePropertyIndex(targetPropertyIndex(), &coreIndex) != -1) { @@ -131,39 +144,39 @@ void QQmlAbstractBinding::removeFromObject() QQmlValueTypeProxyBinding *vtproxybinding = static_cast<QQmlValueTypeProxyBinding *>(vtbinding); - QQmlAbstractBinding *binding = vtproxybinding->m_bindings; + QQmlAbstractBinding *binding = vtproxybinding->m_bindings.data(); if (binding == this) { - vtproxybinding->m_bindings = nextBinding(); + vtproxybinding->m_bindings = next; } else { while (binding->nextBinding() != this) { binding = binding->nextBinding(); Q_ASSERT(binding); } - binding->setNextBinding(nextBinding()); + binding->setNextBinding(next.data()); } // Value type - we don't remove the proxy from the object. It will sit their happily // doing nothing until it is removed by a write, a binding change or it is reused // to hold more sub-bindings. + return; + } + if (data->bindings == this) { + if (next.data()) + next->ref.ref(); + data->bindings = next.data(); + if (!ref.deref()) + delete this; } else { - - if (data->bindings == this) { - data->bindings = nextBinding(); - } else { - QQmlAbstractBinding *binding = data->bindings; - while (binding->nextBinding() != this) { - binding = binding->nextBinding(); - Q_ASSERT(binding); - } - binding->setNextBinding(nextBinding()); + QQmlAbstractBinding *binding = data->bindings; + while (binding->nextBinding() != this) { + binding = binding->nextBinding(); + Q_ASSERT(binding); } - - data->clearBindingBit(coreIndex); + binding->setNextBinding(next.data()); } - setNextBinding(0); - setAddedToObject(false); + data->clearBindingBit(coreIndex); } void QQmlAbstractBinding::printBindingLoopError(QQmlProperty &prop) @@ -171,27 +184,6 @@ void QQmlAbstractBinding::printBindingLoopError(QQmlProperty &prop) qmlInfo(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name()); } - -static void bindingDummyDeleter(QQmlAbstractBinding *) -{ -} - -QQmlAbstractBinding::Pointer QQmlAbstractBinding::weakPointer() -{ - if (m_mePtr.value().isNull()) - m_mePtr.value() = QSharedPointer<QQmlAbstractBinding>(this, bindingDummyDeleter); - - return m_mePtr.value().toWeakRef(); -} - -void QQmlAbstractBinding::clear() -{ - if (!m_mePtr.isNull()) { - **m_mePtr = 0; - m_mePtr = 0; - } -} - QString QQmlAbstractBinding::expression() const { return QLatin1String("<Unknown>"); |