summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJarek Kobus <jaroslaw.kobus@qt.io>2021-06-21 13:51:55 +0200
committerJarek Kobus <jaroslaw.kobus@qt.io>2021-06-21 12:22:08 +0000
commitca09774181af618f440bffe059166a9f7cadb50f (patch)
tree03737c4a51bd5530e4472e7193f6ac323d2eb557 /src
parent54f3232f63d835ef0c17aa195a64c0b248afc759 (diff)
downloadqt-creator-ca09774181af618f440bffe059166a9f7cadb50f.tar.gz
Add more thread safety to ModelManagerInterface
Add ModelManagerInterface *ModelManagerInterface::instanceForFuture() method. If the returned instance is not null, it's guaranteed that it will be valid at least as long as the passed QFuture object isn't finished. Use instanceForFuture() in Link c'tor, as it's called from non-gui thread. Change-Id: I7e5ee6ad27e8f71cc0cef7fd9a91b710e2f8f662 Reviewed-by: Fawzi Mohamed <fawzi.mohamed@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/libs/qmljs/qmljslink.cpp5
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.cpp18
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.h1
3 files changed, 21 insertions, 3 deletions
diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp
index 121fee3301..4fcdb0a748 100644
--- a/src/libs/qmljs/qmljslink.cpp
+++ b/src/libs/qmljs/qmljslink.cpp
@@ -150,7 +150,9 @@ Link::Link(const Snapshot &snapshot, const ViewerContext &vContext, const Librar
d->diagnosticMessages = nullptr;
d->allDiagnosticMessages = nullptr;
- ModelManagerInterface *modelManager = ModelManagerInterface::instance();
+ QFutureInterface<void> fi;
+ fi.reportStarted();
+ ModelManagerInterface *modelManager = ModelManagerInterface::instanceForFuture(fi.future());
if (modelManager) {
const ModelManagerInterface::CppDataHash cppDataHash = modelManager->cppData();
{
@@ -176,6 +178,7 @@ Link::Link(const Snapshot &snapshot, const ViewerContext &vContext, const Librar
}
d->m_valueOwner->cppQmlTypes().setCppContextProperties(cppContextProperties);
}
+ fi.reportFinished();
}
ContextPtr Link::operator()(QHash<QString, QList<DiagnosticMessage> > *messages)
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
index dc9435787f..8eae3c3625 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp
@@ -77,6 +77,7 @@ QMLJS_EXPORT Q_LOGGING_CATEGORY(qmljsLog, "qtc.qmljs.common", QtWarningMsg)
*/
static ModelManagerInterface *g_instance = nullptr;
+static QMutex g_instanceMutex;
static const char *qtQuickUISuffix = "ui.qml";
static void maybeAddPath(ViewerContext &context, const QString &path)
@@ -134,6 +135,7 @@ ModelManagerInterface::ModelManagerInterface(QObject *parent)
updateImportPaths();
+ QMutexLocker locker(&g_instanceMutex);
Q_ASSERT(! g_instance);
g_instance = this;
}
@@ -143,6 +145,8 @@ ModelManagerInterface::~ModelManagerInterface()
joinAllThreads(true);
m_cppQmlTypesUpdater.cancel();
m_cppQmlTypesUpdater.waitForFinished();
+
+ QMutexLocker locker(&g_instanceMutex);
Q_ASSERT(g_instance == this);
g_instance = nullptr;
}
@@ -199,6 +203,15 @@ ModelManagerInterface *ModelManagerInterface::instance()
return g_instance;
}
+// If the returned instance is not null, it's guaranteed that it will be valid at least as long
+// as the passed QFuture object isn't finished.
+ModelManagerInterface *ModelManagerInterface::instanceForFuture(const QFuture<void> &future)
+{
+ QMutexLocker locker(&g_instanceMutex);
+ if (g_instance)
+ g_instance->addFuture(future);
+ return g_instance;
+}
void ModelManagerInterface::writeWarning(const QString &msg)
{
if (ModelManagerInterface *i = instance())
@@ -1250,8 +1263,9 @@ void ModelManagerInterface::maybeQueueCppQmlTypeUpdate(const CPlusPlus::Document
if (!scan)
doc->releaseSourceAndAST();
- // delegate actual queuing to the gui thread
- QMetaObject::invokeMethod(this, [=] { queueCppQmlTypeUpdate(doc, scan); });
+ QMutexLocker locker(&g_instanceMutex);
+ if (g_instance) // delegate actual queuing to the gui thread
+ QMetaObject::invokeMethod(g_instance, [=] { queueCppQmlTypeUpdate(doc, scan); });
}
void ModelManagerInterface::queueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc, bool scan)
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h
index d4eb84e958..a4b6be96c1 100644
--- a/src/libs/qmljs/qmljsmodelmanagerinterface.h
+++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h
@@ -126,6 +126,7 @@ public:
static Dialect guessLanguageOfFile(const QString &fileName);
static QStringList globPatternsForLanguages(const QList<Dialect> &languages);
static ModelManagerInterface *instance();
+ static ModelManagerInterface *instanceForFuture(const QFuture<void> &future);
static void writeWarning(const QString &msg);
static WorkingCopy workingCopy();