org.snapscript.common.CopyOnWriteCache Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of snap Show documentation
Show all versions of snap Show documentation
Dynamic scripting for the JVM
package org.snapscript.common;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class CopyOnWriteCache implements Cache {
private volatile MapUpdater updater;
private volatile Map cache;
public CopyOnWriteCache() {
this(16);
}
public CopyOnWriteCache(int size) {
this(16, 0.5f);
}
public CopyOnWriteCache(int size, float density) {
this.updater = new MapUpdater(size, density);
this.cache = new HashMap();
}
@Override
public Set keySet() {
return cache.keySet();
}
@Override
public V take(K key) {
return updater.take(key);
}
@Override
public V fetch(K key) {
return cache.get(key);
}
@Override
public boolean isEmpty() {
return cache.isEmpty();
}
@Override
public boolean contains(K key) {
return cache.containsKey(key);
}
@Override
public void cache(K key, V value) {
updater.cache(key, value);
}
@Override
public void clear() {
updater.clear();
}
@Override
public int size() {
return cache.size();
}
@Override
public String toString() {
return String.valueOf(cache);
}
private class MapUpdater {
private final Map empty;
private final float density;
private final int size;
public MapUpdater(int size, float density) {
this.empty = new HashMap();
this.density = density;
this.size = size;
}
public synchronized void cache(K key, V value) {
V existing = cache.get(key);
if(existing != value) { // reduce churn
Map copy = new HashMap(size, density);
copy.putAll(cache);
copy.put(key, value);
cache = copy;
}
}
public synchronized V take(K key) {
V existing = cache.get(key);
if(existing != null) {
Map copy = new HashMap(size, density);
copy.putAll(cache);
copy.remove(key);
cache = copy;
}
return existing;
}
public synchronized void clear() {
cache = empty;
}
}
}