From d74ddb76b6229746f8c4538b3a35c760d51d2fd3 Mon Sep 17 00:00:00 2001
From: Roberto Raggi <qtc-committer@nokia.com>
Date: Mon, 8 Dec 2008 10:44:56 +0100
Subject: [PATCH] Protected m_dirty and m_projects with a mutex.

---
 .../cmakeprojectmanager/cmakeproject.cpp      |  7 ++-
 src/plugins/cpptools/cppmodelmanager.cpp      | 61 ++++++++++++++++---
 src/plugins/cpptools/cppmodelmanager.h        | 25 ++++----
 .../cpptools/cppmodelmanagerinterface.h       | 32 ++++++++--
 src/plugins/qt4projectmanager/qt4project.cpp  | 26 ++++----
 5 files changed, 111 insertions(+), 40 deletions(-)

diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
index 1268c57b967..9c6c3947fa3 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
@@ -62,11 +62,12 @@ CMakeProject::CMakeProject(CMakeManager *manager, const QString &fileName)
 
         CppTools::CppModelManagerInterface *modelmanager = ExtensionSystem::PluginManager::instance()->getObject<CppTools::CppModelManagerInterface>();
         if (modelmanager) {
-            CppTools::CppModelManagerInterface::ProjectInfo *pinfo = modelmanager->projectInfo(this);
-            pinfo->includePaths = cbpparser.includeFiles();
+            CppTools::CppModelManagerInterface::ProjectInfo pinfo = modelmanager->projectInfo(this);
+            pinfo.includePaths = cbpparser.includeFiles();
             // TODO we only want C++ files, not all other stuff that might be in the project
-            pinfo->sourceFiles = m_files;
+            pinfo.sourceFiles = m_files;
             // TODO defines
+            modelmanager->updateProjectInfo(pinfo);
         }
     } else {
         // TODO report error
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index 042b93cc74d..dbc324013c6 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -66,6 +66,7 @@
 #include <Token.h>
 
 #include <QPlainTextEdit>
+#include <QMutexLocker>
 #include <QTime>
 #include <QDebug>
 
@@ -450,12 +451,25 @@ CppModelManager::CppModelManager(QObject *parent) :
 CppModelManager::~CppModelManager()
 { }
 
-Document::Ptr CppModelManager::document(const QString &fileName)
+Document::Ptr CppModelManager::document(const QString &fileName) const
 { return m_documents.value(fileName); }
 
-CppModelManager::DocumentTable CppModelManager::documents()
+CppModelManager::DocumentTable CppModelManager::documents() const
 { return m_documents; }
 
+void CppModelManager::ensureUpdated()
+{
+    QMutexLocker locker(&mutex);
+    if (! m_dirty)
+        return;
+
+    m_projectFiles = updateProjectFiles();
+    m_includePaths = updateIncludePaths();
+    m_frameworkPaths = updateFrameworkPaths();
+    m_definedMacros = updateDefinedMacros();
+    m_dirty = false;
+}
+
 QStringList CppModelManager::updateProjectFiles() const
 {
     QStringList files;
@@ -527,8 +541,29 @@ QMap<QString, QByteArray> CppModelManager::buildWorkingCopyList()
 void CppModelManager::updateSourceFiles(const QStringList &sourceFiles)
 { (void) refreshSourceFiles(sourceFiles); }
 
-CppModelManager::ProjectInfo *CppModelManager::projectInfo(ProjectExplorer::Project *project)
-{ return &m_projects[project]; }
+QList<CppModelManager::ProjectInfo> CppModelManager::projectInfos() const
+{
+    QMutexLocker locker(&mutex);
+
+    return m_projects.values();
+}
+
+CppModelManager::ProjectInfo CppModelManager::projectInfo(ProjectExplorer::Project *project) const
+{
+    QMutexLocker locker(&mutex);
+
+    return m_projects.value(project, ProjectInfo(project));
+}
+
+void CppModelManager::updateProjectInfo(const ProjectInfo &pinfo)
+{
+    QMutexLocker locker(&mutex);
+
+    if (! pinfo.isValid())
+        return;
+
+    m_projects.insert(pinfo.project, pinfo);
+}
 
 QFuture<void> CppModelManager::refreshSourceFiles(const QStringList &sourceFiles)
 {
@@ -691,13 +726,18 @@ void CppModelManager::onDocumentUpdated(Document::Ptr doc)
 
 void CppModelManager::onProjectAdded(ProjectExplorer::Project *)
 {
+    QMutexLocker locker(&mutex);
     m_dirty = true;
 }
 
 void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project)
 {
-    m_dirty = true;
-    m_projects.remove(project);
+    do {
+        QMutexLocker locker(&mutex);
+        m_dirty = true;
+        m_projects.remove(project);
+    } while (0);
+
     GC();
 }
 
@@ -705,8 +745,15 @@ void CppModelManager::onSessionUnloaded()
 {
     if (m_core->progressManager()) {
         m_core->progressManager()->cancelTasks(CppTools::Constants::TASK_INDEX);
-        m_dirty = true;
     }
+
+    do {
+        QMutexLocker locker(&mutex);
+        m_projects.clear();
+        m_dirty = true;
+    } while (0);
+
+    GC();
 }
 
 void CppModelManager::parse(QFutureInterface<void> &future,
diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h
index a91a414e480..6bc7d0c1c55 100644
--- a/src/plugins/cpptools/cppmodelmanager.h
+++ b/src/plugins/cpptools/cppmodelmanager.h
@@ -40,6 +40,7 @@
 
 #include <QMap>
 #include <QFutureInterface>
+#include <QMutex>
 
 namespace Core {
 class ICore;
@@ -70,9 +71,13 @@ public:
     virtual ~CppModelManager();
 
     virtual void updateSourceFiles(const QStringList &sourceFiles);
-    virtual ProjectInfo *projectInfo(ProjectExplorer::Project *project);
-    virtual CPlusPlus::Document::Ptr document(const QString &fileName);
-    virtual DocumentTable documents();
+
+    virtual QList<ProjectInfo> projectInfos() const;
+    virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const;
+    virtual void updateProjectInfo(const ProjectInfo &pinfo);
+
+    virtual CPlusPlus::Document::Ptr document(const QString &fileName) const;
+    virtual DocumentTable documents() const;
     virtual void GC();
 
     QFuture<void> refreshSourceFiles(const QStringList &sourceFiles);
@@ -127,22 +132,12 @@ private:
         return m_definedMacros;
     }
 
+    void ensureUpdated();
     QStringList updateProjectFiles() const;
     QStringList updateIncludePaths() const;
     QStringList updateFrameworkPaths() const;
     QByteArray updateDefinedMacros() const;
 
-    void ensureUpdated() {
-        if (! m_dirty)
-            return;
-
-        m_projectFiles = updateProjectFiles();
-        m_includePaths = updateIncludePaths();
-        m_frameworkPaths = updateFrameworkPaths();
-        m_definedMacros = updateDefinedMacros();
-        m_dirty = false;
-    }
-
     static void parse(QFutureInterface<void> &future,
                       CppPreprocessor *preproc,
                       QStringList files);
@@ -166,6 +161,8 @@ private:
     // project integration
     QMap<ProjectExplorer::Project *, ProjectInfo> m_projects;
 
+    mutable QMutex mutex;
+
     enum {
         MAX_SELECTION_COUNT = 5
     };
diff --git a/src/plugins/cpptools/cppmodelmanagerinterface.h b/src/plugins/cpptools/cppmodelmanagerinterface.h
index 11be08a4b0e..e3ad4fe961b 100644
--- a/src/plugins/cpptools/cppmodelmanagerinterface.h
+++ b/src/plugins/cpptools/cppmodelmanagerinterface.h
@@ -38,6 +38,7 @@
 #include <cplusplus/CppDocument.h>
 #include <QtCore/QObject>
 #include <QtCore/QMap>
+#include <QtCore/QPointer>
 
 namespace ProjectExplorer {
     class Project;
@@ -51,10 +52,29 @@ class CPPTOOLS_EXPORT CppModelManagerInterface
     Q_OBJECT
 
 public:
-    typedef QMap<QString, CPlusPlus::Document::Ptr> DocumentTable;
+    typedef QMap<QString, CPlusPlus::Document::Ptr> DocumentTable; // ### remove me
 
-    struct ProjectInfo
+    class ProjectInfo
     {
+    public:
+        ProjectInfo()
+        { }
+
+        ProjectInfo(QPointer<ProjectExplorer::Project> project)
+            : project(project)
+        { }
+
+        operator bool() const
+        { return ! project.isNull(); }
+
+        bool isValid() const
+        { return ! project.isNull(); }
+
+        bool isNull() const
+        { return project.isNull(); }
+
+    public: // attributes
+        QPointer<ProjectExplorer::Project> project;
         QString projectPath;
         QByteArray defines;
         QStringList sourceFiles;
@@ -69,10 +89,12 @@ public:
     virtual void GC() = 0;
     virtual void updateSourceFiles(const QStringList &sourceFiles) = 0;
 
-    virtual CPlusPlus::Document::Ptr document(const QString &fileName) = 0;
-    virtual DocumentTable documents() = 0;
+    virtual CPlusPlus::Document::Ptr document(const QString &fileName) const = 0;
+    virtual DocumentTable documents() const = 0;
 
-    virtual ProjectInfo *projectInfo(ProjectExplorer::Project *project) = 0;
+    virtual QList<ProjectInfo> projectInfos() const = 0;
+    virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const = 0;
+    virtual void updateProjectInfo(const ProjectInfo &pinfo) = 0;
 };
 
 } // namespace CppTools
diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp
index 501068af004..b67535212e7 100644
--- a/src/plugins/qt4projectmanager/qt4project.cpp
+++ b/src/plugins/qt4projectmanager/qt4project.cpp
@@ -480,23 +480,27 @@ void Qt4Project::updateCodeModel()
     files += m_projectFiles->files[SourceType];
     files += m_projectFiles->generatedFiles[SourceType];
 
-    CppTools::CppModelManagerInterface::ProjectInfo *pinfo = modelmanager->projectInfo(this);
+    CppTools::CppModelManagerInterface::ProjectInfo pinfo = modelmanager->projectInfo(this);
 
-    if (pinfo->defines == predefinedMacros         &&
-        pinfo->includePaths == allIncludePaths     &&
-        pinfo->frameworkPaths == allFrameworkPaths &&
-        pinfo->sourceFiles == files) {
-        // Nothing to update...
+    if (pinfo.defines == predefinedMacros             &&
+            pinfo.includePaths == allIncludePaths     &&
+            pinfo.frameworkPaths == allFrameworkPaths &&
+            pinfo.sourceFiles == files) {
+        modelmanager->updateProjectInfo(pinfo);
     } else {
-        pinfo->defines = predefinedMacros;
+        pinfo.defines = predefinedMacros;
         // pinfo->defines += definedMacros;   // ### FIXME: me
-        pinfo->includePaths = allIncludePaths;
-        pinfo->frameworkPaths = allFrameworkPaths;
-        pinfo->sourceFiles = files;
+        pinfo.includePaths = allIncludePaths;
+        pinfo.frameworkPaths = allFrameworkPaths;
+        pinfo.sourceFiles = files;
+
+        modelmanager->updateProjectInfo(pinfo);
 
         modelmanager->GC();
-        modelmanager->updateSourceFiles(pinfo->sourceFiles);
+        modelmanager->updateSourceFiles(pinfo.sourceFiles);
     }
+
+    // update info
 }
 
 
-- 
GitLab