package jelectrum; import java.util.Map; import java.util.Set; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; public class BandingMapSet<K,V> implements MapSet<K, V> { private MapSet<K, V> inner; private long gatherWaitMs; private LinkedList<Map.Entry<K, V> > waiting_map; private SimpleFuture<V> future; private Object magic_lock; public BandingMapSet(MapSet<K,V> inner, long gatherWaitMs) { this.inner = inner; this.gatherWaitMs = gatherWaitMs; magic_lock = new Object(); waiting_map = new LinkedList<Map.Entry<K, V> >(); new BandThread().start(); } public Set<V> getSet(Object key) { return inner.getSet(key); } public void add(K key, V value) { SimpleFuture<V> f = null; synchronized(magic_lock) { if (future != null) { waiting_map.add(new java.util.AbstractMap.SimpleEntry<K,V>(key, value)); f = future; } magic_lock.notifyAll(); } if (f != null) { f.get(); return; } inner.add(key,value); } public void addAll(Collection<Map.Entry<K, V> > lst) { inner.addAll(lst); } public class BandThread extends Thread { public BandThread() { setDaemon(true); setName("Bandthread"); } public void run() { while(true) { doRun(); } } private void doRun() { SimpleFuture<V> f = new SimpleFuture<V>(); try { synchronized(magic_lock) { future = f; magic_lock.wait(); } sleep(gatherWaitMs); synchronized(magic_lock) { future = null; } //System.out.println("Banding: " + waiting_map.size()); inner.addAll(waiting_map); f.setResult(null); waiting_map.clear(); } catch(Throwable t) { if (t instanceof RuntimeException) { f.setException((RuntimeException)t); } else { f.setException(new RuntimeException(t)); } } } } }