sammccall created this revision.
sammccall added a reviewer: kadircet.
Herald added subscribers: usaxena95, arphaman.
sammccall requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang.

This allows modules to do work on non-TUScheduler background threads.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D96755

Files:
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Module.h
  clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp

Index: clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp
+++ clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp
@@ -16,6 +16,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/JSON.h"
+#include "llvm/Testing/Support/Error.h"
 #include "llvm/Testing/Support/SupportHelpers.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
@@ -23,6 +24,8 @@
 namespace clang {
 namespace clangd {
 namespace {
+using llvm::HasValue;
+using llvm::Succeeded;
 
 MATCHER_P(DiagMessage, M, "") {
   if (const auto *O = arg.getAsObject()) {
@@ -39,6 +42,7 @@
     Base = ClangdServer::optsForTest();
     // This is needed to we can test index-based operations like call hierarchy.
     Base.BuildDynamicSymbolIndex = true;
+    Base.Modules = &Modules;
   }
 
   LSPClient &start() {
@@ -66,6 +70,7 @@
 
   MockFS FS;
   ClangdLSPServer::Options Opts;
+  ModuleSet Modules;
 
 private:
   // Color logs so we can distinguish them from test output.
@@ -233,10 +238,7 @@
     void get(const std::nullptr_t &, Callback<int> Reply) { Reply(Value); }
     int Value = 0;
   };
-  std::vector<std::unique_ptr<Module>> Mods;
-  Mods.push_back(std::make_unique<MathModule>());
-  ModuleSet ModSet(std::move(Mods));
-  Opts.Modules = &ModSet;
+  Modules.add(std::make_unique<MathModule>());
 
   auto &Client = start();
   Client.notify("add", 2);
@@ -244,6 +246,118 @@
   EXPECT_EQ(10, Client.call("get", nullptr).takeValue());
 }
 
+// Creates a Callback that writes its received value into an Optional<Expected>.
+template <typename T>
+llvm::unique_function<void(llvm::Expected<T>)>
+capture(llvm::Optional<llvm::Expected<T>> &Out) {
+  Out.reset();
+  return [&Out](llvm::Expected<T> V) { Out.emplace(std::move(V)); };
+}
+
+TEST_F(LSPTest, ModulesThreadingTest) {
+  // A module that does its work on a background thread, and so exercises the
+  // block/shutdown protocol.
+  class AsyncCounter : public Module {
+    bool ShouldStop;
+    int State = 0;
+    std::deque<Callback<int>> Queue; // null = increment, non-null = read.
+    std::condition_variable CV;
+    std::mutex Mu;
+    std::thread Thread;
+
+    void run() {
+      std::unique_lock<std::mutex> Lock(Mu);
+      while (true) {
+        CV.wait(Lock, [&] { return ShouldStop || !Queue.empty(); });
+        if (ShouldStop) {
+          Queue.clear();
+          CV.notify_all();
+          return;
+        }
+        Callback<int> &Task = Queue.front();
+        if (Task)
+          Task(State);
+        else
+          ++State;
+        Queue.pop_front();
+        CV.notify_all();
+      }
+    }
+
+    bool blockUntilIdle(Deadline D) override {
+      std::unique_lock<std::mutex> Lock(Mu);
+      return clangd::wait(Lock, CV, D, [this] { return Queue.empty(); });
+    }
+
+    void stop() override {
+      {
+        std::lock_guard<std::mutex> Lock(Mu);
+        ShouldStop = true;
+      }
+      CV.notify_all();
+    }
+
+  public:
+    AsyncCounter() : Thread([this] { run(); }) {}
+    ~AsyncCounter() {
+      // Verify shutdown sequence was performed.
+      // Real modules would not do this, to be robust to no ClangdServer.
+      EXPECT_TRUE(ShouldStop) << "ClangdServer should request shutdown";
+      EXPECT_EQ(Queue.size(), 0u) << "ClangdServer should block until idle";
+      Thread.join();
+    }
+
+    // Get the current value, bypassing the queue.
+    // Used to verify that sync->blockUntilIdle avoids races in tests.
+    int getSync() {
+      std::lock_guard<std::mutex> Lock(Mu);
+      return State;
+    }
+
+    // Get the current value asynchronously.
+    void get(Callback<int> Reply) {
+      {
+        std::lock_guard<std::mutex> Lock(Mu);
+        Queue.push_back(std::move(Reply));
+      }
+      CV.notify_all();
+    }
+
+    // Increment the current value asynchronously.
+    void increment() {
+      {
+        std::lock_guard<std::mutex> Lock(Mu);
+        Queue.push_back(nullptr);
+      }
+      CV.notify_all();
+    }
+  };
+
+  auto *Counter = new AsyncCounter();
+  Modules.add(std::unique_ptr<AsyncCounter>(Counter));
+  auto &Client = start();
+
+  llvm::Optional<llvm::Expected<int>> One, Two, Three;
+  Counter->increment();
+  Counter->get(capture(One));
+  Counter->increment();
+  Counter->get(capture(Two));
+  Counter->increment();
+  Counter->get(capture(Three));
+  EXPECT_THAT_EXPECTED(Client.call("sync", nullptr).take(), Succeeded());
+  ASSERT_TRUE(One && Two && Three) << "sync should wait for pending requests";
+  EXPECT_EQ(3, Counter->getSync()) << "sync avoids flaky tests";
+  // Sanity check: reads and writes are sequenced on the worker thread.
+  EXPECT_THAT_EXPECTED(*One, HasValue(1));
+  EXPECT_THAT_EXPECTED(*Two, HasValue(2));
+  EXPECT_THAT_EXPECTED(*Three, HasValue(3));
+  // Throw some work on the queue to make sure shutdown blocks on it.
+  Counter->increment();
+  Counter->increment();
+  Counter->increment();
+  // And immediately shut down. Module destructor verifies that we blocked.
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/Module.h
===================================================================
--- clang-tools-extra/clangd/Module.h
+++ clang-tools-extra/clangd/Module.h
@@ -2,6 +2,7 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_MODULE_H
 
 #include "LSPBinder.h"
+#include "support/Threading.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/JSON.h"
 #include <memory>
@@ -9,6 +10,7 @@
 
 namespace clang {
 namespace clangd {
+class Deadline;
 
 /// A Module contributes a vertical feature to clangd.
 ///
@@ -17,18 +19,29 @@
 /// The lifetime of a module is roughly:
 ///  - modules are created before the LSP server, in ClangdMain.cpp
 ///  - these modules are then passed to ClangdLSPServer and ClangdServer
-///  - module hooks can be called at this point.
+///  - module entrypoints can be called at this point.
 ///    FIXME: We should make some server facilities like TUScheduler and index
 ///    available to those modules after ClangdServer is initalized.
-///  - ClangdServer will not be destroyed until all the requests are done.
-///    FIXME: Block server shutdown until all the modules are idle.
+///  - When shutting down, ClangdServer will wait for all requests to
+///    finish, call stop(), and then blockUntilIdle().
 ///  - modules will be destroyed after ClangdLSPServer is destroyed.
 ///
+/// Modules are not threadsafe in general. A module's entrypoints are:
+///   - method handlers registered in initializeLSP()
+///   - public methods called directly via ClangdServer.getModule<T>()->...
+///   - specific overridable "hook" methods inherited from Module
+/// Unless otherwise specified, these are only called on the main thread.
+///
 /// Conventionally, standard modules live in the `clangd` namespace, and other
 /// exposed details live in a sub-namespace.
 class Module {
 public:
-  virtual ~Module() = default;
+  virtual ~Module() {
+    /// Perform shutdown sequence on destruction in case the ClangdServer was
+    /// never initialized. Usually redundant, but shutdown is idempotent.
+    stop();
+    blockUntilIdle(Deadline::infinity());
+  }
 
   /// Called by the server to connect this module to LSP.
   /// The module should register the methods/notifications/commands it handles,
@@ -39,12 +52,27 @@
   virtual void initializeLSP(LSPBinder &Bind,
                              const llvm::json::Object &ClientCaps,
                              llvm::json::Object &ServerCaps) {}
+
+  /// Requests that the module cancel background work and go idle soon.
+  /// Does not block, the caller will call blockUntilIdle() instead.
+  /// After a module is stop()ed, it should not receive any more requests.
+  /// Called by the server when shutting down.
+  /// May be called multiple times, should be idempotent.
+  virtual void stop() {}
+
+  /// Waits until the module is idle (no background work) or a deadline expires.
+  /// In general all modules should eventually go idle, though it may take a
+  /// long time (e.g. background indexing).
+  /// Modules should go idle quickly if stop() has been called.
+  /// Called by the server when shutting down, and also by tests.
+  virtual bool blockUntilIdle(Deadline) { return true; }
 };
 
 class ModuleSet {
   std::vector<std::unique_ptr<Module>> Modules;
 
 public:
+  ModuleSet() = default;
   explicit ModuleSet(std::vector<std::unique_ptr<Module>> Modules)
       : Modules(std::move(Modules)) {}
 
@@ -55,6 +83,8 @@
   iterator end() { return iterator(Modules.end()); }
   const_iterator begin() const { return const_iterator(Modules.begin()); }
   const_iterator end() const { return const_iterator(Modules.end()); }
+
+  void add(std::unique_ptr<Module> M) { Modules.push_back(std::move(M)); }
 };
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/ClangdServer.h
===================================================================
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -160,6 +160,7 @@
   /// if compilation arguments changed on calls to forceReparse().
   ClangdServer(const GlobalCompilationDatabase &CDB, const ThreadsafeFS &TFS,
                const Options &Opts, Callbacks *Callbacks = nullptr);
+  ~ClangdServer();
 
   /// Add a \p File to the list of tracked C++ files or update the contents if
   /// \p File is already tracked. Also schedules parsing of the AST for it on a
@@ -337,6 +338,8 @@
                   ArrayRef<tooling::Range> Ranges,
                   Callback<tooling::Replacements> CB);
 
+  ModuleSet *Modules;
+
   const GlobalCompilationDatabase &CDB;
   const ThreadsafeFS &TFS;
 
@@ -363,10 +366,7 @@
   mutable std::mutex CachedCompletionFuzzyFindRequestMutex;
 
   llvm::Optional<std::string> WorkspaceRoot;
-  // WorkScheduler has to be the last member, because its destructor has to be
-  // called before all other members to stop the worker thread that references
-  // ClangdServer.
-  TUScheduler WorkScheduler;
+  llvm::Optional<TUScheduler> WorkScheduler;
 };
 
 } // namespace clangd
Index: clang-tools-extra/clangd/ClangdServer.cpp
===================================================================
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -127,18 +127,16 @@
 ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
                            const ThreadsafeFS &TFS, const Options &Opts,
                            Callbacks *Callbacks)
-    : CDB(CDB), TFS(TFS),
+    : Modules(Opts.Modules), CDB(CDB), TFS(TFS),
       DynamicIdx(Opts.BuildDynamicSymbolIndex ? new FileIndex() : nullptr),
       ClangTidyProvider(Opts.ClangTidyProvider),
-      WorkspaceRoot(Opts.WorkspaceRoot),
-      // Pass a callback into `WorkScheduler` to extract symbols from a newly
-      // parsed file and rebuild the file index synchronously each time an AST
-      // is parsed.
-      // FIXME(ioeric): this can be slow and we may be able to index on less
-      // critical paths.
-      WorkScheduler(
-          CDB, TUScheduler::Options(Opts),
-          std::make_unique<UpdateIndexCallbacks>(DynamicIdx.get(), Callbacks)) {
+      WorkspaceRoot(Opts.WorkspaceRoot) {
+  // Pass a callback into `WorkScheduler` to extract symbols from a newly
+  // parsed file and rebuild the file index synchronously each time an AST
+  // is parsed.
+  WorkScheduler.emplace(
+      CDB, TUScheduler::Options(Opts),
+      std::make_unique<UpdateIndexCallbacks>(DynamicIdx.get(), Callbacks));
   // Adds an index to the stack, at higher priority than existing indexes.
   auto AddIndex = [&](SymbolIndex *Idx) {
     if (this->Index != nullptr) {
@@ -169,6 +167,20 @@
     AddIndex(DynamicIdx.get());
 }
 
+ClangdServer::~ClangdServer() {
+  // Destroying TUScheduler first shuts down request threads that might
+  // otherwise access members concurrently.
+  // (Nobody can be using TUScheduler because we're on the main thread).
+  WorkScheduler.reset();
+  // Now requests have stopped, we can shut down modules.
+  if (Modules) {
+    for (auto &Mod : *Modules)
+      Mod.stop();
+    for (auto &Mod : *Modules)
+      Mod.blockUntilIdle(Deadline::infinity());
+  }
+}
+
 void ClangdServer::addDocument(PathRef File, llvm::StringRef Contents,
                                llvm::StringRef Version,
                                WantDiagnostics WantDiags, bool ForceRebuild) {
@@ -183,7 +195,7 @@
   Inputs.Opts = std::move(Opts);
   Inputs.Index = Index;
   Inputs.ClangTidyProvider = ClangTidyProvider;
-  bool NewFile = WorkScheduler.update(File, Inputs, WantDiags);
+  bool NewFile = WorkScheduler->update(File, Inputs, WantDiags);
   // If we loaded Foo.h, we want to make sure Foo.cpp is indexed.
   if (NewFile && BackgroundIdx)
     BackgroundIdx->boostRelated(File);
@@ -266,7 +278,7 @@
   };
 }
 
-void ClangdServer::removeDocument(PathRef File) { WorkScheduler.remove(File); }
+void ClangdServer::removeDocument(PathRef File) { WorkScheduler->remove(File); }
 
 void ClangdServer::codeComplete(PathRef File, Position Pos,
                                 const clangd::CodeCompleteOptions &Opts,
@@ -320,7 +332,7 @@
   };
 
   // We use a potentially-stale preamble because latency is critical here.
-  WorkScheduler.runWithPreamble(
+  WorkScheduler->runWithPreamble(
       "CodeComplete", File,
       (Opts.RunParser == CodeCompleteOptions::AlwaysParse)
           ? TUScheduler::Stale
@@ -346,8 +358,8 @@
   };
 
   // Unlike code completion, we wait for a preamble here.
-  WorkScheduler.runWithPreamble("SignatureHelp", File, TUScheduler::Stale,
-                                std::move(Action));
+  WorkScheduler->runWithPreamble("SignatureHelp", File, TUScheduler::Stale,
+                                 std::move(Action));
 }
 
 void ClangdServer::formatRange(PathRef File, llvm::StringRef Code, Range Rng,
@@ -389,7 +401,7 @@
       Result.push_back(replacementToEdit(Code, R));
     return CB(Result);
   };
-  WorkScheduler.runQuick("FormatOnType", File, std::move(Action));
+  WorkScheduler->runQuick("FormatOnType", File, std::move(Action));
 }
 
 void ClangdServer::prepareRename(PathRef File, Position Pos,
@@ -414,14 +426,14 @@
     }
     return CB(*Results);
   };
-  WorkScheduler.runWithAST("PrepareRename", File, std::move(Action));
+  WorkScheduler->runWithAST("PrepareRename", File, std::move(Action));
 }
 
 void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
                           const RenameOptions &Opts,
                           Callback<RenameResult> CB) {
   // A snapshot of all file dirty buffers.
-  llvm::StringMap<std::string> Snapshot = WorkScheduler.getAllFileContents();
+  llvm::StringMap<std::string> Snapshot = WorkScheduler->getAllFileContents();
   auto Action = [File = File.str(), NewName = NewName.str(), Pos, Opts,
                  CB = std::move(CB), Snapshot = std::move(Snapshot),
                  this](llvm::Expected<InputsAndAST> InpAST) mutable {
@@ -456,7 +468,7 @@
     RenameFiles.record(R->GlobalChanges.size());
     return CB(*R);
   };
-  WorkScheduler.runWithAST("Rename", File, std::move(Action));
+  WorkScheduler->runWithAST("Rename", File, std::move(Action));
 }
 
 // May generate several candidate selections, due to SelectionTree ambiguity.
