diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2019-03-27 16:03:57 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2019-03-28 12:37:41 +0000 |
commit | d10ddb040a0be1e179c60d0e364c7ab28b059e15 (patch) | |
tree | c527b8647511601bfd420ce84f39d3538d06b5be /src/qml/qml/qqmlglobal.cpp | |
parent | 0db3493107df8cf8a8f79dfee7a1c1f25b03c655 (diff) |
Make sure we can delete value type providers in any order
Previously the null provider had to be deleted last as it would leave a
dangling pointer in the global static. This meant that we could not
delete any other value providers on shutdown as the deletion order
between different Q_GLOBAL_STATICs is undefined.
Task-number: QTBUG-74348
Change-Id: I12aab6ab9ec4c71b90af69c5f824e0c6686433f5
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlglobal.cpp')
-rw-r--r-- | src/qml/qml/qqmlglobal.cpp | 62 |
1 files changed, 26 insertions, 36 deletions
diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp index 1d60c518c4..a10ded6487 100644 --- a/src/qml/qml/qqmlglobal.cpp +++ b/src/qml/qml/qqmlglobal.cpp @@ -231,57 +231,47 @@ bool QQmlValueTypeProvider::store(int, const void *, void *, size_t) { return fa bool QQmlValueTypeProvider::read(const QVariant&, void *, int) { return false; } bool QQmlValueTypeProvider::write(int, const void *, QVariant&) { return false; } -Q_GLOBAL_STATIC(QQmlValueTypeProvider, nullValueTypeProvider) -static QQmlValueTypeProvider *valueTypeProvider = nullptr; +struct ValueTypeProviderList { + QQmlValueTypeProvider nullProvider; + QQmlValueTypeProvider *head = &nullProvider; +}; -static QQmlValueTypeProvider **getValueTypeProvider(void) -{ - if (valueTypeProvider == nullptr) { - valueTypeProvider = nullValueTypeProvider; - } - - return &valueTypeProvider; -} +Q_GLOBAL_STATIC(ValueTypeProviderList, valueTypeProviders) Q_QML_PRIVATE_EXPORT void QQml_addValueTypeProvider(QQmlValueTypeProvider *newProvider) { - static QQmlValueTypeProvider **providerPtr = getValueTypeProvider(); - newProvider->next = *providerPtr; - *providerPtr = newProvider; + if (ValueTypeProviderList *providers = valueTypeProviders()) { + newProvider->next = providers->head; + providers->head = newProvider; + } } Q_QML_PRIVATE_EXPORT void QQml_removeValueTypeProvider(QQmlValueTypeProvider *oldProvider) { - if (oldProvider == nullValueTypeProvider) { - // don't remove the null provider - // we get here when the QtQml library is being unloaded - return; - } - - // the only entry with next = 0 is the null provider - Q_ASSERT(oldProvider->next); - - QQmlValueTypeProvider *prev = valueTypeProvider; - if (prev == oldProvider) { - valueTypeProvider = oldProvider->next; - return; - } + if (ValueTypeProviderList *providers = valueTypeProviders()) { + QQmlValueTypeProvider *prev = providers->head; + if (prev == oldProvider) { + providers->head = oldProvider->next; + return; + } - // singly-linked list removal - for ( ; prev; prev = prev->next) { - if (prev->next != oldProvider) - continue; // this is not the provider you're looking for - prev->next = oldProvider->next; - return; + // singly-linked list removal + for (; prev; prev = prev->next) { + if (prev->next != oldProvider) + continue; // this is not the provider you're looking for + prev->next = oldProvider->next; + return; + } } qWarning("QQml_removeValueTypeProvider: was asked to remove provider %p but it was not found", oldProvider); } -Q_AUTOTEST_EXPORT QQmlValueTypeProvider *QQml_valueTypeProvider(void) +Q_AUTOTEST_EXPORT QQmlValueTypeProvider *QQml_valueTypeProvider() { - static QQmlValueTypeProvider **providerPtr = getValueTypeProvider(); - return *providerPtr; + if (ValueTypeProviderList *providers = valueTypeProviders()) + return providers->head; + return nullptr; } QQmlColorProvider::~QQmlColorProvider() {} |