28 struct PerInstanceState;
30 using PointerAndFlag = std::pair<ValueT *, std::atomic<bool>>;
46 std::shared_ptr<PointerAndFlag>
ptr =
47 std::make_shared<PointerAndFlag>(std::make_pair(
nullptr,
false));
54 std::weak_ptr<PerInstanceState> keepalive;
66 Owner(Observer &observer)
67 : value(std::make_unique<ValueT>()), ptrRef(observer.ptr) {
68 observer.ptr->second =
true;
69 observer.ptr->first = value.get();
72 if (std::shared_ptr<PointerAndFlag>
ptr = ptrRef.lock()) {
78 Owner(Owner &&) =
default;
79 Owner &operator=(Owner &&) =
default;
81 std::unique_ptr<ValueT> value;
82 std::weak_ptr<PointerAndFlag> ptrRef;
89 struct PerInstanceState {
94 void remove(ValueT *value) {
97 llvm::sys::SmartScopedLock<true> threadInstanceLock(instanceMutex);
98 auto it = llvm::find_if(instances, [&](Owner &instance) {
99 return instance.value.get() == value;
101 assert(it != instances.end() &&
"expected value to exist in cache");
118 struct CacheType :
public llvm::SmallDenseMap<PerInstanceState *, Observer> {
123 for (
auto &[instance, observer] : *
this)
124 if (std::shared_ptr<PerInstanceState> state = observer.keepalive.lock())
125 state->remove(observer.ptr->first);
130 void clearExpiredEntries() {
132 [](
const auto &entry) {
return !entry.second.ptr->second; });
146 CacheType &staticCache = getStaticCache();
147 Observer &threadInstance = staticCache[perInstanceState.get()];
148 if (ValueT *value = threadInstance.ptr->first)
153 llvm::sys::SmartScopedLock<true> threadInstanceLock(
154 perInstanceState->instanceMutex);
155 perInstanceState->instances.emplace_back(threadInstance);
157 threadInstance.keepalive = perInstanceState;
167 ValueT &value = *threadInstance.ptr->first;
168 staticCache.clearExpiredEntries();
180 static CacheType &getStaticCache() {
181 static LLVM_THREAD_LOCAL CacheType cache;
185 std::shared_ptr<PerInstanceState> perInstanceState =
186 std::make_shared<PerInstanceState>();