@@ -512,8 +524,8 @@
     CB(std::move(Res));
   };
 
-  WorkScheduler.runWithAST("EnumerateTweaks", File, std::move(Action),
-                           TUScheduler::InvalidateOnUpdate);
+  WorkScheduler->runWithAST("EnumerateTweaks", File, std::move(Action),
+                            TUScheduler::InvalidateOnUpdate);
 }
 
 void ClangdServer::applyTweak(PathRef File, Range Sel, StringRef TweakID,
@@ -559,7 +571,7 @@
     }
     return CB(std::move(*Effect));
   };
-  WorkScheduler.runWithAST("ApplyTweak", File, std::move(Action));
+  WorkScheduler->runWithAST("ApplyTweak", File, std::move(Action));
 }
 
 void ClangdServer::locateSymbolAt(PathRef File, Position Pos,
@@ -571,7 +583,7 @@
     CB(clangd::locateSymbolAt(InpAST->AST, Pos, Index));
   };
 
-  WorkScheduler.runWithAST("Definitions", File, std::move(Action));
+  WorkScheduler->runWithAST("Definitions", File, std::move(Action));
 }
 
 void ClangdServer::switchSourceHeader(
@@ -591,7 +603,7 @@
       return CB(InpAST.takeError());
     CB(getCorrespondingHeaderOrSource(Path, InpAST->AST, Index));
   };
