@@ -20,12 +20,13 @@ Licensed to the Apache Software Foundation (ASF) under one or more
2020
2121import java .awt .Shape ;
2222import java .awt .geom .Rectangle2D ;
23- import java .lang .ref .ReferenceQueue ;
2423import java .lang .ref .SoftReference ;
24+ import java .util .Optional ;
25+ import java .util .concurrent .ConcurrentHashMap ;
2526
2627/**
27- * This class represents a doubly indexed hash table, which holds
28- * soft references to the contained glyph geometry informations .
28+ * This class holds
29+ * soft references to the contained glyph geometry information using a {@link java.util.concurrent.ConcurrentHashMap} .
2930 *
3031 * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
3132 * @author <a href="mailto:tkormann@ilog.fr">Thierry Kormann</a>
@@ -39,160 +40,55 @@ public class AWTGlyphGeometryCache {
3940 protected static final int INITIAL_CAPACITY = 71 ;
4041
4142 /**
42- * The underlying array
43+ * The underlying map
4344 */
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 ();
45+ ConcurrentHashMap <Character , SoftReference <Value >> cache ;
5546
5647 /**
5748 * Creates a new AWTGlyphGeometryCache.
5849 */
5950 public AWTGlyphGeometryCache () {
60- table = new Entry [ INITIAL_CAPACITY ] ;
51+ this ( INITIAL_CAPACITY ) ;
6152 }
6253
6354 /**
6455 * Creates a new AWTGlyphGeometryCache.
6556 * @param c The inital capacity.
6657 */
6758 public AWTGlyphGeometryCache (int c ) {
68- table = new Entry [ c ] ;
59+ cache = new ConcurrentHashMap <>( c ) ;
6960 }
7061
7162 /**
7263 * Returns the size of this table.
7364 */
7465 public int size () {
75- return count ;
66+ return cache . size () ;
7667 }
7768
7869 /**
7970 * Gets the value of a variable
8071 * @return the value or null
8172 */
8273 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 ;
74+ return Optional .ofNullable (cache .get (c )).map (SoftReference ::get ).orElse (null );
9275 }
9376
9477 /**
9578 * Sets a new value for the given variable
9679 * @return the old value or null
9780 */
9881 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 ;
82+ Value oldValue = get (c );
83+ cache .put (c , new SoftReference <>(value ));
84+ return oldValue ;
13685 }
13786
13887 /**
13988 * Clears the table.
14089 */
14190 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- }
91+ cache .clear ();
19692 }
19793
19894 /**
@@ -234,42 +130,4 @@ public Rectangle2D getOutlineBounds2D() {
234130 return outlineBounds ;
235131 }
236132 }
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- }
275133}
0 commit comments