diff --git a/batik-gvt/src/main/java/org/apache/batik/gvt/font/AWTGlyphGeometryCache.java b/batik-gvt/src/main/java/org/apache/batik/gvt/font/AWTGlyphGeometryCache.java index 9df052ac34..a7c08ea271 100644 --- a/batik-gvt/src/main/java/org/apache/batik/gvt/font/AWTGlyphGeometryCache.java +++ b/batik-gvt/src/main/java/org/apache/batik/gvt/font/AWTGlyphGeometryCache.java @@ -20,12 +20,12 @@ Licensed to the Apache Software Foundation (ASF) under one or more import java.awt.Shape; import java.awt.geom.Rectangle2D; -import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; +import java.util.concurrent.ConcurrentHashMap; /** - * This class represents a doubly indexed hash table, which holds - * soft references to the contained glyph geometry informations. + * This class holds + * soft references to the contained glyph geometry information using a {@link java.util.concurrent.ConcurrentHashMap}. * * @author Stephane Hillion * @author Thierry Kormann @@ -38,26 +38,20 @@ public class AWTGlyphGeometryCache { */ protected static final int INITIAL_CAPACITY = 71; - /** - * The underlying array - */ - protected Entry[] table; - - /** - * The number of entries - */ - protected int count; + private static T getIfSet(SoftReference ref) { + return ref == null ? null : ref.get(); + } /** - * The reference queue. + * The underlying map */ - protected ReferenceQueue referenceQueue = new ReferenceQueue(); + ConcurrentHashMap> cache; /** * Creates a new AWTGlyphGeometryCache. */ public AWTGlyphGeometryCache() { - table = new Entry[INITIAL_CAPACITY]; + this(INITIAL_CAPACITY); } /** @@ -65,14 +59,14 @@ public AWTGlyphGeometryCache() { * @param c The inital capacity. */ public AWTGlyphGeometryCache(int c) { - table = new Entry[c]; + cache = new ConcurrentHashMap<>(c); } /** * Returns the size of this table. */ public int size() { - return count; + return cache.size(); } /** @@ -80,15 +74,7 @@ public int size() { * @return the value or null */ public Value get(char c) { - int hash = hashCode(c) & 0x7FFFFFFF; - int index = hash % table.length; - - for (Entry e = table[index]; e != null; e = e.next) { - if ((e.hash == hash) && e.match(c)) { - return (Value)e.get(); - } - } - return null; + return getIfSet(cache.get(c)); } /** @@ -96,103 +82,14 @@ public Value get(char c) { * @return the old value or null */ public Value put(char c, Value value) { - removeClearedEntries(); - - int hash = hashCode(c) & 0x7FFFFFFF; - int index = hash % table.length; - - Entry e = table[index]; - if (e != null) { - if ((e.hash == hash) && e.match(c)) { - Object old = e.get(); - table[index] = new Entry(hash, c, value, e.next); - return (Value)old; - } - Entry o = e; - e = e.next; - while (e != null) { - if ((e.hash == hash) && e.match(c)) { - Object old = e.get(); - e = new Entry(hash, c, value, e.next); - o.next = e; - return (Value)old; - } - - o = e; - e = e.next; - } - } - - // The key is not in the hash table - int len = table.length; - if (count++ >= (len - (len >> 2))) { - // more than 75% loaded: grow - rehash(); - index = hash % table.length; - } - - table[index] = new Entry(hash, c, value, table[index]); - return null; + return getIfSet(cache.put(c, new SoftReference<>(value))); } /** * Clears the table. */ public void clear() { - table = new Entry[INITIAL_CAPACITY]; - count = 0; - referenceQueue = new ReferenceQueue(); - } - - /** - * Rehash the table - */ - protected void rehash () { - Entry[] oldTable = table; - - table = new Entry[oldTable.length * 2 + 1]; - - for (int i = oldTable.length-1; i >= 0; i--) { - for (Entry old = oldTable[i]; old != null;) { - Entry e = old; - old = old.next; - - int index = e.hash % table.length; - e.next = table[index]; - table[index] = e; - } - } - } - - /** - * Computes a hash code corresponding to the given objects. - */ - protected int hashCode(char c) { - return c; - } - - /** - * Removes the cleared entries. - */ - protected void removeClearedEntries() { - Entry e; - while ((e = (Entry)referenceQueue.poll()) != null) { - int index = e.hash % table.length; - Entry t = table[index]; - if (t == e) { - table[index] = e.next; - } else { - loop: for (;t!=null;) { - Entry c = t.next; - if (c == e) { - t.next = e.next; - break loop; - } - t = c; - } - } - count--; - } + cache.clear(); } /** @@ -234,42 +131,4 @@ public Rectangle2D getOutlineBounds2D() { return outlineBounds; } } - - /** - * To manage collisions - */ - protected class Entry extends SoftReference { - - /** - * The hash code - */ - public int hash; - - /** - * The character - */ - public char c; - - /** - * The next entry - */ - public Entry next; - - /** - * Creates a new entry - */ - public Entry(int hash, char c, Value value, Entry next) { - super(value, referenceQueue); - this.hash = hash; - this.c = c; - this.next = next; - } - - /** - * Whether this entry match the given keys. - */ - public boolean match(char o2) { - return (c == o2); - } - } }