-  WorkScheduler.runWithAST("SwitchHeaderSource", Path, std::move(Action));
+  WorkScheduler->runWithAST("SwitchHeaderSource", Path, std::move(Action));
 }
 
 void ClangdServer::formatCode(PathRef File, llvm::StringRef Code,
@@ -612,7 +624,7 @@
         tooling::calculateRangesAfterReplacements(IncludeReplaces, Ranges),
         File)));
   };
-  WorkScheduler.runQuick("Format", File, std::move(Action));
+  WorkScheduler->runQuick("Format", File, std::move(Action));
 }
 
 void ClangdServer::findDocumentHighlights(
@@ -624,8 +636,8 @@
         CB(clangd::findDocumentHighlights(InpAST->AST, Pos));
       };
 
-  WorkScheduler.runWithAST("Highlights", File, std::move(Action),
-                           TUScheduler::InvalidateOnUpdate);
+  WorkScheduler->runWithAST("Highlights", File, std::move(Action),
+                            TUScheduler::InvalidateOnUpdate);
 }
 
 void ClangdServer::findHover(PathRef File, Position Pos,
@@ -639,8 +651,8 @@
     CB(clangd::getHover(InpAST->AST, Pos, std::move(Style), Index));
   };
 
-  WorkScheduler.runWithAST("Hover", File, std::move(Action),
-                           TUScheduler::InvalidateOnUpdate);
+  WorkScheduler->runWithAST("Hover", File, std::move(Action),
+                            TUScheduler::InvalidateOnUpdate);
 }
 
 void ClangdServer::typeHierarchy(PathRef File, Position Pos, int Resolve,
@@ -654,13 +666,13 @@
                                 File));
   };
 
