[clang-tools-extra] [clangd] [Modules] Support Reusable Modules Builder (PR #106683)

kadir çetinkaya via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 12 01:04:50 PST 2024


================
@@ -316,36 +295,187 @@ llvm::Error buildModuleFile(llvm::StringRef ModuleName,
   if (Clang->getDiagnostics().hasErrorOccurred())
     return llvm::createStringError("Compilation failed");
 
-  BuiltModuleFiles.addModuleFile(ModuleName, Inputs.CompileCommand.Output);
-  return llvm::Error::success();
+  return ModuleFile{ModuleName, Inputs.CompileCommand.Output};
 }
+
+bool ReusablePrerequisiteModules::canReuse(
+    const CompilerInvocation &CI,
+    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) const {
+  if (RequiredModules.empty())
+    return true;
+
+  SmallVector<StringRef> BMIPaths;
+  for (auto &MF : RequiredModules)
+    BMIPaths.push_back(MF->getModuleFilePath());
+  return IsModuleFilesUpToDate(BMIPaths, *this, VFS);
+}
+
+class ModuleFileCache {
+public:
+  ModuleFileCache(const GlobalCompilationDatabase &CDB) : CDB(CDB) {}
+  const GlobalCompilationDatabase &getCDB() const { return CDB; }
+
+  std::shared_ptr<const ModuleFile> getModule(StringRef ModuleName);
+
+  void add(StringRef ModuleName, std::shared_ptr<const ModuleFile> ModuleFile) {
+    std::lock_guard<std::mutex> Lock(ModuleFilesMutex);
+
+    ModuleFiles.insert_or_assign(ModuleName, ModuleFile);
+  }
+
+  void remove(StringRef ModuleName);
+
+private:
+  const GlobalCompilationDatabase &CDB;
+
+  llvm::StringMap<std::weak_ptr<const ModuleFile>> ModuleFiles;
+  // Mutex to guard accesses to ModuleFiles.
+  std::mutex ModuleFilesMutex;
+};
+
+std::shared_ptr<const ModuleFile>
+ModuleFileCache::getModule(StringRef ModuleName) {
+  std::lock_guard<std::mutex> Lock(ModuleFilesMutex);
+
+  auto Iter = ModuleFiles.find(ModuleName);
+  if (Iter == ModuleFiles.end())
+    return nullptr;
+
+  if (Iter->second.expired()) {
+    ModuleFiles.erase(Iter);
+    return nullptr;
+  }
+
+  return Iter->second.lock();
----------------
kadircet wrote:

again we can actually lose the reference between `expired` and `lock` call here (e.g. another thread destroys the last reference right after we called `expired`).

can you instead do:
```cpp
if (auto Res = Iter->second.lock())
  return Res;
ModuleFiles.erase(Iter);
return nullptr;
```

here `lock` atomically makes a copy, if weak_ptr hasn't expired.

https://github.com/llvm/llvm-project/pull/106683


More information about the cfe-commits mailing list