================
@@ -151,68 +155,181 @@ 
DependencyScanningFilesystemSharedCache::getOutOfDateEntries(
   return InvalidDiagInfo;
 }
 
-const CachedFileSystemEntry *
-DependencyScanningFilesystemSharedCache::CacheShard::findEntryByFilename(
-    StringRef Filename) const {
-  assert(llvm::sys::path::is_absolute_gnu(Filename));
-  std::lock_guard<std::mutex> LockGuard(CacheLock);
-  auto It = CacheByFilename.find(Filename);
-  return It == CacheByFilename.end() ? nullptr : It->getValue().first;
-}
-
-const CachedFileSystemEntry *
-DependencyScanningFilesystemSharedCache::CacheShard::findEntryByUID(
-    llvm::sys::fs::UniqueID UID) const {
-  std::lock_guard<std::mutex> LockGuard(CacheLock);
-  auto It = EntriesByUID.find(UID);
-  return It == EntriesByUID.end() ? nullptr : It->getSecond();
-}
-
 const CachedFileSystemEntry &
 DependencyScanningFilesystemSharedCache::CacheShard::
     getOrEmplaceEntryForFilename(StringRef Filename,
                                  llvm::ErrorOr<llvm::vfs::Status> Stat) {
   std::lock_guard<std::mutex> LockGuard(CacheLock);
-  auto [It, Inserted] = CacheByFilename.insert({Filename, {nullptr, nullptr}});
-  auto &[CachedEntry, CachedRealPath] = It->getValue();
-  if (!CachedEntry) {
-    // The entry is not present in the shared cache. Either the cache doesn't
-    // know about the file at all, or it only knows about its real path.
-    assert((Inserted || CachedRealPath) && "existing file with empty pair");
-    CachedEntry =
+  auto [It, Inserted] = CacheByFilename.try_emplace(Filename);
+  auto &State = It->getValue();
+  if (!State.Entry) {
+    // The entry is not present in the shared cache. This method runs only
+    // from inside a producer slot held by the caller, so either the cache
+    // state was just freshly inserted or it already carries an in-flight
+    // slot.
+    assert((Inserted || State.InProgress) &&
+           "cache state should be fresh or carry an in-flight slot held by "
+           "the caller");
+    State.Entry =
         new (EntryStorage.Allocate()) CachedFileSystemEntry(std::move(Stat));
   }
-  return *CachedEntry;
+  return *State.Entry;
+}
+
+DependencyScanningFilesystemSharedCache::SlotAcquisitionResult
+DependencyScanningFilesystemSharedCache::CacheShard::acquireFilenameSlot(
+    StringRef Filename) {
+  assert(llvm::sys::path::is_absolute_gnu(Filename));
+  while (true) {
+    std::shared_ptr<InProgressEntry> Pending;
+    {
+      std::lock_guard<std::mutex> ShardLock(CacheLock);
+      auto &State = CacheByFilename[Filename];
+
+      // Cache hit.
+      if (State.Entry)
+        return SlotAcquisitionResult{State.Entry, nullptr};
+
+      // No outstanding query: install an in-progress entry and become the
+      // producer.
+      if (!State.InProgress) {
+        State.InProgress = std::make_shared<InProgressEntry>();
+        return SlotAcquisitionResult{nullptr, State.InProgress};
+      }
+
+      // Another worker is producing for this filename. Capture the shared_ptr
+      // by copy so the slot stays alive for us to wait on after we release the
+      // shard lock (the producer resets State.InProgress on publish).
+      Pending = State.InProgress;
+    }
+
+    // Wait for the producer on the slot's own mutex/CV, with the shard lock
+    // released so unrelated keys in this shard are not blocked by our wait.
+    const CachedFileSystemEntry *Result;
+    {
+      std::unique_lock<std::mutex> EntryLock(Pending->Mutex);
+      Pending->CondVar.wait(EntryLock, [&] { return Pending->Done; });
+      Result = Pending->Result;
+    }
+
+    // A producer that deliberately does not cache its result (e.g. an uncached
+    // negative stat) publishes a null entry. Retry the lookup so this worker
+    // re-runs the query rather than adopting a missing result.
----------------
artemcm wrote:

Fair point. Refactored to have `InProgressEntry` hold `ErrorOr<const 
CachedFileSystemEntry *>` so that it can share negative `stat` lookups with 
awaiting workers. 

https://github.com/llvm/llvm-project/pull/199680
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to