-  WorkScheduler.runWithAST("TypeHierarchy", File, std::move(Action));
+  WorkScheduler->runWithAST("TypeHierarchy", File, std::move(Action));
 }
 
 void ClangdServer::resolveTypeHierarchy(
     TypeHierarchyItem Item, int Resolve, TypeHierarchyDirection Direction,
     Callback<llvm::Optional<TypeHierarchyItem>> CB) {
-  WorkScheduler.run(
+  WorkScheduler->run(
       "Resolve Type Hierarchy", "", [=, CB = std::move(CB)]() mutable {
         clangd::resolveTypeHierarchy(Item, Resolve, Direction, Index);
         CB(Item);
@@ -675,16 +687,16 @@
       return CB(InpAST.takeError());
     CB(clangd::prepareCallHierarchy(InpAST->AST, Pos, File));
   };
-  WorkScheduler.runWithAST("CallHierarchy", File, std::move(Action));
+  WorkScheduler->runWithAST("CallHierarchy", File, std::move(Action));
 }
 
 void ClangdServer::incomingCalls(
     const CallHierarchyItem &Item,
     Callback<std::vector<CallHierarchyIncomingCall>> CB) {
-  WorkScheduler.run("Incoming Calls", "",
-                    [CB = std::move(CB), Item, this]() mutable {
-                      CB(clangd::incomingCalls(Item, Index));
-                    });
+  WorkScheduler->run("Incoming Calls", "",
+                     [CB = std::move(CB), Item, this]() mutable {
+                       CB(clangd::incomingCalls(Item, Index));
+                     });
 }
 
 void ClangdServer::onFileEvent(const DidChangeWatchedFilesParams &Params) {
@@ -695,7 +707,7 @@
 void ClangdServer::workspaceSymbols(
     llvm::StringRef Query, int Limit,
     Callback<std::vector<SymbolInformation>> CB) {
-  WorkScheduler.run(
+  WorkScheduler->run(
       "getWorkspaceSymbols", /*Path=*/"",
       [Query = Query.str(), Limit, CB = std::move(CB), this]() mutable {
         CB(clangd::getWorkspaceSymbols(Query, Limit, Index,
@@ -711,8 +723,8 @@
           return CB(InpAST.takeError());
         CB(clangd::getDocumentSymbols(InpAST->AST));
       };
-  WorkScheduler.runWithAST("DocumentSymbols", File, std::move(Action),
-                           TUScheduler::InvalidateOnUpdate);
+  WorkScheduler->runWithAST("DocumentSymbols", File, std::move(Action),
+                            TUScheduler::InvalidateOnUpdate);
 }
 
 void ClangdServer::foldingRanges(llvm::StringRef File,
@@ -723,8 +735,8 @@
           return CB(InpAST.takeError());
         CB(clangd::getFoldingRanges(InpAST->AST));
       };
-  WorkScheduler.runWithAST("FoldingRanges", File, std::move(Action),
-                           TUScheduler::InvalidateOnUpdate);
+  WorkScheduler->runWithAST("FoldingRanges", File, std::move(Action),
+                            TUScheduler::InvalidateOnUpdate);
 }
 
 void ClangdServer::findImplementations(
@@ -736,7 +748,7 @@
     CB(clangd::findImplementations(InpAST->AST, Pos, Index));
   };
 
-  WorkScheduler.runWithAST("Implementations", File, std::move(Action));
+  WorkScheduler->runWithAST("Implementations", File, std::move(Action));
 }
 
 void ClangdServer::findReferences(PathRef File, Position Pos, uint32_t Limit,
@@ -748,7 +760,7 @@
     CB(clangd::findReferences(InpAST->AST, Pos, Limit, Index));
   };
 
-  WorkScheduler.runWithAST("References", File, std::move(Action));
+  WorkScheduler->runWithAST("References", File, std::move(Action));
 }
 
 void ClangdServer::symbolInfo(PathRef File, Position Pos,
@@ -760,7 +772,7 @@
         CB(clangd::getSymbolInfo(InpAST->AST, Pos));
       };
 
-  WorkScheduler.runWithAST("SymbolInfo", File, std::move(Action));
+  WorkScheduler->runWithAST("SymbolInfo", File, std::move(Action));
 }
 
 void ClangdServer::semanticRanges(PathRef File,
@@ -779,7 +791,7 @@
     }
     CB(std::move(Result));
   };
-  WorkScheduler.runWithAST("SemanticRanges", File, std::move(Action));
+  WorkScheduler->runWithAST("SemanticRanges", File, std::move(Action));
 }
 
 void ClangdServer::documentLinks(PathRef File,
@@ -790,8 +802,8 @@
           return CB(InpAST.takeError());
         CB(clangd::getDocumentLinks(InpAST->AST));
       };
-  WorkScheduler.runWithAST("DocumentLinks", File, std::move(Action),
-                           TUScheduler::InvalidateOnUpdate);
+  WorkScheduler->runWithAST("DocumentLinks", File, std::move(Action),
+                            TUScheduler::InvalidateOnUpdate);
 }
 
 void ClangdServer::semanticHighlights(
@@ -802,8 +814,8 @@
           return CB(InpAST.takeError());
         CB(clangd::getSemanticHighlightings(InpAST->AST));
       };
