Project

Profile

Help

Revision d291f2ec

Added by Michael Kay over 9 years ago

Fix bug #1481 - thread local Converter cache problem

View differences:

latest9.4/hej/net/sf/saxon/expr/sort/LRUCache.java
1 1
package net.sf.saxon.expr.sort;
2 2

  
3
import java.util.Collections;
3 4
import java.util.LinkedHashMap;
4 5
import java.util.Map;
5 6

  
......
10 11
 */
11 12
public class LRUCache<K,V> {
12 13

  
13
    private LinkedHashMap<K,V> map;
14
    private Map<K,V> map;
14 15

  
15 16
    /**
16 17
     * Creates a new LRU cache.
......
18 19
     * @param cacheSize the maximum number of entries that will be kept in this cache.
19 20
     */
20 21
    public LRUCache(final int cacheSize) {
22
        this(cacheSize, false);
23
    }
24

  
25
    /**
26
     * Creates a new LRU cache with the option of synchronization.
27
     *
28
     * @param cacheSize the maximum number of entries that will be kept in this cache.
29
     */
30
    public LRUCache(final int cacheSize, boolean concurrent) {
21 31
        map = new LinkedHashMap<K,V>(cacheSize, 0.75f, true) {
22 32
            protected boolean removeEldestEntry(Map.Entry eldest) {
23 33
                return cacheSize < super.size();
24 34
            }
25 35
        };
36
        if (concurrent) {
37
            map = Collections.synchronizedMap(map);
38
        }
26 39
    }
27 40

  
28 41
    /**
latest9.4/hej/net/sf/saxon/lib/ConversionRules.java
33 33
    private boolean allowYearZero;
34 34

  
35 35
    // These two tables need to be thread-local or synchronised to make the caching thread-safe
36
    private ThreadLocal<LRUCache<Integer, Converter>> converterCache =
37
            new ThreadLocal<LRUCache<Integer, Converter>>();
38
    private ThreadLocal<LRUCache<Integer, StringConverter>> stringConverterCache =
39
            new ThreadLocal<LRUCache<Integer, StringConverter>>();
36
    private LRUCache<Integer, Converter> converterCache =
37
            new LRUCache<Integer, Converter>(100, true);
38
    private LRUCache<Integer, StringConverter> stringConverterCache =
39
            new LRUCache<Integer, StringConverter>(100, true);
40 40

  
41 41

  
42 42
    public ConversionRules() {
......
179 179
        // For a lookup key, use the primitive type of the source type (always 10 bits) and the
180 180
        // fingerprint of the target type (20 bits)
181 181
        int key = (source.getPrimitiveType() << 20) | target.getFingerprint();
182
        LRUCache<Integer, Converter> converters = converterCache.get();
183
        if (converters == null) {
184
            converters = new LRUCache<Integer, Converter>(50);
185
            converterCache.set(converters);
186
        }
187
        Converter converter = converters.get(key);
182
        Converter converter = converterCache.get(key);
188 183
        if (converter == null) {
189 184
            converter = Converter.getConverter(source, target, this);
190 185
            if (converter != null) {
191
                converters.put(key, converter);
186
                converterCache.put(key, converter);
192 187
            } else {
193 188
                return null;
194 189
            }
......
205 200

  
206 201
    public StringConverter getStringConverter(AtomicType target) {
207 202
        int key = target.getFingerprint();
208
        LRUCache<Integer, StringConverter> stringConverters = stringConverterCache.get();
209
        if (stringConverters == null) {
210
            stringConverters = new LRUCache<Integer, StringConverter>(50);
211
            stringConverterCache.set(stringConverters);
212
        }
213
        StringConverter converter = stringConverters.get(key);
203
        StringConverter converter = stringConverterCache.get(key);
214 204
        if (converter == null) {
215 205
            converter = StringConverter.getStringConverter(target, this);
216
            stringConverters.put(key, converter);
206
            stringConverterCache.put(key, converter);
217 207
        }
218 208
        return converter;
219 209
    }

Also available in: Unified diff