1 package org.simantics.db.layer0.variable;
3 import java.util.HashMap;
5 import java.util.TreeMap;
7 import gnu.trove.map.hash.TObjectLongHashMap;
10 * @author Antti Villberg
17 public class NodeCache<Node,Value> {
19 // Expiration time for items in this cache
20 private long defaultExpirationTimeInNs;
22 // Here we hold all nodes with finite expiration times
23 private TreeMap<Long,Node> expirationTimes = new TreeMap<Long,Node>();
24 // Finite expiration times for nodes
25 private TObjectLongHashMap<Node> exp = new TObjectLongHashMap<Node>(10, 0.5f, -1L);
28 private Map<Node,Value> map = new HashMap<Node,Value>();
30 private boolean disposed;
36 public NodeCache(long defaultExpirationTimeInNs) {
37 this.defaultExpirationTimeInNs = defaultExpirationTimeInNs;
40 public synchronized Value get(Node node) {
44 public synchronized void clearExpired() {
46 long now = System.nanoTime();
47 while(!expirationTimes.isEmpty()) {
48 Long first = expirationTimes.firstKey();
50 Node node = expirationTimes.remove(first);
60 private long scheduleExpiration(Node node, long expiration) {
61 while(expirationTimes.containsKey(expiration)) expiration++;
62 expirationTimes.put(expiration, node);
63 exp.put(node, expiration);
67 private void refreshExpiration(Node node, long newExpiration, boolean existing) {
69 long current = exp.get(node);
72 // We have infinite expiration => do nothing
74 // This is a new value
75 if(newExpiration == 0) {
76 // We require infinite expiration => do nothing
78 scheduleExpiration(node, newExpiration);
84 // This node is already under expiration tracking
85 if(newExpiration == 0) {
86 // We now want infinite expiration => remove expiration time info
87 expirationTimes.remove(current);
90 if(newExpiration > current) {
91 // Update expiration time
92 expirationTimes.remove(current);
93 scheduleExpiration(node, newExpiration);
99 public synchronized void put(Node node, Value value) {
102 Value existing = map.put(node, value);
103 refreshExpiration(node, 0, existing != null);
106 public synchronized void put(Node node, Value value, long expiration) {
109 Value existing = map.put(node, value);
110 refreshExpiration(node, System.nanoTime() + expiration, existing != null);
113 public synchronized void removeListening(Node node) {
116 scheduleExpiration(node, System.nanoTime() + defaultExpirationTimeInNs);
119 public synchronized void remove(Node node) {
122 Long expTime = exp.get(node);
123 if (expTime != null) {
124 expirationTimes.remove(expTime);
129 public synchronized void clear() {
132 expirationTimes.clear();
137 public synchronized void dispose() {
139 expirationTimes.clear();