diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -61,21 +61,35 @@ struct UpdateIndexCallbacks : public ParsingCallbacks { UpdateIndexCallbacks(FileIndex *FIndex, ClangdServer::Callbacks *ServerCallbacks, - const ThreadsafeFS &TFS, AsyncTaskRunner *Tasks) + const ThreadsafeFS &TFS, AsyncTaskRunner *Tasks, + AsyncTaskRunner* PreambleIndexTask) : FIndex(FIndex), ServerCallbacks(ServerCallbacks), TFS(TFS), - Stdlib{std::make_shared()}, Tasks(Tasks) {} + Stdlib{std::make_shared()}, Tasks(Tasks), + PreambleIndexTask(PreambleIndexTask) {} void onPreambleAST(PathRef Path, llvm::StringRef Version, const CompilerInvocation &CI, ASTContext &Ctx, Preprocessor &PP, const CanonicalIncludes &CanonIncludes) override { + if (!FIndex) + return; + // If this preamble uses a standard library we haven't seen yet, index it. - if (FIndex) - if (auto Loc = Stdlib->add(*CI.getLangOpts(), PP.getHeaderSearchInfo())) - indexStdlib(CI, std::move(*Loc)); + if (auto Loc = Stdlib->add(*CI.getLangOpts(), PP.getHeaderSearchInfo())) + indexStdlib(CI, std::move(*Loc)); - if (FIndex) - FIndex->updatePreamble(Path, Version, Ctx, PP, CanonIncludes); + auto Task = [FIndex(FIndex), Path(Path), + Version(Version), Ctx(&Ctx), PP(&PP), + CanonIncludes(CanonIncludes)] { + FIndex->updatePreamble(Path, Version, *Ctx, *PP, CanonIncludes); + }; + + assert(PreambleIndexTask); + if (PreambleIndexTask) + PreambleIndexTask->runAsync("task:" + Path + Version, + std::move(Task)); + else + Task(); } void indexStdlib(const CompilerInvocation &CI, StdLibLocation Loc) { @@ -139,6 +153,7 @@ const ThreadsafeFS &TFS; std::shared_ptr Stdlib; AsyncTaskRunner *Tasks; + AsyncTaskRunner *PreambleIndexTask; }; class DraftStoreFS : public ThreadsafeFS { @@ -201,7 +216,8 @@ WorkScheduler.emplace(CDB, TUScheduler::Options(Opts), std::make_unique( DynamicIdx.get(), Callbacks, TFS, - IndexTasks ? &*IndexTasks : nullptr)); + IndexTasks ? &*IndexTasks : nullptr, + WorkScheduler->getPreambleIndexTasks())); // Adds an index to the stack, at higher priority than existing indexes. auto AddIndex = [&](SymbolIndex *Idx) { if (this->Index != nullptr) { diff --git a/clang-tools-extra/clangd/TUScheduler.h b/clang-tools-extra/clangd/TUScheduler.h --- a/clang-tools-extra/clangd/TUScheduler.h +++ b/clang-tools-extra/clangd/TUScheduler.h @@ -335,6 +335,10 @@ /// Mostly useful for synchronizing tests. bool blockUntilIdle(Deadline D) const; + AsyncTaskRunner* getPreambleIndexTasks() { + return PreambleIndexTasks ? &PreambleIndexTasks.value() : nullptr; + } + private: /// This class stores per-file data in the Files map. struct FileData; @@ -371,6 +375,7 @@ // None when running tasks synchronously and non-None when running tasks // asynchronously. std::optional PreambleTasks; + std::optional PreambleIndexTasks; std::optional WorkerThreads; // Used to create contexts for operations that are not bound to a particular // file (e.g. index queries). diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp --- a/clang-tools-extra/clangd/TUScheduler.cpp +++ b/clang-tools-extra/clangd/TUScheduler.cpp @@ -1646,6 +1646,7 @@ } if (0 < Opts.AsyncThreadsCount) { PreambleTasks.emplace(); + PreambleIndexTasks.emplace(); WorkerThreads.emplace(); } } @@ -1657,6 +1658,8 @@ // Wait for all in-flight tasks to finish. if (PreambleTasks) PreambleTasks->wait(); + if (PreambleIndexTasks) + PreambleIndexTasks->wait(); if (WorkerThreads) WorkerThreads->wait(); } @@ -1668,6 +1671,9 @@ if (PreambleTasks) if (!PreambleTasks->wait(D)) return false; + if (PreambleIndexTasks) + if (!PreambleIndexTasks->wait(D)) + return false; return true; }