diff options
Diffstat (limited to 'src/main/java/org/javacs/Cache.java')
-rw-r--r-- | src/main/java/org/javacs/Cache.java | 69 |
1 files changed, 43 insertions, 26 deletions
diff --git a/src/main/java/org/javacs/Cache.java b/src/main/java/org/javacs/Cache.java index 2319e94..b1c893d 100644 --- a/src/main/java/org/javacs/Cache.java +++ b/src/main/java/org/javacs/Cache.java @@ -6,51 +6,68 @@ import java.nio.file.Path; import java.time.Instant; import java.util.HashMap; import java.util.Map; -import java.util.function.Function; +import java.util.Objects; +/** Cache maps a file + an arbitrary key to a value. When the file is modified, the mapping expires. */ class Cache<K, V> { - private class Entry { - final V value; - final Instant created = Instant.now(); + private class Key { + final Path file; + final K key; - Entry(V value) { - this.value = value; + Key(Path file, K key) { + this.file = file; + this.key = key; } - } - private Map<K, Entry> map = new HashMap<>(); + @Override + public boolean equals(Object other) { + if (other.getClass() != Key.class) return false; + var that = (Key) other; + return Objects.equals(this.key, that.key) && Objects.equals(this.file, that.file); + } - private final Function<K, V> loader; + @Override + public int hashCode() { + return Objects.hash(file, key); + } + } - private final Function<K, Path> asFile; + private class Value { + final V value; + final Instant created = Instant.now(); - Cache(Function<K, V> loader, Function<K, Path> asFile) { - this.loader = loader; - this.asFile = asFile; + Value(V value) { + this.value = value; + } } - private void load(K key) { - // TODO limit total size of cache - var value = loader.apply(key); - map.put(key, new Entry(value)); - } + private final Map<Key, Value> map = new HashMap<>(); - V get(K key) { - // Check if file is missing from cache - if (!map.containsKey(key)) load(key); + boolean needs(Path file, K key) { + // If key is not in map, it needs to be loaded + if (!map.containsKey(key)) return true; - // Check if file is out-of-date + // If key was loaded before file was last modified, it needs to be reloaded var value = map.get(key); - var file = asFile.apply(key); Instant modified; try { modified = Files.getLastModifiedTime(file).toInstant(); } catch (IOException e) { throw new RuntimeException(e); } - if (value.created.isBefore(modified)) load(key); + return value.created.isBefore(modified); + } - // Get up-to-date file from cache - return map.get(key).value; + void load(Path file, K key, V value) { + // TODO limit total size of cache + map.put(new Key(file, key), new Value(value)); + } + + V get(Path file, K key) { + var k = new Key(file, key); + if (!map.containsKey(k)) { + throw new IllegalArgumentException(k + " is not in map " + map); + } + return map.get(k).value; } } |