1 // Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
3 // You may modify, copy, and redistribute this code under the terms of
4 // the GNU Library Public License version 2.1, with the exception of
5 // the portion of clause 6a after the semicolon (aka the "obnoxious
10 Bug report from a user:
12 I looked at your Cache.java and tried to make good use of it, but I was
13 out of luck - it wouldn't run here. Digging deeper into the code, I came
14 across something that might be considered a bug. But maybe it's just a
18 Starting with an empty cache, Cache.put() immediately followed by
19 Cache.get() on same keys / same object will set Node lru back to null in
20 Node.remove() which is called in get().
22 Assuming this put()-get() sequence is fixed, it will fill the cache, but
25 When cache is filled 100%, we have, at the end of the get(), where
26 size>maxSize is checked, a state that mru == lru == n (from
27 if(lru==null) thus deleteting the newly inserted object. Oops.
30 Hope I made this clear enough. Maybe it's not a problem in xwt due to a
31 different usage scheme of the cache.
37 package org.ibex.util;
39 // FIXME needs to be a weak hash
42 * A Hash table with a fixed size; drops extraneous elements. Uses
45 public class Cache extends Hash {
47 /** head of list is the mru; tail is the lru */
53 public Cache(int maxSize) {
54 super(maxSize * 2, 3);
55 this.maxSize = maxSize;
58 /** A doubly-linked list */
63 public Node(Object k1, Object k2, Object val) { this.k1 = k1; this.k2 = k2; this.val = val; }
67 if (this == lru) lru = prev;
68 if (this == mru) mru = next;
69 if (next != null) next.prev = prev;
70 if (prev != null) prev.next = next;
73 void placeAfter(Node n) {
75 if (n == null) return;
77 if (n.next != null) n.next.prev = this;
81 void placeBefore(Node n) {
83 if (n == null) return;
87 if (prev != null) prev.next = this;
96 public void remove(Object k1, Object k2) {
97 Object o = super.get(k1, k2);
98 if (o != null) ((Node)o).remove();
102 public Object get(Object k1, Object k2) {
103 Node n = (Node)super.get(k1, k2);
104 if (n == null) return null;
111 public void put(Object k1, Object k2, Object v) {
112 Node n = new Node(k1, k2, v);
119 if (super.get(k1, k2) != null) remove(k1, k2);
120 super.put(k1, k2, n);
121 if (size > maxSize) remove(lru.k1, lru.k2);