From 15d762e6464a5db06ab390328c0975b89cfeff52 Mon Sep 17 00:00:00 2001 From: Tobias Pietzsch <tobias.pietzsch@gmail.com> Date: Thu, 9 Feb 2017 15:15:28 -0500 Subject: [PATCH] Moved Entry.loaded flags to Entry.ref.loaded This allows to drop the "V extends VolatileCacheValue" requirement without running into concurrent modification problems. (hopefully...) --- .../cache/revised/WeakRefVolatileCache.java | 81 +++++++++++-------- 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/src/main/java/bdv/cache/revised/WeakRefVolatileCache.java b/src/main/java/bdv/cache/revised/WeakRefVolatileCache.java index 383ed991..ea1647db 100644 --- a/src/main/java/bdv/cache/revised/WeakRefVolatileCache.java +++ b/src/main/java/bdv/cache/revised/WeakRefVolatileCache.java @@ -8,13 +8,12 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import bdv.cache.CacheHints; -import bdv.cache.VolatileCacheValue; import bdv.cache.iotiming.CacheIoTiming; import bdv.cache.iotiming.IoStatistics; import bdv.cache.iotiming.IoTimeBudget; import bdv.cache.util.BlockingFetchQueues; -public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements VolatileCache< K, V > +public class WeakRefVolatileCache< K, V > implements VolatileCache< K, V > { final ConcurrentHashMap< K, Entry > map = new ConcurrentHashMap<>(); @@ -36,10 +35,20 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements { private final Entry entry; - public CacheWeakReference( final V referent, final Entry entry ) + final int loaded; + + public CacheWeakReference( final V referent ) + { + super( referent ); + entry = null; + loaded = NOTLOADED; + } + + public CacheWeakReference( final V referent, final Entry entry, final int loaded ) { super( referent, queue ); this.entry = entry; + this.loaded = loaded; } public void clean() @@ -57,11 +66,9 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements final class Entry { - private WeakReference< V > ref; - final K key; - int loaded; + CacheWeakReference ref; long enqueueFrame; @@ -71,8 +78,7 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements { this.key = key; this.loader = loader; - this.ref = new WeakReference<>( null ); - this.loaded = NOTLOADED; + this.ref = new CacheWeakReference( null ); this.enqueueFrame = -1; } @@ -83,15 +89,13 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements public void setInvalid( final V value ) { - loaded = INVALID; - ref = new CacheWeakReference( value, this ); + ref = new CacheWeakReference( value, this, INVALID ); } // Precondition: caller must hold lock on this. public void setValid( final V value ) { - loaded = VALID; - ref = new CacheWeakReference( value, this ); + ref = new CacheWeakReference( value, this, VALID ); loader = null; enqueueFrame = Long.MAX_VALUE; notifyAll(); @@ -111,8 +115,9 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements if ( entry == null ) return null; - final V v = entry.getValue(); - if ( v != null && v.isValid() ) + final CacheWeakReference ref = entry.ref; + final V v = ref.get(); + if ( v != null && ref.loaded == VALID ) return v; cleanUp( 50 ); @@ -147,8 +152,9 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements */ final Entry entry = map.computeIfAbsent( key, k -> new Entry( k, loader ) ); - V v = entry.getValue(); - if ( v != null && v.isValid() ) + final CacheWeakReference ref = entry.ref; + V v = ref.get(); + if ( v != null && ref.loaded == VALID ) return v; cleanUp( 50 ); @@ -247,7 +253,7 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements if ( v != null ) return v; - if ( entry.loaded != NOTLOADED ) + if ( entry.ref.loaded != NOTLOADED ) { map.remove( entry.key, entry ); return null; @@ -270,14 +276,15 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements { synchronized( entry ) { - V v = entry.getValue(); - if ( v == null && entry.loaded != NOTLOADED ) + final CacheWeakReference ref = entry.ref; + V v = ref.get(); + if ( v == null && ref.loaded != NOTLOADED ) { map.remove( entry.key, entry ); return null; } - if ( entry.loaded == VALID ) // v.isValid() + if ( ref.loaded == VALID ) return v; final V vl = backingCache.getIfPresent( entry.key ); @@ -287,7 +294,7 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements return vl; } - if ( entry.loaded == NOTLOADED ) + if ( ref.loaded == NOTLOADED ) { v = entry.loader.createInvalid(); entry.setInvalid( v ); @@ -302,15 +309,16 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements { synchronized( entry ) { - V v = entry.getValue(); - if ( v == null && entry.loaded != NOTLOADED ) + CacheWeakReference ref = entry.ref; + V v = ref.get(); + if ( v == null && ref.loaded != NOTLOADED ) { // printEntryCollected( "map.remove getBudgeted 1", entry ); map.remove( entry.key, entry ); return null; } - if ( entry.loaded == VALID ) // v.isValid() + if ( ref.loaded == VALID ) return v; enqueue( entry, hints ); @@ -335,10 +343,11 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements budget.use( t, priority ); } - v = entry.getValue(); + ref = entry.ref; + v = ref.get(); if ( v == null ) { - if ( entry.loaded == NOTLOADED ) + if ( ref.loaded == NOTLOADED ) { v = entry.loader.createInvalid(); entry.setInvalid( v ); @@ -360,15 +369,16 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements VolatileLoader< ? extends V > loader; synchronized( entry ) { - final V v = entry.getValue(); - if ( v == null && entry.loaded != NOTLOADED ) + final CacheWeakReference ref = entry.ref; + final V v = ref.get(); + if ( v == null && ref.loaded != NOTLOADED ) { // printEntryCollected( "map.remove getBlocking 1", entry ); map.remove( entry.key, entry ); return null; } - if ( entry.loaded == VALID ) // v.isValid() + if ( ref.loaded == VALID ) // v.isValid() return v; loader = entry.loader; @@ -376,15 +386,16 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements final V vl = backingCache.get( entry.key, loader ); synchronized( entry ) { - final V v = entry.getValue(); - if ( v == null && entry.loaded != NOTLOADED ) + final CacheWeakReference ref = entry.ref; + final V v = ref.get(); + if ( v == null && ref.loaded != NOTLOADED ) { // printEntryCollected( "map.remove getBlocking 2", entry ); map.remove( entry.key, entry ); return null; } - if ( entry.loaded == VALID ) // v.isValid() + if ( ref.loaded == VALID ) // v.isValid() return v; // entry.loaded == INVALID @@ -416,11 +427,11 @@ public class WeakRefVolatileCache< K, V extends VolatileCacheValue > implements */ private synchronized void printEntryCollected( final String title, final Entry entry ) { - final String state = entry.loaded == 0 + final String state = entry.ref.loaded == 0 ? "NOTLOADED" - : ( entry.loaded == 1 + : ( entry.ref.loaded == 1 ? "INVALID" - : ( entry.loaded == 2 + : ( entry.ref.loaded == 2 ? "VALID" : "UNDEFINED" ) ); System.out.println( title + " entry.loaded = " + state ); -- GitLab