From bfe36575b74ce96dba1b4802a97be7c9a37232f3 Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Tue, 24 Feb 2009 11:04:52 +0100
Subject: [PATCH] Introduced a parallel indexer. It is ifdef-out atm.

---
 src/libs/cplusplus/CppDocument.cpp       | 23 +++++-
 src/libs/cplusplus/CppDocument.h         |  8 ++
 src/plugins/cpptools/cppmodelmanager.cpp | 94 ++++++++++++++++++------
 3 files changed, 102 insertions(+), 23 deletions(-)

diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp
index 8c2d6265909..a0ae6760d61 100644
--- a/src/libs/cplusplus/CppDocument.cpp
+++ b/src/libs/cplusplus/CppDocument.cpp
@@ -230,7 +230,8 @@ Document::Ptr Document::create(const QString &fileName)
 
 void Document::setSource(const QByteArray &source)
 {
-    _translationUnit->setSource(source.constBegin(), source.size());
+    _source = source;
+    _translationUnit->setSource(_source.constBegin(), _source.size());
 }
 
 void Document::startSkippingBlocks(unsigned start)
@@ -250,6 +251,21 @@ void Document::stopSkippingBlocks(unsigned stop)
         _skippedBlocks.back() = Block(start, stop);
 }
 
+bool Document::isTokenized() const
+{
+    return _translationUnit->isTokenized();
+}
+
+void Document::tokenize()
+{
+    _translationUnit->tokenize();
+}
+
+bool Document::isParsed() const
+{
+    return _translationUnit->isParsed();
+}
+
 bool Document::parse(ParseMode mode)
 {
     TranslationUnit::ParseMode m = TranslationUnit::ParseTranlationUnit;
@@ -295,6 +311,11 @@ void Document::check()
     }
 }
 
+void Document::releaseSource()
+{
+    _source.clear();
+}
+
 void Document::releaseTranslationUnit()
 {
     _translationUnit->release();
diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h
index 73bae23679c..90946a5295d 100644
--- a/src/libs/cplusplus/CppDocument.h
+++ b/src/libs/cplusplus/CppDocument.h
@@ -96,8 +96,15 @@ public:
         ParseStatement
     };
 
+    bool isTokenized() const;
+    void tokenize();
+
+    bool isParsed() const;
     bool parse(ParseMode mode = ParseTranlationUnit);
+
     void check();
+
+    void releaseSource();
     void releaseTranslationUnit();
 
     static Ptr create(const QString &fileName);
@@ -233,6 +240,7 @@ private:
     QList<Macro> _definedMacros;
     QList<Block> _skippedBlocks;
     QList<MacroUse> _macroUses;
+    QByteArray _source;
 };
 
 class CPLUSPLUS_EXPORT Snapshot: public QMap<QString, Document::Ptr>
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index c7cda11081e..586ea67c0e2 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -73,6 +73,7 @@
 #include <QtCore/QMutexLocker>
 #include <QtCore/QTime>
 #include <QtCore/QTimer>
+#include <QtConcurrentMap>
 #include <iostream>
 #include <sstream>
 
@@ -171,8 +172,8 @@ public:
     void setProjectFiles(const QStringList &files);
     void setTodo(const QStringList &files);
 
-    void run(QString &fileName);
-    void operator()(QString &fileName);
+    void run(const QString &fileName);
+    void run_helper(const QString &fileName, QList<Document::Ptr> *documents);
 
     void resetEnvironment();
 
@@ -211,8 +212,9 @@ private:
     QStringList m_projectFiles;
     QStringList m_frameworkPaths;
     QSet<QString> m_included;
-    CPlusPlus::Document::Ptr m_currentDoc;
+    Document::Ptr m_currentDoc;
     QSet<QString> m_todo;
+    QList<Document::Ptr> *m_documents;
 };
 
 } // namespace Internal
@@ -221,7 +223,8 @@ private:
 CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager)
     : snapshot(modelManager->snapshot()),
       m_modelManager(modelManager),
-      m_proc(this, env)
+      m_proc(this, env),
+      m_documents(0)
 { }
 
 void CppPreprocessor::setWorkingCopy(const QMap<QString, QByteArray> &workingCopy)
@@ -239,15 +242,70 @@ void CppPreprocessor::setProjectFiles(const QStringList &files)
 void CppPreprocessor::setTodo(const QStringList &files)
 { m_todo = QSet<QString>::fromList(files); }
 
-void CppPreprocessor::run(QString &fileName)
-{ sourceNeeded(fileName, IncludeGlobal, /*line = */ 0); }
+
+namespace {
+
+class Process
+{
+    QPointer<CppModelManager> _modelManager;
+
+public:
+    Process(QPointer<CppModelManager> modelManager)
+        : _modelManager(modelManager)
+    { }
+
+    void operator()(Document::Ptr doc)
+    {
+        doc->parse();
+        doc->check();
+        doc->releaseTranslationUnit();
+
+        if (_modelManager)
+            _modelManager->emitDocumentUpdated(doc); // ### TODO: compress
+    }
+};
+
+} // end of anonymous namespace
+
+// #define QTCREATOR_WITH_PARALLEL_INDEXER
+
+void CppPreprocessor::run(const QString &fileName)
+{
+    QList<Document::Ptr> documents;
+    run_helper(fileName, &documents);
+
+#ifdef QTCREATOR_WITH_PARALLEL_INDEXER
+    QFuture<void> future = QtConcurrent::map(documents, Process(m_modelManager));
+    future.waitForFinished();
+
+#else
+    foreach (Document::Ptr doc, documents) {
+        doc->parse();
+        doc->check();
+
+        doc->releaseTranslationUnit();
+
+        if (m_modelManager)
+            m_modelManager->emitDocumentUpdated(doc); // ### TODO: compress
+    }
+#endif
+}
+
+void CppPreprocessor::run_helper(const QString &fileName,
+                                 QList<Document::Ptr> *documents)
+{
+    QList<Document::Ptr> *previousDocuments = m_documents;
+    m_documents = documents;
+
+    QString absoluteFilePath = fileName;
+    sourceNeeded(absoluteFilePath, IncludeGlobal, /*line = */ 0);
+
+    m_documents = previousDocuments;
+}
 
 void CppPreprocessor::resetEnvironment()
 { env.reset(); }
 
-void CppPreprocessor::operator()(QString &fileName)
-{ run(fileName); }
-
 bool CppPreprocessor::includeFile(const QString &absoluteFilePath, QByteArray *result)
 {
     if (absoluteFilePath.isEmpty() || m_included.contains(absoluteFilePath)) {
@@ -475,23 +533,15 @@ void CppPreprocessor::sourceNeeded(QString &fileName, IncludeType type,
     m_proc(fileName.toUtf8(), contents, &preprocessedCode);
 
     doc->setSource(preprocessedCode);
+    doc->tokenize();
+    doc->releaseSource();
 
-    doc->parse();
-    doc->check();
-
-#if defined(QTCREATOR_WITH_DUMP_AST) && defined(Q_CC_GNU)
-            DumpAST dump(m_currentDoc->control());
-            dump(m_currentDoc->translationUnit()->ast());
-#endif
-
-    doc->releaseTranslationUnit();
+    snapshot.insert(doc->fileName(), doc);
 
-    snapshot[fileName] = doc;
-
-    if (m_modelManager)
-        m_modelManager->emitDocumentUpdated(m_currentDoc); // ### TODO: compress
+    m_documents->append(doc);
 
     (void) switchDocument(previousDoc);
+
     m_todo.remove(fileName);
 }
 
-- 
GitLab