Skip to content
Snippets Groups Projects
Commit e246512e authored by Tobias Pietzsch's avatar Tobias Pietzsch
Browse files

split finalize-queue into separate class. One queue is shared by many WeakSoftCaches

parent 59553677
No related branches found
No related tags found
No related merge requests found
package bdv.cache;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.Map;
public class WeakSoftCacheFinalizeQueue
{
public static final int MAX_PER_FRAME_FINALIZE_ENTRIES = 500;
private final ReferenceQueue< Object > finalizeQueue = new ReferenceQueue<>();
/**
* Remove references from the cache that have been garbage-collected.
* To avoid long run-times, per call to {@code cleanUp()}, at most
* {@link #MAX_PER_FRAME_FINALIZE_ENTRIES} are processed.
*/
public void cleanUp()
{
for ( int i = 0; i < MAX_PER_FRAME_FINALIZE_ENTRIES; ++i )
{
final Reference< ? > poll = finalizeQueue.poll();
if ( poll == null )
break;
final GetKey< ?, ? > x = ( GetKey< ?, ? > ) poll;
final Object key = x.getKey();
final Map< ?, ? extends Reference< ? > > cache = x.getCache();
final Reference< ? > ref = cache.get( key );
if ( ref == poll )
cache.remove( key );
}
}
public < K, V > Reference< V > createSoftReference( final K key, final V referent, final Map< K, Reference< V > > cache )
{
return new CacheSoftReference< >( key, referent, cache, finalizeQueue );
}
public < K, V > Reference< V > createWeakReference( final K key, final V referent, final Map< K, Reference< V > > cache )
{
return new CacheWeakReference<>( key, referent, cache, finalizeQueue );
}
private static interface GetKey< K, V >
{
public K getKey();
public Map< K, Reference< V > > getCache();
}
private static class CacheSoftReference< K, V > extends SoftReference< V > implements GetKey< K, V >
{
private final K key;
private final Map< K, Reference< V > > cache;
public CacheSoftReference( final K key, final V referent, final Map< K, Reference< V > > cache, final ReferenceQueue< ? super V > q )
{
super( referent, q );
this.key = key;
this.cache = cache;
}
@Override
public K getKey()
{
return key;
}
@Override
public Map< K, Reference< V > > getCache()
{
return cache;
}
}
private static class CacheWeakReference< K, V > extends WeakReference< V > implements GetKey< K, V >
{
private final K key;
private final Map< K, Reference< V > > cache;
public CacheWeakReference( final K key, final V referent, final Map< K, Reference< V > > cache, final ReferenceQueue< ? super V > q )
{
super( referent, q );
this.key = key;
this.cache = cache;
}
@Override
public K getKey()
{
return key;
}
@Override
public Map< K, Reference< V > > getCache()
{
return cache;
}
}
}
......@@ -30,7 +30,6 @@
package bdv.cache;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.concurrent.ConcurrentHashMap;
......@@ -48,101 +47,57 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class WeakSoftCacheImp< K, V > implements WeakSoftCache< K, V >
{
public static final int MAX_PER_FRAME_FINALIZE_ENTRIES = 500;
private static WeakSoftCacheFinalizeQueue sharedQueue = new WeakSoftCacheFinalizeQueue();
private final ConcurrentHashMap< K, Reference< V > > softReferenceCache = new ConcurrentHashMap<>();
WeakSoftCacheImp()
{
this( sharedQueue );
}
private final ReferenceQueue< V > finalizeQueue = new ReferenceQueue<>();
private final ConcurrentHashMap< K, Reference< V > > map = new ConcurrentHashMap<>();
WeakSoftCacheImp()
{}
private final WeakSoftCacheFinalizeQueue queue;
public WeakSoftCacheImp( final WeakSoftCacheFinalizeQueue finalizeQueue )
{
this.queue = finalizeQueue;
}
@Override
public void putWeak( final K key, final V value )
{
softReferenceCache.put( key, new MyWeakReference<>( key, value, finalizeQueue ) );
map.put( key, queue.createWeakReference( key, value, map ) );
}
@Override
public void putSoft( final K key, final V value )
{
softReferenceCache.put( key, new MySoftReference<>( key, value, finalizeQueue ) );
map.put( key, queue.createSoftReference( key, value, map ) );
}
@Override
public V get( final Object key )
{
final Reference< V > ref = softReferenceCache.get( key );
final Reference< V > ref = map.get( key );
return ref == null ? null : ref.get();
}
@Override
public void invalidateAll()
{
for ( final Reference< ? > ref : softReferenceCache.values() )
for ( final Reference< ? > ref : map.values() )
ref.clear();
softReferenceCache.clear();
map.clear();
}
/**
* Remove references from the cache that have been garbage-collected.
* To avoid long run-times, per call to {@code cleanUp()}, at most
* Remove references from the cache that have been garbage-collected. To
* avoid long run-times, per call to {@code cleanUp()}, at most
* {@link #MAX_PER_FRAME_FINALIZE_ENTRIES} are processed.
*/
@Override
public void cleanUp()
{
synchronized ( softReferenceCache )
{
for ( int i = 0; i < MAX_PER_FRAME_FINALIZE_ENTRIES; ++i )
{
final Reference< ? > poll = finalizeQueue.poll();
if ( poll == null )
break;
final Object key = ( ( GetKey< ? > ) poll ).getKey();
final Reference< ? > ref = softReferenceCache.get( key );
if ( ref == poll )
softReferenceCache.remove( key );
}
}
}
private static interface GetKey< K >
{
public K getKey();
}
private static class MySoftReference< K, V > extends SoftReference< V > implements GetKey< K >
{
private final K key;
public MySoftReference( final K key, final V referent, final ReferenceQueue< ? super V > q )
{
super( referent, q );
this.key = key;
}
@Override
public K getKey()
{
return key;
}
}
private static class MyWeakReference< K, V > extends WeakReference< V > implements GetKey< K >
{
private final K key;
public MyWeakReference( final K key, final V referent, final ReferenceQueue< ? super V > q )
{
super( referent, q );
this.key = key;
}
@Override
public K getKey()
{
return key;
}
queue.cleanUp();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment