================
@@ -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