@@ -20,12 +20,12 @@ 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 .concurrent .ConcurrentHashMap ;
2525
2626/**
27- * This class represents a doubly indexed hash table, which holds
28- * soft references to the contained glyph geometry informations .
27+ * This class holds
28+ * soft references to the contained glyph geometry information using a {@link java.util.concurrent.ConcurrentHashMap} .
2929 *
3030 * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
3131 * @author <a href="mailto:tkormann@ilog.fr">Thierry Kormann</a>
@@ -38,161 +38,58 @@ public class AWTGlyphGeometryCache {
3838 */
3939 protected static final int INITIAL_CAPACITY = 71 ;
4040
41- /**
42- * The underlying array
43- */
44- protected Entry [] table ;
45-
46- /**
47- * The number of entries
48- */
49- protected int count ;
41+ private static <T > T getIfSet (SoftReference <T > ref ) {
42+ return ref == null ? null : ref .get ();
43+ }
5044
5145 /**
52- * The reference queue.
46+ * The underlying map
5347 */
54- protected ReferenceQueue referenceQueue = new ReferenceQueue () ;
48+ ConcurrentHashMap < Character , SoftReference < Value >> cache ;
5549
5650 /**
5751 * Creates a new AWTGlyphGeometryCache.
5852 */
5953 public AWTGlyphGeometryCache () {
60- table = new Entry [ INITIAL_CAPACITY ] ;
54+ this ( INITIAL_CAPACITY ) ;
6155 }
6256
6357 /**
6458 * Creates a new AWTGlyphGeometryCache.
6559 * @param c The inital capacity.
6660 */
6761 public AWTGlyphGeometryCache (int c ) {
68- table = new Entry [ c ] ;
62+ cache = new ConcurrentHashMap <>( c ) ;
6963 }
7064
7165 /**
7266 * Returns the size of this table.
7367 */
7468 public int size () {
75- return count ;
69+ return cache . size () ;
7670 }
7771
7872 /**
7973 * Gets the value of a variable
8074 * @return the value or null
8175 */
8276 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 ;
77+ return getIfSet (cache .get (c ));
9278 }
9379
9480 /**
9581 * Sets a new value for the given variable
9682 * @return the old value or null
9783 */
9884 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 ;
85+ return getIfSet (cache .put (c , new SoftReference <>(value )));
13686 }
13787
13888 /**
13989 * Clears the table.
14090 */
14191 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- }
92+ cache .clear ();
19693 }
19794
19895 /**
@@ -234,42 +131,4 @@ public Rectangle2D getOutlineBounds2D() {
234131 return outlineBounds ;
235132 }
236133 }
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- }
275134}
0 commit comments