diff options
Diffstat (limited to 'src/qml/qml/qqmlnotifier.cpp')
-rw-r--r-- | src/qml/qml/qqmlnotifier.cpp | 56 |
1 files changed, 39 insertions, 17 deletions
diff --git a/src/qml/qml/qqmlnotifier.cpp b/src/qml/qml/qqmlnotifier.cpp index 4ce5be4d1a..ea3f7a1530 100644 --- a/src/qml/qml/qqmlnotifier.cpp +++ b/src/qml/qml/qqmlnotifier.cpp @@ -51,30 +51,52 @@ static Callback QQmlNotifier_callbacks[] = { QQmlVMEMetaObjectEndpoint_callback }; +namespace { + struct NotifyListTraversalData { + NotifyListTraversalData(QQmlNotifierEndpoint *ep = 0) + : originalSenderPtr(0) + , disconnectWatch(0) + , endpoint(ep) + {} + + qintptr originalSenderPtr; + qintptr *disconnectWatch; + QQmlNotifierEndpoint *endpoint; + }; +} + void QQmlNotifier::emitNotify(QQmlNotifierEndpoint *endpoint, void **a) { - qintptr originalSenderPtr; - qintptr *disconnectWatch; - - if (!endpoint->isNotifying()) { - originalSenderPtr = endpoint->senderPtr; - disconnectWatch = &originalSenderPtr; - endpoint->senderPtr = qintptr(disconnectWatch) | 0x1; - } else { - disconnectWatch = (qintptr *)(endpoint->senderPtr & ~0x1); + QVarLengthArray<NotifyListTraversalData> stack; + while (endpoint) { + stack.append(NotifyListTraversalData(endpoint)); + endpoint = endpoint->next; } - if (endpoint->next) - emitNotify(endpoint->next, a); + int i = 0; + for (; i < stack.size(); ++i) { + NotifyListTraversalData &data = stack[i]; + + if (!data.endpoint->isNotifying()) { + data.originalSenderPtr = data.endpoint->senderPtr; + data.disconnectWatch = &data.originalSenderPtr; + data.endpoint->senderPtr = qintptr(data.disconnectWatch) | 0x1; + } else { + data.disconnectWatch = (qintptr *)(data.endpoint->senderPtr & ~0x1); + } + } - if (*disconnectWatch) { + while (--i >= 0) { + const NotifyListTraversalData &data = stack.at(i); + if (*data.disconnectWatch) { - Q_ASSERT(QQmlNotifier_callbacks[endpoint->callback]); - QQmlNotifier_callbacks[endpoint->callback](endpoint, a); + Q_ASSERT(QQmlNotifier_callbacks[data.endpoint->callback]); + QQmlNotifier_callbacks[data.endpoint->callback](data.endpoint, a); - if (disconnectWatch == &originalSenderPtr && originalSenderPtr) { - // End of notifying, restore values - endpoint->senderPtr = originalSenderPtr; + if (data.disconnectWatch == &data.originalSenderPtr && data.originalSenderPtr) { + // End of notifying, restore values + data.endpoint->senderPtr = data.originalSenderPtr; + } } } } |