1 /* |
1 /* |
2 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
32 package sun.util.locale; |
32 package sun.util.locale; |
33 |
33 |
34 import java.lang.ref.ReferenceQueue; |
34 import java.lang.ref.ReferenceQueue; |
35 import java.lang.ref.SoftReference; |
35 import java.lang.ref.SoftReference; |
36 import java.util.concurrent.ConcurrentHashMap; |
36 import java.util.concurrent.ConcurrentHashMap; |
|
37 import java.util.concurrent.ConcurrentMap; |
37 |
38 |
38 public abstract class LocaleObjectCache<K, V> { |
39 public abstract class LocaleObjectCache<K, V> { |
39 private ConcurrentHashMap<K, CacheEntry<K, V>> _map; |
40 private ConcurrentMap<K, CacheEntry<K, V>> map; |
40 private ReferenceQueue<V> _queue = new ReferenceQueue<V>(); |
41 private ReferenceQueue<V> queue = new ReferenceQueue<>(); |
41 |
42 |
42 public LocaleObjectCache() { |
43 public LocaleObjectCache() { |
43 this(16, 0.75f, 16); |
44 this(16, 0.75f, 16); |
44 } |
45 } |
45 |
46 |
46 public LocaleObjectCache(int initialCapacity, float loadFactor, int concurrencyLevel) { |
47 public LocaleObjectCache(int initialCapacity, float loadFactor, int concurrencyLevel) { |
47 _map = new ConcurrentHashMap<K, CacheEntry<K, V>>(initialCapacity, loadFactor, concurrencyLevel); |
48 map = new ConcurrentHashMap<>(initialCapacity, loadFactor, concurrencyLevel); |
48 } |
49 } |
49 |
50 |
50 public V get(K key) { |
51 public V get(K key) { |
51 V value = null; |
52 V value = null; |
52 |
53 |
53 cleanStaleEntries(); |
54 cleanStaleEntries(); |
54 CacheEntry<K, V> entry = _map.get(key); |
55 CacheEntry<K, V> entry = map.get(key); |
55 if (entry != null) { |
56 if (entry != null) { |
56 value = entry.get(); |
57 value = entry.get(); |
57 } |
58 } |
58 if (value == null) { |
59 if (value == null) { |
59 key = normalizeKey(key); |
60 key = normalizeKey(key); |
61 if (key == null || newVal == null) { |
62 if (key == null || newVal == null) { |
62 // subclass must return non-null key/value object |
63 // subclass must return non-null key/value object |
63 return null; |
64 return null; |
64 } |
65 } |
65 |
66 |
66 CacheEntry<K, V> newEntry = new CacheEntry<K, V>(key, newVal, _queue); |
67 CacheEntry<K, V> newEntry = new CacheEntry<>(key, newVal, queue); |
67 |
68 |
68 while (value == null) { |
69 while (value == null) { |
69 cleanStaleEntries(); |
70 cleanStaleEntries(); |
70 entry = _map.putIfAbsent(key, newEntry); |
71 entry = map.putIfAbsent(key, newEntry); |
71 if (entry == null) { |
72 if (entry == null) { |
72 value = newVal; |
73 value = newVal; |
73 break; |
74 break; |
74 } else { |
75 } else { |
75 value = entry.get(); |
76 value = entry.get(); |
77 } |
78 } |
78 } |
79 } |
79 return value; |
80 return value; |
80 } |
81 } |
81 |
82 |
|
83 protected V put(K key, V value) { |
|
84 CacheEntry<K, V> entry = new CacheEntry<>(key, value, queue); |
|
85 CacheEntry<K, V> oldEntry = map.put(key, entry); |
|
86 return (oldEntry == null) ? null : oldEntry.get(); |
|
87 } |
|
88 |
82 @SuppressWarnings("unchecked") |
89 @SuppressWarnings("unchecked") |
83 private void cleanStaleEntries() { |
90 private void cleanStaleEntries() { |
84 CacheEntry<K, V> entry; |
91 CacheEntry<K, V> entry; |
85 while ((entry = (CacheEntry<K, V>)_queue.poll()) != null) { |
92 while ((entry = (CacheEntry<K, V>)queue.poll()) != null) { |
86 _map.remove(entry.getKey()); |
93 map.remove(entry.getKey()); |
87 } |
94 } |
88 } |
95 } |
89 |
96 |
90 protected abstract V createObject(K key); |
97 protected abstract V createObject(K key); |
91 |
98 |
92 protected K normalizeKey(K key) { |
99 protected K normalizeKey(K key) { |
93 return key; |
100 return key; |
94 } |
101 } |
95 |
102 |
96 private static class CacheEntry<K, V> extends SoftReference<V> { |
103 private static class CacheEntry<K, V> extends SoftReference<V> { |
97 private K _key; |
104 private K key; |
98 |
105 |
99 CacheEntry(K key, V value, ReferenceQueue<V> queue) { |
106 CacheEntry(K key, V value, ReferenceQueue<V> queue) { |
100 super(value, queue); |
107 super(value, queue); |
101 _key = key; |
108 this.key = key; |
102 } |
109 } |
103 |
110 |
104 K getKey() { |
111 K getKey() { |
105 return _key; |
112 return key; |
106 } |
113 } |
107 } |
114 } |
108 } |
115 } |