forked from swiftlang/swift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCache.cpp
142 lines (119 loc) · 4.29 KB
/
Cache.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//===--- Cache.cpp - Caching mechanism implementation ---------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#if defined(__APPLE__)
#include "Darwin/Cache-Mac.cpp"
#else
// This file implements a default caching implementation that never evicts
// its entries.
#include "swift/Basic/Cache.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Mutex.h"
using namespace swift::sys;
using llvm::StringRef;
namespace {
struct DefaultCacheKey {
void *Key = nullptr;
CacheImpl::CallBacks *CBs = nullptr;
//DefaultCacheKey() = default;
DefaultCacheKey(void *Key, CacheImpl::CallBacks *CBs) : Key(Key), CBs(CBs) {}
};
struct DefaultCache {
llvm::sys::Mutex Mux;
CacheImpl::CallBacks CBs;
llvm::DenseMap<DefaultCacheKey, void *> Entries;
explicit DefaultCache(CacheImpl::CallBacks CBs) : CBs(std::move(CBs)) { }
};
} // end anonymous namespace
namespace llvm {
template<> struct DenseMapInfo<DefaultCacheKey> {
static inline DefaultCacheKey getEmptyKey() {
return { DenseMapInfo<void*>::getEmptyKey(), nullptr };
}
static inline DefaultCacheKey getTombstoneKey() {
return { DenseMapInfo<void*>::getTombstoneKey(), nullptr };
}
static unsigned getHashValue(const DefaultCacheKey &Val) {
uintptr_t Hash = Val.CBs->keyHashCB(Val.Key, nullptr);
return DenseMapInfo<uintptr_t>::getHashValue(Hash);
}
static bool isEqual(const DefaultCacheKey &LHS, const DefaultCacheKey &RHS) {
if (LHS.Key == RHS.Key)
return true;
if (LHS.Key == DenseMapInfo<void*>::getEmptyKey() ||
LHS.Key == DenseMapInfo<void*>::getTombstoneKey() ||
RHS.Key == DenseMapInfo<void*>::getEmptyKey() ||
RHS.Key == DenseMapInfo<void*>::getTombstoneKey())
return false;
return LHS.CBs->keyIsEqualCB(LHS.Key, RHS.Key, nullptr);
}
};
} // namespace llvm
CacheImpl::ImplTy CacheImpl::create(StringRef Name, const CallBacks &CBs) {
return new DefaultCache(CBs);
}
void CacheImpl::setAndRetain(void *Key, void *Value, size_t Cost) {
DefaultCache &DCache = *static_cast<DefaultCache*>(Impl);
llvm::sys::ScopedLock L(DCache.Mux);
DefaultCacheKey CKey(Key, &DCache.CBs);
auto Entry = DCache.Entries.find(CKey);
if (Entry != DCache.Entries.end()) {
DCache.CBs.keyDestroyCB(Entry->first.Key, nullptr);
DCache.CBs.valueDestroyCB(Entry->second, nullptr);
DCache.Entries.erase(Entry);
}
DCache.Entries[CKey] = Value;
// FIXME: Not thread-safe! It should avoid deleting the value until
// 'releaseValue is called on it.
}
bool CacheImpl::getAndRetain(const void *Key, void **Value_out) {
DefaultCache &DCache = *static_cast<DefaultCache*>(Impl);
llvm::sys::ScopedLock L(DCache.Mux);
DefaultCacheKey CKey(const_cast<void*>(Key), &DCache.CBs);
auto Entry = DCache.Entries.find(CKey);
if (Entry != DCache.Entries.end()) {
// FIXME: Not thread-safe! It should avoid deleting the value until
// 'releaseValue is called on it.
*Value_out = Entry->second;
return true;
}
return false;
}
void CacheImpl::releaseValue(void *Value) {
// FIXME: Implementation.
}
bool CacheImpl::remove(const void *Key) {
DefaultCache &DCache = *static_cast<DefaultCache*>(Impl);
llvm::sys::ScopedLock L(DCache.Mux);
DefaultCacheKey CKey(const_cast<void*>(Key), &DCache.CBs);
auto Entry = DCache.Entries.find(CKey);
if (Entry != DCache.Entries.end()) {
DCache.CBs.keyDestroyCB(Entry->first.Key, nullptr);
DCache.CBs.valueDestroyCB(Entry->second, nullptr);
DCache.Entries.erase(Entry);
return true;
}
return false;
}
void CacheImpl::removeAll() {
DefaultCache &DCache = *static_cast<DefaultCache*>(Impl);
llvm::sys::ScopedLock L(DCache.Mux);
for (auto Entry : DCache.Entries) {
DCache.CBs.keyDestroyCB(Entry.first.Key, nullptr);
DCache.CBs.valueDestroyCB(Entry.second, nullptr);
}
DCache.Entries.clear();
}
void CacheImpl::destroy() {
removeAll();
delete static_cast<DefaultCache*>(Impl);
}
#endif // finish default implementation