blob: fb2c808c64aa38c1f85c78261ade370b32b7b7c6 [file] [log] [blame]
/*
* *****************************************************************************
* Copyright (C) 2006, International Business Machines Corporation and others.
* All Rights Reserved.
* *****************************************************************************
*/
package com.ibm.icu.impl;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
/**
* LRU hash map using softly-referenced values
*/
public class SoftCache {
private final LRUMap map;
private final ReferenceQueue queue = new ReferenceQueue();
/**
* Construct a SoftCache with default cache size
*/
public SoftCache() {
map = new LRUMap();
}
/**
* Construct a SoftCache with sepcified initial/max size
*
* @param initialSize the initial cache size
* @param maxSize the maximum cache size
*/
public SoftCache(int initialSize, int maxSize) {
map = new LRUMap(initialSize, maxSize);
}
/**
* Put an object to the cache
* @param key key object
* @param value value object
* @return the value previously put, null when not matching key is found.
*/
public synchronized Object put(Object key, Object value) {
if (key == null || value == null) {
throw new IllegalArgumentException("Key and value must not be null");
}
ProcessQueue();
Object obj = map.put(key, new SoftMapEntry(key, value, queue));
return obj;
}
/**
* Get an object from the cache
* @param key key object
* @return the cached value, null when the value is not found.
*/
public synchronized Object get(Object key) {
ProcessQueue();
Object obj = null;
SoftMapEntry entry = (SoftMapEntry)map.get(key);
if (entry != null) {
obj = entry.get();
if (obj == null) {
// It is unlikely to enter into this block, because
// ProcessQueue() should already remove a map entrie
// whose value was deleted by the garbage collactor.
map.remove(key);
}
}
return obj;
}
/**
* Remove a cache entry from the cache
* @param key key object
* @return the value of cache entry which is removed from this cache,
* or null when no entry for the key was no found.
*/
public synchronized Object remove(Object key) {
return map.remove(key);
}
/**
* Clear the cache contents
*/
public synchronized void clear() {
ProcessQueue();
map.clear();
}
/**
* Remove map entries which no longer have value
*/
private void ProcessQueue() {
while (true) {
SoftMapEntry entry = (SoftMapEntry)queue.poll();
if (entry == null) {
break;
}
map.remove(entry.getKey());
}
}
/**
* A class for map entry with soft-referenced value
*/
private static class SoftMapEntry extends SoftReference {
private final Object key;
private SoftMapEntry(Object key, Object value, ReferenceQueue queue) {
super(value, queue);
this.key = key;
}
private Object getKey() {
return key;
}
}
}