/*
* This code is distributed under The GNU Lesser General Public License (LGPLv3)
* Please visit GNU site for LGPLv3 http://www.gnu.org/copyleft/lesser.html
*
* Copyright Denis Pavlov 2009
* Web: http://www.genericdtoassembler.org
* SVN: https://svn.code.sf.net/p/geda-genericdto/code/trunk/
* SVN (mirror): http://geda-genericdto.googlecode.com/svn/trunk/
*/
package com.inspiresoftware.lib.dto.geda.assembler.extension.impl;
import com.inspiresoftware.lib.dto.geda.assembler.extension.Cache;
import com.inspiresoftware.lib.dto.geda.assembler.extension.DisposableContainer;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
/**
* GC friendly implementation of cache using SoftReferences.
*
* @author DPavlov
* @since 1.1.0
*
* @param <V> value
*
*/
public class SoftReferenceCache<V> implements Cache<V> {
private final IntHashTable<SoftReference<V>> cache = new IntHashTable<SoftReference<V>>();
private final ReferenceQueue<V> cacheQueue = new ReferenceQueue<V>();
/**
* Simple soft references cache that allows efficient access via int hash key.
* Hash should be well defined as bad hashes will degrade performance.
*/
public SoftReferenceCache() {
}
/** {@inheritDoc} */
public V get(final int key) {
SoftReference<V> val = cache.get(key);
if (val != null) {
final V obj = val.get();
if (obj == null) {
synchronized (this) {
cache.remove(key);
}
return null;
}
return obj;
}
return null;
}
/** {@inheritDoc} */
public void put(final int key, final V value) {
synchronized (this) {
final SoftReference<V> ref = new SoftReference<V>(value, cacheQueue);
cache.put(key, ref);
}
}
/** {@inheritDoc} */
public boolean configure(final String configuration, final Object value) {
return false;
}
/** {@inheritDoc} */
public void releaseResources() {
synchronized (this) {
int[] keys = cache.keysArray();
for (int index = 0; index < keys.length; index++) {
int key = keys[index];
if (key != 0) {
final SoftReference<V> ref = cache.remove(key);
final Object obj = ref.get();
if (obj instanceof DisposableContainer) {
((DisposableContainer) obj).releaseResources();
}
ref.clear();
}
}
while (cacheQueue.poll() != null) {
// Nothing for now
}
}
}
}