]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/classes/core/src/com/ibm/icu/impl/locale/LocaleObjectCache.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / classes / core / src / com / ibm / icu / impl / locale / LocaleObjectCache.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 2009, International Business Machines Corporation and         *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 package com.ibm.icu.impl.locale;\r
8 \r
9 import java.lang.ref.Reference;\r
10 import java.lang.ref.ReferenceQueue;\r
11 import java.lang.ref.WeakReference;\r
12 import java.util.concurrent.ConcurrentHashMap;\r
13 \r
14 public class LocaleObjectCache<K, V> {\r
15 \r
16     private ConcurrentHashMap<K, WeakValueRef<V>> _map = new ConcurrentHashMap<K, WeakValueRef<V>>();\r
17     private ReferenceQueue<V> _rq = new ReferenceQueue<V>();\r
18 \r
19     public LocaleObjectCache() {\r
20     }\r
21 \r
22     public V get(Object key) {\r
23         expungeStaleEntries();\r
24         WeakValueRef<V> ref = _map.get(key);\r
25         if (ref != null) {\r
26             return ref.get();\r
27         }\r
28         return null;\r
29     }\r
30 \r
31     /*\r
32      * Unlike Map#put, this method returns non-null value actually\r
33      * in the cache, even no values for the key was not available\r
34      * before.\r
35      */\r
36     public V put(K key, V value) {\r
37         expungeStaleEntries();\r
38         WeakValueRef<V> ref = _map.get(key);\r
39         if (ref != null) {\r
40             // Make sure if another thread put the new value\r
41             V valInCache = ref.get();\r
42             if (valInCache != null) {\r
43                 return valInCache;\r
44             }\r
45         }\r
46         // We do not synchronize the internal map here.\r
47         // In the worst case, another thread may put the new\r
48         // value with the same contents, but it should not cause\r
49         // any serious problem.\r
50         _map.put(key, new WeakValueRef<V>(key, value, _rq));\r
51         return value;\r
52     }\r
53 \r
54     private void expungeStaleEntries() {\r
55         Reference<? extends V> val;\r
56         while ((val = _rq.poll()) != null) {\r
57             Object key = ((WeakValueRef<?>)val).getKey();\r
58             _map.remove(key);\r
59         }\r
60     }\r
61 \r
62     private static class WeakValueRef<V> extends WeakReference<V> {\r
63         private Object _key;\r
64 \r
65         public WeakValueRef(Object key, V value, ReferenceQueue<V> rq) {\r
66             super(value, rq);\r
67             _key = key;\r
68         }\r
69 \r
70         public V get() {\r
71             return super.get();\r
72         }\r
73 \r
74         public Object getKey() {\r
75             return _key;\r
76         }\r
77     }\r
78 }\r