Changeset View
Changeset View
Standalone View
Standalone View
clang-tools-extra/clangd/TUScheduler.cpp
Show First 20 Lines • Show All 218 Lines • ▼ Show 20 Lines | struct Association { | ||||
Association *Next; | Association *Next; | ||||
}; | }; | ||||
llvm::StringMap<Association, llvm::BumpPtrAllocator &> HeaderToMain; | llvm::StringMap<Association, llvm::BumpPtrAllocator &> HeaderToMain; | ||||
llvm::StringMap<Association *, llvm::BumpPtrAllocator &> MainToFirst; | llvm::StringMap<Association *, llvm::BumpPtrAllocator &> MainToFirst; | ||||
std::atomic<size_t> UsedBytes; // Updated after writes. | std::atomic<size_t> UsedBytes; // Updated after writes. | ||||
mutable std::mutex Mu; | mutable std::mutex Mu; | ||||
void invalidate(Association *First) { | void invalidate(Association *First) { | ||||
// Association might've already been invalidated. | |||||
if (!First->Next) | |||||
return; | |||||
Association *Current = First; | Association *Current = First; | ||||
do { | do { | ||||
Association *Next = Current->Next; | Association *Next = Current->Next; | ||||
Current->Next = nullptr; | Current->Next = nullptr; | ||||
Current = Next; | Current = Next; | ||||
} while (Current != First); | } while (Current != First); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | public: | ||||
// Mark MainFile as gone. | // Mark MainFile as gone. | ||||
// This will *not* disassociate headers with MainFile immediately, but they | // This will *not* disassociate headers with MainFile immediately, but they | ||||
// will be eligible for association with other files that get update()d. | // will be eligible for association with other files that get update()d. | ||||
void remove(PathRef MainFile) { | void remove(PathRef MainFile) { | ||||
std::lock_guard<std::mutex> Lock(Mu); | std::lock_guard<std::mutex> Lock(Mu); | ||||
Association *&First = MainToFirst[MainFile]; | Association *&First = MainToFirst[MainFile]; | ||||
if (First) | if (First) | ||||
invalidate(First); | invalidate(First); | ||||
// MainToFirst entry should stay alive, as Associations might be pointing at | |||||
sammccall: Hmm, this leaves MainToFirst pointing to an invalidated entry.
Would it make more sense to just… | |||||
kadircetAuthorUnsubmitted Thanks! Yeah that makes sense + now there's a point for First being a reference :P kadircet: Thanks! Yeah that makes sense + now there's a point for `First` being a reference :P | |||||
// its key. | |||||
} | } | ||||
/// Get the mainfile associated with Header, or the empty string if none. | /// Get the mainfile associated with Header, or the empty string if none. | ||||
std::string get(PathRef Header) const { | std::string get(PathRef Header) const { | ||||
std::lock_guard<std::mutex> Lock(Mu); | std::lock_guard<std::mutex> Lock(Mu); | ||||
return HeaderToMain.lookup(Header).MainFile.str(); | return HeaderToMain.lookup(Header).MainFile.str(); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,390 Lines • Show Last 20 Lines |
Hmm, this leaves MainToFirst pointing to an invalidated entry.
Would it make more sense to just null out the value (i.e. First here)?
Then I think we need no code changes elsewhere, as update() already checks if First already exists before invalidating.
(This special case would occur on a rarer path, but the real reason for my preference is that I think the data structure is easier to interpret)