diff src/main/java/edu/harvard/iq/dataverse/util/LruCache.java @ 10:a50cf11e5178

Rewrite LGDataverse completely upgrading to dataverse4.0
author Zoe Hong <zhong@mpiwg-berlin.mpg.de>
date Tue, 08 Sep 2015 17:00:21 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/edu/harvard/iq/dataverse/util/LruCache.java	Tue Sep 08 17:00:21 2015 +0200
@@ -0,0 +1,88 @@
+package edu.harvard.iq.dataverse.util;
+
+import java.util.LinkedHashMap;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * A thread-safe implementation of a capped-size cache, where the removal is done 
+ * based on the "Least Recently Used" strategy.
+ * This implementation allows some scenarios where the removed values are not the
+ * least recently used, in order to provide better performance.
+ * 
+ * @author michael
+ * @param <K> Class for the cache keys
+ * @param <V> Class for the cache values
+ */
+public class LruCache<K,V> {
+    private final LinkedHashMap<K, V> cache = new LinkedHashMap<>(10, 0.75f, true);
+    private final ReentrantLock cacheLock = new ReentrantLock();
+    private long maxSize = 128;
+    
+    /**
+     * @param k The key to get
+     * @return The value associated with {@code k}, or {@code null}, if there isn't any.
+     */
+    public V get( K k ) {
+        try {
+            cacheLock.lock();
+            return cache.get(k);
+        } finally { cacheLock.unlock(); }
+    }
+    
+    /**
+     * Associates {@code k} with {@code v}.
+     * @param k the key
+     * @param v the value
+     * @return {@code v}, to allow method call chaining.
+     */
+    public V put( K k, V v ) {
+        try {
+            cacheLock.lock();
+            cache.put(k, v);
+            shrinkToMaxSize();
+            return v;
+        } finally { cacheLock.unlock(); }
+    }
+
+    public long size() {
+        try {
+            cacheLock.lock();
+            return cache.size();
+        } finally { cacheLock.unlock(); }
+    }
+        
+    public long getMaxSize() {
+        return maxSize;
+    }
+
+    public void setMaxSize(long maxSize) {
+        if ( maxSize < 1 ) {
+            throw new IllegalArgumentException("Max cache size can't be less than 1");
+        }
+        try {
+            cacheLock.lock();
+            this.maxSize = maxSize;
+            shrinkToMaxSize();
+        } finally { cacheLock.unlock(); }
+    }
+    
+    public void invalidate() {
+        try {
+            cacheLock.lock();
+            cache.clear();
+        } finally { cacheLock.unlock(); }
+    }
+    
+    public void invalidate( K k ) {
+        try {
+            cacheLock.lock();
+            cache.remove(k);
+        } finally { cacheLock.unlock(); }
+    }
+    
+    private void shrinkToMaxSize() {
+        while( cache.size() > getMaxSize() ) {
+            cache.remove( cache.entrySet().iterator().next().getKey() );
+        }
+    }
+}