aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/qml/qqmlmetatype.cpp124
-rw-r--r--src/qml/qml/qqmltypemodule.cpp63
-rw-r--r--src/qml/qml/qqmltypemodule_p.h20
-rw-r--r--src/qml/qml/qqmltypemodule_p_p.h24
4 files changed, 123 insertions, 108 deletions
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 34412a5fcb..8c3717844c 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -253,7 +253,7 @@ bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *da
versionedUri.uri = nameSpace;
versionedUri.majorVersion = majorVersion;
if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)){
- if (QQmlTypeModulePrivate::get(qqtm)->locked){
+ if (qqtm->isLocked()){
QString failure(QCoreApplication::translate("qmlRegisterType",
"Cannot install %1 '%2' into protected module '%3' version '%4'"));
data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType)).arg(typeName).arg(nameSpace).arg(majorVersion));
@@ -272,8 +272,7 @@ QQmlTypeModule *getTypeModule(const QHashedString &uri, int majorVersion, QQmlMe
QQmlMetaTypeData::VersionedUri versionedUri(uri, majorVersion);
QQmlTypeModule *module = data->uriToModule.value(versionedUri);
if (!module) {
- module = new QQmlTypeModule;
- module->d->uri = versionedUri;
+ module = new QQmlTypeModule(versionedUri.uri, versionedUri.majorVersion);
data->uriToModule.insert(versionedUri, module);
}
return module;
@@ -309,7 +308,7 @@ void addTypeToData(QQmlTypePrivate *type, QQmlMetaTypeData *data)
QQmlTypeModule *module = getTypeModule(mod, type->version_maj, data);
Q_ASSERT(module);
- module->d->add(type);
+ module->add(type);
}
}
@@ -447,7 +446,7 @@ bool QQmlMetaType::protectModule(const char *uri, int majVersion)
versionedUri.majorVersion = majVersion;
if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)) {
- QQmlTypeModulePrivate::get(qqtm)->locked = true;
+ qqtm->lock();
return true;
}
return false;
@@ -460,9 +459,7 @@ void QQmlMetaType::registerModule(const char *uri, int versionMajor, int version
QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), versionMajor, data);
Q_ASSERT(module);
- QQmlTypeModulePrivate *p = QQmlTypeModulePrivate::get(module);
- p->minMinorVersion = qMin(p->minMinorVersion, versionMinor);
- p->maxMinorVersion = qMax(p->maxMinorVersion, versionMinor);
+ module->addMinorVersion(versionMinor);
}
int QQmlMetaType::typeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
@@ -543,7 +540,7 @@ bool QQmlMetaType::isLockedModule(const QString &uri, int majVersion)
versionedUri.uri = uri;
versionedUri.majorVersion = majVersion;
if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0))
- return QQmlTypeModulePrivate::get(qqtm)->locked;
+ return qqtm->isLocked();
return false;
}
@@ -900,20 +897,15 @@ QQmlPropertyCache *QQmlMetaType::propertyCache(const QQmlType &type, int minorVe
void QQmlMetaType::unregisterType(int typeIndex)
{
QQmlMetaTypeDataPtr data;
- {
- const QQmlTypePrivate *d = data->types.value(typeIndex).priv();
- if (d) {
- removeQQmlTypePrivate(data->idToType, d);
- removeQQmlTypePrivate(data->nameToType, d);
- removeQQmlTypePrivate(data->urlToType, d);
- removeQQmlTypePrivate(data->urlToNonFileImportType, d);
- removeQQmlTypePrivate(data->metaObjectToType, d);
- for (QQmlMetaTypeData::TypeModules::Iterator module = data->uriToModule.begin(); module != data->uriToModule.end(); ++module) {
- QQmlTypeModulePrivate *modulePrivate = (*module)->priv();
- modulePrivate->remove(d);
- }
- data->types[typeIndex] = QQmlType();
- }
+ if (const QQmlTypePrivate *d = data->types.value(typeIndex).priv()) {
+ removeQQmlTypePrivate(data->idToType, d);
+ removeQQmlTypePrivate(data->nameToType, d);
+ removeQQmlTypePrivate(data->urlToType, d);
+ removeQQmlTypePrivate(data->urlToNonFileImportType, d);
+ removeQQmlTypePrivate(data->metaObjectToType, d);
+ for (auto & module : data->uriToModule)
+ module->remove(d);
+ data->types[typeIndex] = QQmlType();
}
}
@@ -921,54 +913,48 @@ void QQmlMetaType::freeUnusedTypesAndCaches()
{
QQmlMetaTypeDataPtr data;
- {
- bool deletedAtLeastOneType;
- do {
- deletedAtLeastOneType = false;
- QList<QQmlType>::Iterator it = data->types.begin();
- while (it != data->types.end()) {
- const QQmlTypePrivate *d = (*it).priv();
- if (d && d->refCount == 1) {
- deletedAtLeastOneType = true;
-
- removeQQmlTypePrivate(data->idToType, d);
- removeQQmlTypePrivate(data->nameToType, d);
- removeQQmlTypePrivate(data->urlToType, d);
- removeQQmlTypePrivate(data->urlToNonFileImportType, d);
- removeQQmlTypePrivate(data->metaObjectToType, d);
-
- for (QQmlMetaTypeData::TypeModules::Iterator module = data->uriToModule.begin(); module != data->uriToModule.end(); ++module) {
- QQmlTypeModulePrivate *modulePrivate = (*module)->priv();
- modulePrivate->remove(d);
- }
-
- *it = QQmlType();
- } else {
- ++it;
- }
+ bool deletedAtLeastOneType;
+ do {
+ deletedAtLeastOneType = false;
+ QList<QQmlType>::Iterator it = data->types.begin();
+ while (it != data->types.end()) {
+ const QQmlTypePrivate *d = (*it).priv();
+ if (d && d->refCount == 1) {
+ deletedAtLeastOneType = true;
+
+ removeQQmlTypePrivate(data->idToType, d);
+ removeQQmlTypePrivate(data->nameToType, d);
+ removeQQmlTypePrivate(data->urlToType, d);
+ removeQQmlTypePrivate(data->urlToNonFileImportType, d);
+ removeQQmlTypePrivate(data->metaObjectToType, d);
+
+ for (auto &module : data->uriToModule)
+ module->remove(d);
+
+ *it = QQmlType();
+ } else {
+ ++it;
}
- } while (deletedAtLeastOneType);
- }
-
- {
- bool deletedAtLeastOneCache;
- do {
- deletedAtLeastOneCache = false;
- QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator it = data->propertyCaches.begin();
- while (it != data->propertyCaches.end()) {
-
- if ((*it)->count() == 1) {
- QQmlPropertyCache *pc = nullptr;
- qSwap(pc, *it);
- it = data->propertyCaches.erase(it);
- pc->release();
- deletedAtLeastOneCache = true;
- } else {
- ++it;
- }
+ }
+ } while (deletedAtLeastOneType);
+
+ bool deletedAtLeastOneCache;
+ do {
+ deletedAtLeastOneCache = false;
+ QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator it = data->propertyCaches.begin();
+ while (it != data->propertyCaches.end()) {
+
+ if ((*it)->count() == 1) {
+ QQmlPropertyCache *pc = nullptr;
+ qSwap(pc, *it);
+ it = data->propertyCaches.erase(it);
+ pc->release();
+ deletedAtLeastOneCache = true;
+ } else {
+ ++it;
}
- } while (deletedAtLeastOneCache);
- }
+ }
+ } while (deletedAtLeastOneCache);
}
/*!
diff --git a/src/qml/qml/qqmltypemodule.cpp b/src/qml/qml/qqmltypemodule.cpp
index 05264abb1d..4d7553fbab 100644
--- a/src/qml/qml/qqmltypemodule.cpp
+++ b/src/qml/qml/qqmltypemodule.cpp
@@ -45,46 +45,60 @@
QT_BEGIN_NAMESPACE
-QQmlTypeModule::QQmlTypeModule()
- : d(new QQmlTypeModulePrivate)
+QQmlTypeModule::QQmlTypeModule(const QString &module, int majorVersion)
+ : d(new QQmlTypeModulePrivate(module, majorVersion))
{
}
QQmlTypeModule::~QQmlTypeModule()
{
- delete d; d = nullptr;
+ delete d;
}
QString QQmlTypeModule::module() const
{
- return d->uri.uri;
+ // No need to lock. d->module is const
+ return d->module;
}
int QQmlTypeModule::majorVersion() const
{
- return d->uri.majorVersion;
+ // No need to lock. d->majorVersion is const
+ return d->majorVersion;
}
int QQmlTypeModule::minimumMinorVersion() const
{
- return d->minMinorVersion;
+ return d->minMinorVersion.load();
}
int QQmlTypeModule::maximumMinorVersion() const
{
- return d->maxMinorVersion;
+ return d->maxMinorVersion.load();
}
-void QQmlTypeModulePrivate::add(QQmlTypePrivate *type)
+void QQmlTypeModule::addMinorVersion(int version)
{
- int minVersion = type->version_min;
- minMinorVersion = qMin(minMinorVersion, minVersion);
- maxMinorVersion = qMax(maxMinorVersion, minVersion);
+ for (int oldVersion = d->minMinorVersion.load();
+ oldVersion > version && !d->minMinorVersion.testAndSetOrdered(oldVersion, version);
+ oldVersion = d->minMinorVersion.load()) {
+ }
+
+ for (int oldVersion = d->maxMinorVersion.load();
+ oldVersion < version && !d->maxMinorVersion.testAndSetOrdered(oldVersion, version);
+ oldVersion = d->maxMinorVersion.load()) {
+ }
+}
- QList<QQmlTypePrivate *> &list = typeHash[type->elementName];
+void QQmlTypeModule::add(QQmlTypePrivate *type)
+{
+ QMutexLocker lock(&d->mutex);
+ addMinorVersion(type->version_min);
+
+ QList<QQmlTypePrivate *> &list = d->typeHash[type->elementName];
for (int ii = 0; ii < list.count(); ++ii) {
Q_ASSERT(list.at(ii));
- if (list.at(ii)->version_min < minVersion) {
+ if (list.at(ii)->version_min < type->version_min) {
list.insert(ii, type);
return;
}
@@ -92,9 +106,10 @@ void QQmlTypeModulePrivate::add(QQmlTypePrivate *type)
list.append(type);
}
-void QQmlTypeModulePrivate::remove(const QQmlTypePrivate *type)
+void QQmlTypeModule::remove(const QQmlTypePrivate *type)
{
- for (TypeHash::MutableIterator elementIt = typeHash.begin(); elementIt != typeHash.end();) {
+ QMutexLocker lock(&d->mutex);
+ for (auto elementIt = d->typeHash.begin(); elementIt != d->typeHash.end();) {
QQmlMetaType::removeQQmlTypePrivate(elementIt.value(), type);
#if 0
@@ -108,10 +123,19 @@ void QQmlTypeModulePrivate::remove(const QQmlTypePrivate *type)
}
}
-QQmlType QQmlTypeModule::type(const QHashedStringRef &name, int minor) const
+bool QQmlTypeModule::isLocked() const
{
- QMutexLocker lock(QQmlMetaType::typeRegistrationLock());
+ return d->locked.load() != 0;
+}
+
+void QQmlTypeModule::lock()
+{
+ d->locked.store(1);
+}
+QQmlType QQmlTypeModule::type(const QHashedStringRef &name, int minor) const
+{
+ QMutexLocker lock(&d->mutex);
QList<QQmlTypePrivate *> *types = d->typeHash.value(name);
if (types) {
for (int ii = 0; ii < types->count(); ++ii)
@@ -124,8 +148,7 @@ QQmlType QQmlTypeModule::type(const QHashedStringRef &name, int minor) const
QQmlType QQmlTypeModule::type(const QV4::String *name, int minor) const
{
- QMutexLocker lock(QQmlMetaType::typeRegistrationLock());
-
+ QMutexLocker lock(&d->mutex);
QList<QQmlTypePrivate *> *types = d->typeHash.value(name);
if (types) {
for (int ii = 0; ii < types->count(); ++ii)
@@ -138,7 +161,7 @@ QQmlType QQmlTypeModule::type(const QV4::String *name, int minor) const
void QQmlTypeModule::walkCompositeSingletons(const std::function<void(const QQmlType &)> &callback) const
{
- QMutexLocker lock(QQmlMetaType::typeRegistrationLock());
+ QMutexLocker lock(&d->mutex);
for (auto typeCandidates = d->typeHash.begin(), end = d->typeHash.end();
typeCandidates != end; ++typeCandidates) {
for (auto type: typeCandidates.value()) {
diff --git a/src/qml/qml/qqmltypemodule_p.h b/src/qml/qml/qqmltypemodule_p.h
index 6107988a70..b84a91b5db 100644
--- a/src/qml/qml/qqmltypemodule_p.h
+++ b/src/qml/qml/qqmltypemodule_p.h
@@ -72,9 +72,19 @@ class QQmlTypeModulePrivate;
class QQmlTypeModule
{
public:
+ QQmlTypeModule(const QString &uri = QString(), int majorVersion = 0);
+ ~QQmlTypeModule();
+
+ void add(QQmlTypePrivate *);
+ void remove(const QQmlTypePrivate *type);
+
+ bool isLocked() const;
+ void lock();
+
QString module() const;
int majorVersion() const;
+ void addMinorVersion(int minorVersion);
int minimumMinorVersion() const;
int maximumMinorVersion() const;
@@ -83,17 +93,7 @@ public:
void walkCompositeSingletons(const std::function<void(const QQmlType &)> &callback) const;
- QQmlTypeModulePrivate *priv() { return d; }
private:
- //Used by register functions and creates the QQmlTypeModule for them
- friend QQmlTypeModule *getTypeModule(const QHashedString &uri, int majorVersion, QQmlMetaTypeData *data);
- friend void addTypeToData(QQmlTypePrivate *type, QQmlMetaTypeData *data);
- friend struct QQmlMetaTypeData;
- friend class QQmlMetaType;
- friend class QQmlTypeModulePrivate;
-
- QQmlTypeModule();
- ~QQmlTypeModule();
QQmlTypeModulePrivate *d;
};
diff --git a/src/qml/qml/qqmltypemodule_p_p.h b/src/qml/qml/qqmltypemodule_p_p.h
index c045d3ed9b..b1dab1c4a0 100644
--- a/src/qml/qml/qqmltypemodule_p_p.h
+++ b/src/qml/qml/qqmltypemodule_p_p.h
@@ -55,27 +55,33 @@
#include <private/qstringhash_p.h>
#include <private/qqmlmetatypedata_p.h>
+#include <QtCore/qmutex.h>
+
QT_BEGIN_NAMESPACE
class QQmlTypeModulePrivate
{
public:
- QQmlTypeModulePrivate()
- : minMinorVersion(INT_MAX), maxMinorVersion(0), locked(false) {}
+ QQmlTypeModulePrivate(QString module, int majorVersion) :
+ module(std::move(module)), majorVersion(majorVersion)
+ {}
- static QQmlTypeModulePrivate* get(QQmlTypeModule* q) { return q->d; }
+ const QString module;
+ const int majorVersion = 0;
- QQmlMetaTypeData::VersionedUri uri;
+ // Can only ever decrease
+ QAtomicInt minMinorVersion = std::numeric_limits<int>::max();
- int minMinorVersion;
- int maxMinorVersion;
- bool locked;
+ // Can only ever increase
+ QAtomicInt maxMinorVersion = 0;
- void add(QQmlTypePrivate *);
- void remove(const QQmlTypePrivate *type);
+ // Bool. Can only be set to 1 once.
+ QAtomicInt locked = 0;
typedef QStringHash<QList<QQmlTypePrivate *> > TypeHash;
TypeHash typeHash;
+
+ QMutex mutex;
};
QT_END_NAMESPACE