-package org.simantics.db.layer0.variable;\r
-\r
-import java.util.HashMap;\r
-import java.util.Map;\r
-import java.util.TreeMap;\r
-\r
-import gnu.trove.map.hash.TObjectLongHashMap;\r
-\r
-/**\r
- * @author Antti Villberg\r
- *\r
- * @param <Node>\r
- * @param <Value>\r
- * \r
- * @since 1.23\r
- */\r
-public class NodeCache<Node,Value> {\r
-\r
- // Expiration time for items in this cache\r
- private long defaultExpirationTimeInNs;\r
-\r
- // Here we hold all nodes with finite expiration times\r
- private TreeMap<Long,Node> expirationTimes = new TreeMap<Long,Node>();\r
- // Finite expiration times for nodes\r
- private TObjectLongHashMap<Node> exp = new TObjectLongHashMap<Node>(10, 0.5f, -1L);\r
- \r
- // All node values\r
- private Map<Node,Value> map = new HashMap<Node,Value>();\r
-\r
- private boolean disposed;\r
-\r
- public NodeCache() {\r
- this(1_000_000_000L);\r
- }\r
-\r
- public NodeCache(long defaultExpirationTimeInNs) {\r
- this.defaultExpirationTimeInNs = defaultExpirationTimeInNs;\r
- }\r
-\r
- public synchronized Value get(Node node) {\r
- return map.get(node); \r
- }\r
- \r
- public synchronized void clearExpired() {\r
- \r
- long now = System.nanoTime();\r
- while(!expirationTimes.isEmpty()) {\r
- Long first = expirationTimes.firstKey();\r
- if(first < now) {\r
- Node node = expirationTimes.remove(first);\r
- exp.remove(node);\r
- map.remove(node);\r
- } else {\r
- return;\r
- }\r
- }\r
- \r
- }\r
-\r
- private long scheduleExpiration(Node node, long expiration) {\r
- while(expirationTimes.containsKey(expiration)) expiration++;\r
- expirationTimes.put(expiration, node);\r
- exp.put(node, expiration);\r
- return expiration;\r
- }\r
- \r
- private void refreshExpiration(Node node, long newExpiration, boolean existing) {\r
- \r
- long current = exp.get(node);\r
- if(current == -1) {\r
- if(existing) {\r
- // We have infinite expiration => do nothing\r
- } else {\r
- // This is a new value\r
- if(newExpiration == 0) {\r
- // We require infinite expiration => do nothing\r
- } else {\r
- scheduleExpiration(node, newExpiration);\r
- }\r
- }\r
- return;\r
- }\r
- \r
- // This node is already under expiration tracking\r
- if(newExpiration == 0) {\r
- // We now want infinite expiration => remove expiration time info\r
- expirationTimes.remove(current);\r
- exp.remove(node);\r
- } else {\r
- if(newExpiration > current) {\r
- // Update expiration time\r
- expirationTimes.remove(current);\r
- scheduleExpiration(node, newExpiration);\r
- }\r
- }\r
- \r
- }\r
-\r
- public synchronized void put(Node node, Value value) {\r
- if (disposed)\r
- return;\r
- Value existing = map.put(node, value);\r
- refreshExpiration(node, 0, existing != null);\r
- }\r
-\r
- public synchronized void put(Node node, Value value, long expiration) {\r
- if (disposed)\r
- return;\r
- Value existing = map.put(node, value);\r
- refreshExpiration(node, System.nanoTime() + expiration, existing != null);\r
- }\r
-\r
- public synchronized void removeListening(Node node) {\r
- if (disposed)\r
- return;\r
- scheduleExpiration(node, System.nanoTime() + defaultExpirationTimeInNs);\r
- }\r
-\r
- public synchronized void dispose() {\r
- disposed = true;\r
- expirationTimes.clear();\r
- exp.clear();\r
- map.clear();\r
- }\r
- \r
-}\r
+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 <Node>
+ * @param <Value>
+ *
+ * @since 1.23
+ */
+public class NodeCache<Node,Value> {
+
+ // Expiration time for items in this cache
+ private long defaultExpirationTimeInNs;
+
+ // Here we hold all nodes with finite expiration times
+ private TreeMap<Long,Node> expirationTimes = new TreeMap<Long,Node>();
+ // Finite expiration times for nodes
+ private TObjectLongHashMap<Node> exp = new TObjectLongHashMap<Node>(10, 0.5f, -1L);
+
+ // All node values
+ private Map<Node,Value> map = new HashMap<Node,Value>();
+
+ 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();
+ }
+
+}