X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.db.layer0%2Fsrc%2Forg%2Fsimantics%2Fdb%2Flayer0%2Fvariable%2FNodeCache.java;h=5ed9678e9ec41aa4d75f6375b09362a1844f83a1;hb=1ecae6e1ad40507badb8807fb14bb67b4adf199c;hp=04af108401c2cfcff4e404cc5f29fbf93dc49814;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeCache.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeCache.java index 04af10840..5ed9678e9 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeCache.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeCache.java @@ -1,126 +1,144 @@ -package org.simantics.db.layer0.variable; - -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; - -import gnu.trove.map.hash.TObjectLongHashMap; - -/** - * @author Antti Villberg - * - * @param - * @param - * - * @since 1.23 - */ -public class NodeCache { - - // Expiration time for items in this cache - private long defaultExpirationTimeInNs; - - // Here we hold all nodes with finite expiration times - private TreeMap expirationTimes = new TreeMap(); - // Finite expiration times for nodes - private TObjectLongHashMap exp = new TObjectLongHashMap(10, 0.5f, -1L); - - // All node values - private Map map = new HashMap(); - - private boolean disposed; - - public NodeCache() { - this(1_000_000_000L); - } - - public NodeCache(long defaultExpirationTimeInNs) { - this.defaultExpirationTimeInNs = defaultExpirationTimeInNs; - } - - public synchronized Value get(Node node) { - return map.get(node); - } - - public synchronized void clearExpired() { - - long now = System.nanoTime(); - while(!expirationTimes.isEmpty()) { - Long first = expirationTimes.firstKey(); - if(first < now) { - Node node = expirationTimes.remove(first); - exp.remove(node); - map.remove(node); - } else { - return; - } - } - - } - - private long scheduleExpiration(Node node, long expiration) { - while(expirationTimes.containsKey(expiration)) expiration++; - expirationTimes.put(expiration, node); - exp.put(node, expiration); - return expiration; - } - - private void refreshExpiration(Node node, long newExpiration, boolean existing) { - - long current = exp.get(node); - if(current == -1) { - if(existing) { - // We have infinite expiration => do nothing - } else { - // This is a new value - if(newExpiration == 0) { - // We require infinite expiration => do nothing - } else { - scheduleExpiration(node, newExpiration); - } - } - return; - } - - // This node is already under expiration tracking - if(newExpiration == 0) { - // We now want infinite expiration => remove expiration time info - expirationTimes.remove(current); - exp.remove(node); - } else { - if(newExpiration > current) { - // Update expiration time - expirationTimes.remove(current); - scheduleExpiration(node, newExpiration); - } - } - - } - - public synchronized void put(Node node, Value value) { - if (disposed) - return; - Value existing = map.put(node, value); - refreshExpiration(node, 0, existing != null); - } - - public synchronized void put(Node node, Value value, long expiration) { - if (disposed) - return; - Value existing = map.put(node, value); - refreshExpiration(node, System.nanoTime() + expiration, existing != null); - } - - public synchronized void removeListening(Node node) { - if (disposed) - return; - scheduleExpiration(node, System.nanoTime() + defaultExpirationTimeInNs); - } - - public synchronized void dispose() { - disposed = true; - expirationTimes.clear(); - exp.clear(); - map.clear(); - } - -} +package org.simantics.db.layer0.variable; + +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +import gnu.trove.map.hash.TObjectLongHashMap; + +/** + * @author Antti Villberg + * + * @param + * @param + * + * @since 1.23 + */ +public class NodeCache { + + // Expiration time for items in this cache + private long defaultExpirationTimeInNs; + + // Here we hold all nodes with finite expiration times + private TreeMap expirationTimes = new TreeMap(); + // Finite expiration times for nodes + private TObjectLongHashMap exp = new TObjectLongHashMap(10, 0.5f, -1L); + + // All node values + private Map map = new HashMap(); + + private boolean disposed; + + public NodeCache() { + this(1_000_000_000L); + } + + public NodeCache(long defaultExpirationTimeInNs) { + this.defaultExpirationTimeInNs = defaultExpirationTimeInNs; + } + + public synchronized Value get(Node node) { + return map.get(node); + } + + public synchronized void clearExpired() { + + long now = System.nanoTime(); + while(!expirationTimes.isEmpty()) { + Long first = expirationTimes.firstKey(); + if(first < now) { + Node node = expirationTimes.remove(first); + exp.remove(node); + map.remove(node); + } else { + return; + } + } + + } + + private long scheduleExpiration(Node node, long expiration) { + while(expirationTimes.containsKey(expiration)) expiration++; + expirationTimes.put(expiration, node); + exp.put(node, expiration); + return expiration; + } + + private void refreshExpiration(Node node, long newExpiration, boolean existing) { + + long current = exp.get(node); + if(current == -1) { + if(existing) { + // We have infinite expiration => do nothing + } else { + // This is a new value + if(newExpiration == 0) { + // We require infinite expiration => do nothing + } else { + scheduleExpiration(node, newExpiration); + } + } + return; + } + + // This node is already under expiration tracking + if(newExpiration == 0) { + // We now want infinite expiration => remove expiration time info + expirationTimes.remove(current); + exp.remove(node); + } else { + if(newExpiration > current) { + // Update expiration time + expirationTimes.remove(current); + scheduleExpiration(node, newExpiration); + } + } + + } + + public synchronized void put(Node node, Value value) { + if (disposed) + return; + Value existing = map.put(node, value); + refreshExpiration(node, 0, existing != null); + } + + public synchronized void put(Node node, Value value, long expiration) { + if (disposed) + return; + Value existing = map.put(node, value); + refreshExpiration(node, System.nanoTime() + expiration, existing != null); + } + + public synchronized void removeListening(Node node) { + if (disposed) + return; + scheduleExpiration(node, System.nanoTime() + defaultExpirationTimeInNs); + } + + public synchronized void remove(Node node) { + if (disposed) + return; + Long expTime = exp.get(node); + if (expTime != null) { + expirationTimes.remove(expTime); + } + map.remove(node); + } + + public synchronized void clear() { + if (disposed) + return; + expirationTimes.clear(); + exp.clear(); + map.clear(); + } + + public synchronized void dispose() { + disposed = true; + expirationTimes.clear(); + exp.clear(); + map.clear(); + } + +}