-  WorkScheduler.runWithAST("SemanticHighlights", File, std::move(Action),
-                           TUScheduler::InvalidateOnUpdate);
+  WorkScheduler->runWithAST("SemanticHighlights", File, std::move(Action),
+                            TUScheduler::InvalidateOnUpdate);
 }
 
 void ClangdServer::getAST(PathRef File, Range R,
@@ -835,21 +847,21 @@
         if (!Success)
           CB(llvm::None);
       };
-  WorkScheduler.runWithAST("GetAST", File, std::move(Action));
+  WorkScheduler->runWithAST("GetAST", File, std::move(Action));
 }
 
 void ClangdServer::customAction(PathRef File, llvm::StringRef Name,
                                 Callback<InputsAndAST> Action) {
-  WorkScheduler.runWithAST(Name, File, std::move(Action));
+  WorkScheduler->runWithAST(Name, File, std::move(Action));
 }
 
 llvm::StringMap<TUScheduler::FileStats> ClangdServer::fileStats() const {
-  return WorkScheduler.fileStats();
+  return WorkScheduler->fileStats();
 }
 
 LLVM_NODISCARD bool
 ClangdServer::blockUntilIdleForTest(llvm::Optional<double> TimeoutSeconds) {
-  return WorkScheduler.blockUntilIdle(timeoutSeconds(TimeoutSeconds)) &&
+  return WorkScheduler->blockUntilIdle(timeoutSeconds(TimeoutSeconds)) &&
          CDB.blockUntilIdle(timeoutSeconds(TimeoutSeconds)) &&
          (!BackgroundIdx ||
           BackgroundIdx->blockUntilIdleForTest(TimeoutSeconds));
@@ -860,7 +872,7 @@
     DynamicIdx->profile(MT.child("dynamic_index"));
   if (BackgroundIdx)
     BackgroundIdx->profile(MT.child("background_index"));
-  WorkScheduler.profile(MT.child("tuscheduler"));
+  WorkScheduler->profile(MT.child("tuscheduler"));
 }
 } // namespace clangd
 } // namespace clang
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to