in glean/rts/cache.cpp [160:201]
bool LookupCache::Anchor::factById(
Id id,
std::function<void(Pid, Fact::Clause)> f) {
const auto cached = cache->index.withRLockPtr([&](auto rindex) {
const auto i = rindex->ids.find(id);
if (i != rindex->ids.end() && (*i)->tag() == FULL) {
const auto fact = *i;
// It is imporant to call f after we (i.e., touch) have released the read
// lock (since f might use the cache). However, fact needs to exist until
// after we've called f. Grabbing a read lock for delete_lock makes sure
// no facts will be deleted until we're done.
//
// We might consider finer-grained locking if this becomes an issue.
folly::SharedMutex::ReadHolder dont_delete(rindex->delete_lock);
cache->touch(std::move(rindex), fact);
f(fact->type(), fact->clause());
return true;
} else {
return false;
}
});
if (cached) {
++cache->stats->values[Stats::factById_hits];
return true;
}
Fact::unique_ptr fact;
base->factById(id, [&](auto type, auto clause) {
fact = Fact::create({id, type, clause}, FULL);
});
if (fact) {
++cache->stats->values[Stats::factById_misses];
f(fact->type(), fact->clause());
// FIXME: probably do this before f
cache->insert(std::move(fact));
return true;
} else {
++cache->stats->values[Stats::factById_failures];
return false;
}
}