1 package charactermanaj.graphics.io;
\r
3 import java.awt.image.BufferedImage;
\r
4 import java.lang.ref.Reference;
\r
5 import java.lang.ref.ReferenceQueue;
\r
6 import java.lang.ref.SoftReference;
\r
7 import java.util.HashMap;
\r
8 import java.util.logging.Level;
\r
9 import java.util.logging.Logger;
\r
14 * キャッシュは自動的にガベージコレクタにより回収されます.<br>
\r
15 * ただし、{@link #unlockImages()}が呼び出されるまで、{@link #set(Object, BufferedImage)}されたイメージは
\r
16 * ガベージコレクトの対象にはなりません。
\r
21 public class ImageCache<K> {
\r
23 private static final Logger logger = Logger.getLogger(ImageCache.class.getName());
\r
25 private static final ImageCacheMBeanImpl imageCacheMBean = ImageCacheMBeanImpl.getSingleton();
\r
27 private HashMap<K, BufferedImageWithKeyReference<K>> lockedImages
\r
28 = new HashMap<K, BufferedImageWithKeyReference<K>>();
\r
30 private ReferenceQueue<LoadedImage> queue = new ReferenceQueue<LoadedImage>();
\r
32 private HashMap<K, BufferedImageWithKeyReference<K>> caches
\r
33 = new HashMap<K, BufferedImageWithKeyReference<K>>();
\r
35 public ImageCache() {
\r
36 imageCacheMBean.incrementInstance();
\r
40 protected void finalize() throws Throwable {
\r
42 imageCacheMBean.decrementInstance();
\r
46 public LoadedImage get(K key) {
\r
50 synchronized (caches) {
\r
51 BufferedImageWithKeyReference<K> ref = caches.get(key);
\r
52 LoadedImage img = null;
\r
56 imageCacheMBean.incrementReadCount(img != null);
\r
62 public void set(K key, LoadedImage img) {
\r
66 synchronized (caches) {
\r
67 // 現在キャッシュされているものがあれば、いったん解放する.
\r
68 BufferedImageWithKeyReference<K> ref = caches.get(key);
\r
74 if (logger.isLoggable(Level.FINE)) {
\r
75 logger.log(Level.FINE, "remove cache: " + key);
\r
80 BufferedImageWithKeyReference<K> cacheData = new BufferedImageWithKeyReference<K>(key, img, queue);
\r
81 lockedImages.put(key, cacheData);
\r
82 caches.put(key, cacheData);
\r
84 imageCacheMBean.cacheIn(cacheData.getImageSize());
\r
87 // 解放済みのアイテムエントリを除去する.
\r
92 public void unlockImages() {
\r
93 synchronized (caches) {
\r
94 lockedImages.clear();
\r
100 * すべてのエントリをキャッシュアウトしてクリアする.
\r
102 public void clear() {
\r
103 synchronized (caches) {
\r
104 lockedImages.clear();
\r
105 for (BufferedImageWithKeyReference<K> ref : caches.values()) {
\r
113 public void sweep() {
\r
114 synchronized (caches) {
\r
115 // ガベージコレクト済みアイテムを除去する
\r
116 Reference<?> ref = null;
\r
117 boolean removed = false;
\r
118 while ((ref = queue.poll()) != null) {
\r
119 @SuppressWarnings("unchecked")
\r
120 BufferedImageWithKeyReference<K> r =
\r
121 (BufferedImageWithKeyReference<K>) ref;
\r
122 K key = r.getKey();
\r
124 if (caches.get(key).get() == null) {
\r
125 if (logger.isLoggable(Level.FINE)) {
\r
126 logger.log(Level.FINE, "removed cache: " + key);
\r
129 caches.remove(key);
\r
133 int imageSize = r.getImageSize();
\r
134 imageCacheMBean.cacheOut(imageSize);
\r
137 if (logger.isLoggable(Level.FINE)) {
\r
138 logger.log(Level.FINE,
\r
139 "cache[" + Integer.toHexString(this.hashCode())
\r
140 + "] size:" + caches.size());
\r
148 * キー情報つきSoftReference
\r
153 class BufferedImageWithKeyReference<K> extends SoftReference<LoadedImage> {
\r
155 private final K key;
\r
157 private final int imageSize;
\r
159 public BufferedImageWithKeyReference(K key, LoadedImage img, ReferenceQueue<? super LoadedImage> queue) {
\r
162 this.imageSize = (img == null) ? 0 : img.getImageSize();
\r
165 public K getKey() {
\r
169 public int getImageSize() {
\r