12#include "llvm/Support/AdvisoryLock.h"
13#include "llvm/Support/Chrono.h"
14#include "llvm/Support/Error.h"
15#include "llvm/Support/IOSandbox.h"
21class ReaderWriterLock :
public llvm::AdvisoryLock {
22 ModuleCacheEntry &Entry;
23 std::optional<unsigned> OwnedGeneration;
26 ReaderWriterLock(ModuleCacheEntry &Entry) : Entry(Entry) {}
28 Expected<bool> tryLock()
override {
29 std::lock_guard<std::mutex> Lock(Entry.Mutex);
33 OwnedGeneration = Entry.Generation;
37 llvm::WaitForUnlockResult
38 waitForUnlockFor(std::chrono::seconds MaxSeconds)
override {
39 assert(!OwnedGeneration);
40 std::unique_lock<std::mutex> Lock(Entry.Mutex);
41 unsigned CurrentGeneration = Entry.Generation;
42 bool Success = Entry.CondVar.wait_for(Lock, MaxSeconds, [&] {
45 return !Entry.Locked || Entry.Generation != CurrentGeneration;
47 return Success ? llvm::WaitForUnlockResult::Success
48 : llvm::WaitForUnlockResult::Timeout;
51 std::error_code unsafeUnlock()
override {
53 std::lock_guard<std::mutex> Lock(Entry.Mutex);
54 Entry.Generation += 1;
57 Entry.CondVar.notify_all();
61 ~ReaderWriterLock()
override {
62 if (OwnedGeneration) {
64 std::lock_guard<std::mutex> Lock(Entry.Mutex);
67 if (*OwnedGeneration == Entry.Generation)
70 Entry.CondVar.notify_all();
76 ModuleCacheEntries &Entries;
82 InMemoryModuleCache InMemory;
85 InProcessModuleCache(ModuleCacheEntries &Entries) : Entries(Entries) {}
87 std::unique_ptr<llvm::AdvisoryLock> getLock(StringRef Filename)
override {
88 auto &Entry = [&]() -> ModuleCacheEntry & {
89 std::lock_guard<std::mutex> Lock(Entries.Mutex);
90 auto &Entry = Entries.Map[Filename];
92 Entry = std::make_unique<ModuleCacheEntry>();
95 return std::make_unique<ReaderWriterLock>(Entry);
98 std::time_t getModuleTimestamp(StringRef Filename)
override {
99 auto &Timestamp = [&]() -> std::atomic<std::time_t> & {
100 std::lock_guard<std::mutex> Lock(Entries.Mutex);
101 auto &Entry = Entries.Map[Filename];
103 Entry = std::make_unique<ModuleCacheEntry>();
107 return Timestamp.load();
110 void updateModuleTimestamp(StringRef Filename)
override {
112 auto &Timestamp = [&]() -> std::atomic<std::time_t> & {
113 std::lock_guard<std::mutex> Lock(Entries.Mutex);
114 auto &Entry = Entries.Map[Filename];
116 Entry = std::make_unique<ModuleCacheEntry>();
120 Timestamp.store(llvm::sys::toTimeT(std::chrono::system_clock::now()));
123 void maybePrune(StringRef Path, time_t PruneInterval,
124 time_t PruneAfter)
override {
130 InMemoryModuleCache &getInMemoryModuleCache()
override {
return InMemory; }
131 const InMemoryModuleCache &getInMemoryModuleCache()
const override {
135 std::error_code write(StringRef Path, llvm::MemoryBufferRef Buffer)
override {
137 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
144 Expected<std::unique_ptr<llvm::MemoryBuffer>>
145 read(StringRef
FileName, off_t &Size, time_t &ModTime)
override {
147 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
156std::shared_ptr<ModuleCache>
158 return std::make_shared<InProcessModuleCache>(Entries);
The module cache used for compiling modules implicitly.
std::shared_ptr< ModuleCache > makeInProcessModuleCache(ModuleCacheEntries &Entries)
The JSON file list parser is used to communicate input to InstallAPI.
Expected< std::unique_ptr< llvm::MemoryBuffer > > readImpl(StringRef FileName, off_t &Size, time_t &ModTime)
Shared implementation of ModuleCache::read().
@ Success
Annotation was successful.
void maybePruneImpl(StringRef Path, time_t PruneInterval, time_t PruneAfter)
Shared implementation of ModuleCache::maybePrune().
std::error_code writeImpl(StringRef Path, llvm::MemoryBufferRef Buffer)
Shared implementation of ModuleCache::write().
std::atomic< std::time_t > Timestamp