aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlglobal.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2019-03-27 16:03:57 +0100
committerUlf Hermann <ulf.hermann@qt.io>2019-03-28 12:37:41 +0000
commitd10ddb040a0be1e179c60d0e364c7ab28b059e15 (patch)
treec527b8647511601bfd420ce84f39d3538d06b5be /src/qml/qml/qqmlglobal.cpp
parent0db3493107df8cf8a8f79dfee7a1c1f25b03c655 (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.cpp62
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() {}