Skip to content

Commit ef5b651

Browse files
BATIK-1271: Make AWTGlyphGeometryCache thread safe
1 parent 93d9e9d commit ef5b651

1 file changed

Lines changed: 7 additions & 182 deletions

File tree

batik-gvt/src/main/java/org/apache/batik/gvt/font/AWTGlyphGeometryCache.java

Lines changed: 7 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ Licensed to the Apache Software Foundation (ASF) under one or more
1818
*/
1919
package org.apache.batik.gvt.font;
2020

21+
import org.apache.xmlgraphics.image.loader.util.SoftMapCache;
22+
2123
import java.awt.Shape;
2224
import java.awt.geom.Rectangle2D;
23-
import java.lang.ref.ReferenceQueue;
24-
import java.lang.ref.SoftReference;
2525

2626
/**
2727
* This class represents a doubly indexed hash table, which holds
@@ -32,167 +32,30 @@ Licensed to the Apache Software Foundation (ASF) under one or more
3232
* @version $Id$
3333
*/
3434
public class AWTGlyphGeometryCache {
35-
36-
/**
37-
* The initial capacity
38-
*/
39-
protected static final int INITIAL_CAPACITY = 71;
40-
41-
/**
42-
* The underlying array
43-
*/
44-
protected Entry[] table;
45-
46-
/**
47-
* The number of entries
48-
*/
49-
protected int count;
50-
51-
/**
52-
* The reference queue.
53-
*/
54-
protected ReferenceQueue referenceQueue = new ReferenceQueue();
55-
56-
/**
57-
* Creates a new AWTGlyphGeometryCache.
58-
*/
59-
public AWTGlyphGeometryCache() {
60-
table = new Entry[INITIAL_CAPACITY];
61-
}
62-
63-
/**
64-
* Creates a new AWTGlyphGeometryCache.
65-
* @param c The inital capacity.
66-
*/
67-
public AWTGlyphGeometryCache(int c) {
68-
table = new Entry[c];
69-
}
70-
71-
/**
72-
* Returns the size of this table.
73-
*/
74-
public int size() {
75-
return count;
76-
}
35+
private SoftMapCache table = new SoftMapCache(true);
7736

7837
/**
7938
* Gets the value of a variable
8039
* @return the value or null
8140
*/
8241
public Value get(char c) {
83-
int hash = hashCode(c) & 0x7FFFFFFF;
84-
int index = hash % table.length;
85-
86-
for (Entry e = table[index]; e != null; e = e.next) {
87-
if ((e.hash == hash) && e.match(c)) {
88-
return (Value)e.get();
89-
}
90-
}
91-
return null;
42+
return (Value) table.get(c);
9243
}
9344

9445
/**
9546
* Sets a new value for the given variable
9647
* @return the old value or null
9748
*/
9849
public Value put(char c, Value value) {
99-
removeClearedEntries();
100-
101-
int hash = hashCode(c) & 0x7FFFFFFF;
102-
int index = hash % table.length;
103-
104-
Entry e = table[index];
105-
if (e != null) {
106-
if ((e.hash == hash) && e.match(c)) {
107-
Object old = e.get();
108-
table[index] = new Entry(hash, c, value, e.next);
109-
return (Value)old;
110-
}
111-
Entry o = e;
112-
e = e.next;
113-
while (e != null) {
114-
if ((e.hash == hash) && e.match(c)) {
115-
Object old = e.get();
116-
e = new Entry(hash, c, value, e.next);
117-
o.next = e;
118-
return (Value)old;
119-
}
120-
121-
o = e;
122-
e = e.next;
123-
}
124-
}
125-
126-
// The key is not in the hash table
127-
int len = table.length;
128-
if (count++ >= (len - (len >> 2))) {
129-
// more than 75% loaded: grow
130-
rehash();
131-
index = hash % table.length;
132-
}
133-
134-
table[index] = new Entry(hash, c, value, table[index]);
135-
return null;
50+
table.put(c, value);
51+
return value;
13652
}
13753

13854
/**
13955
* Clears the table.
14056
*/
14157
public void clear() {
142-
table = new Entry[INITIAL_CAPACITY];
143-
count = 0;
144-
referenceQueue = new ReferenceQueue();
145-
}
146-
147-
/**
148-
* Rehash the table
149-
*/
150-
protected void rehash () {
151-
Entry[] oldTable = table;
152-
153-
table = new Entry[oldTable.length * 2 + 1];
154-
155-
for (int i = oldTable.length-1; i >= 0; i--) {
156-
for (Entry old = oldTable[i]; old != null;) {
157-
Entry e = old;
158-
old = old.next;
159-
160-
int index = e.hash % table.length;
161-
e.next = table[index];
162-
table[index] = e;
163-
}
164-
}
165-
}
166-
167-
/**
168-
* Computes a hash code corresponding to the given objects.
169-
*/
170-
protected int hashCode(char c) {
171-
return c;
172-
}
173-
174-
/**
175-
* Removes the cleared entries.
176-
*/
177-
protected void removeClearedEntries() {
178-
Entry e;
179-
while ((e = (Entry)referenceQueue.poll()) != null) {
180-
int index = e.hash % table.length;
181-
Entry t = table[index];
182-
if (t == e) {
183-
table[index] = e.next;
184-
} else {
185-
loop: for (;t!=null;) {
186-
Entry c = t.next;
187-
if (c == e) {
188-
t.next = e.next;
189-
break loop;
190-
}
191-
t = c;
192-
}
193-
}
194-
count--;
195-
}
58+
table.clear();
19659
}
19760

19861
/**
@@ -234,42 +97,4 @@ public Rectangle2D getOutlineBounds2D() {
23497
return outlineBounds;
23598
}
23699
}
237-
238-
/**
239-
* To manage collisions
240-
*/
241-
protected class Entry extends SoftReference {
242-
243-
/**
244-
* The hash code
245-
*/
246-
public int hash;
247-
248-
/**
249-
* The character
250-
*/
251-
public char c;
252-
253-
/**
254-
* The next entry
255-
*/
256-
public Entry next;
257-
258-
/**
259-
* Creates a new entry
260-
*/
261-
public Entry(int hash, char c, Value value, Entry next) {
262-
super(value, referenceQueue);
263-
this.hash = hash;
264-
this.c = c;
265-
this.next = next;
266-
}
267-
268-
/**
269-
* Whether this entry match the given keys.
270-
*/
271-
public boolean match(char o2) {
272-
return (c == o2);
273-
}
274-
}
275100
}

0 commit comments

Comments
 (0)