@ -52,6 +52,7 @@ import java.util.concurrent.locks.ReentrantLock;
@@ -52,6 +52,7 @@ import java.util.concurrent.locks.ReentrantLock;
* { @linkplain SoftReference soft entry references } .
*
* @author Phillip Webb
* @author Juergen Hoeller
* @since 3 . 2
* @param < K > the key type
* @param < V > the value type
@ -94,7 +95,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -94,7 +95,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
/ * *
* Late binding entry set .
* /
private Set < Map . Entry < K , V > > entrySet ;
private volatile Set < Map . Entry < K , V > > entrySet ;
/ * *
@ -163,8 +164,8 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -163,8 +164,8 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
* @param referenceType the reference type used for entries ( soft or weak )
* /
@SuppressWarnings ( "unchecked" )
public ConcurrentReferenceHashMap ( int initialCapacity , float loadFactor , int concurrencyLevel ,
ReferenceType referenceType ) {
public ConcurrentReferenceHashMap (
int initialCapacity , float loadFactor , int concurrencyLevel , ReferenceType referenceType ) {
Assert . isTrue ( initialCapacity > = 0 , "Initial capacity must not be negative" ) ;
Assert . isTrue ( loadFactor > 0f , "Load factor must be positive" ) ;
@ -211,7 +212,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -211,7 +212,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
* @return the resulting hash code
* /
protected int getHash ( Object o ) {
int hash = o = = null ? 0 : o . hashCode ( ) ;
int hash = ( o ! = null ? o . hashCode ( ) : 0 ) ;
hash + = ( hash < < 15 ) ^ 0xffffcd7d ;
hash ^ = ( hash > > > 10 ) ;
hash + = ( hash < < 3 ) ;
@ -240,8 +241,8 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -240,8 +241,8 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
}
private Entry < K , V > getEntryIfAvailable ( Object key ) {
Reference < K , V > reference = getReference ( key , Restructure . WHEN_NECESSARY ) ;
return ( reference ! = null ? reference . get ( ) : null ) ;
Reference < K , V > ref = getReference ( key , Restructure . WHEN_NECESSARY ) ;
return ( ref ! = null ? ref . get ( ) : null ) ;
}
/ * *
@ -269,13 +270,13 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -269,13 +270,13 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
private V put ( final K key , final V value , final boolean overwriteExisting ) {
return doTask ( key , new Task < V > ( TaskOption . RESTRUCTURE_BEFORE , TaskOption . RESIZE ) {
@Override
protected V execute ( Reference < K , V > reference , Entry < K , V > entry , Entries entries ) {
protected V execute ( Reference < K , V > ref , Entry < K , V > entry , Entries entries ) {
if ( entry ! = null ) {
V previous Value = entry . getValue ( ) ;
V old Value = entry . getValue ( ) ;
if ( overwriteExisting ) {
entry . setValue ( value ) ;
}
return previous Value;
return old Value;
}
entries . add ( value ) ;
return null ;
@ -287,9 +288,9 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -287,9 +288,9 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
public V remove ( Object key ) {
return doTask ( key , new Task < V > ( TaskOption . RESTRUCTURE_AFTER , TaskOption . SKIP_IF_EMPTY ) {
@Override
protected V execute ( Reference < K , V > reference , Entry < K , V > entry ) {
protected V execute ( Reference < K , V > ref , Entry < K , V > entry ) {
if ( entry ! = null ) {
reference . release ( ) ;
ref . release ( ) ;
return entry . value ;
}
return null ;
@ -301,9 +302,9 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -301,9 +302,9 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
public boolean remove ( Object key , final Object value ) {
return doTask ( key , new Task < Boolean > ( TaskOption . RESTRUCTURE_AFTER , TaskOption . SKIP_IF_EMPTY ) {
@Override
protected Boolean execute ( Reference < K , V > reference , Entry < K , V > entry ) {
protected Boolean execute ( Reference < K , V > ref , Entry < K , V > entry ) {
if ( entry ! = null & & ObjectUtils . nullSafeEquals ( entry . getValue ( ) , value ) ) {
reference . release ( ) ;
ref . release ( ) ;
return true ;
}
return false ;
@ -315,7 +316,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -315,7 +316,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
public boolean replace ( K key , final V oldValue , final V newValue ) {
return doTask ( key , new Task < Boolean > ( TaskOption . RESTRUCTURE_BEFORE , TaskOption . SKIP_IF_EMPTY ) {
@Override
protected Boolean execute ( Reference < K , V > reference , Entry < K , V > entry ) {
protected Boolean execute ( Reference < K , V > ref , Entry < K , V > entry ) {
if ( entry ! = null & & ObjectUtils . nullSafeEquals ( entry . getValue ( ) , oldValue ) ) {
entry . setValue ( newValue ) ;
return true ;
@ -329,11 +330,11 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -329,11 +330,11 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
public V replace ( K key , final V value ) {
return doTask ( key , new Task < V > ( TaskOption . RESTRUCTURE_BEFORE , TaskOption . SKIP_IF_EMPTY ) {
@Override
protected V execute ( Reference < K , V > reference , Entry < K , V > entry ) {
protected V execute ( Reference < K , V > ref , Entry < K , V > entry ) {
if ( entry ! = null ) {
V previous Value = entry . getValue ( ) ;
V old Value = entry . getValue ( ) ;
entry . setValue ( value ) ;
return previous Value;
return old Value;
}
return null ;
}
@ -370,11 +371,23 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -370,11 +371,23 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
}
@Override
public Set < java . util . Map . Entry < K , V > > entrySet ( ) {
if ( this . entrySet = = null ) {
this . entrySet = new EntrySet ( ) ;
public boolean isEmpty ( ) {
for ( Segment segment : this . segments ) {
if ( segment . getCount ( ) > 0 ) {
return false ;
}
}
return true ;
}
@Override
public Set < Map . Entry < K , V > > entrySet ( ) {
Set < Map . Entry < K , V > > entrySet = this . entrySet ;
if ( entrySet = = null ) {
entrySet = new EntrySet ( ) ;
this . entrySet = entrySet ;
}
return this . entrySet ;
return entrySet ;
}
private < T > T doTask ( Object key , Task < T > task ) {
@ -485,8 +498,8 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -485,8 +498,8 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
try {
final int index = getIndex ( hash , this . references ) ;
final Reference < K , V > head = this . references [ index ] ;
Reference < K , V > reference = findInChain ( head , key , hash ) ;
Entry < K , V > entry = ( reference ! = null ? reference . get ( ) : null ) ;
Reference < K , V > ref = findInChain ( head , key , hash ) ;
Entry < K , V > entry = ( ref ! = null ? ref . get ( ) : null ) ;
Entries entries = new Entries ( ) {
@Override
public void add ( V value ) {
@ -497,7 +510,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -497,7 +510,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
Segment . this . count + + ;
}
} ;
return task . execute ( reference , entry , entries ) ;
return task . execute ( ref , entry , entries ) ;
}
finally {
unlock ( ) ;
@ -531,19 +544,18 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -531,19 +544,18 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
* @param allowResize if resizing is permitted
* /
protected final void restructureIfNecessary ( boolean allowResize ) {
boolean needsResize = ( ( this . count > 0 ) & & ( this . count > = this . resizeThreshold ) ) ;
Reference < K , V > reference = this . referenceManager . pollForPurge ( ) ;
if ( ( reference ! = null ) | | ( needsResize & & allowResize ) ) {
boolean needsResize = ( this . count > 0 & & this . count > = this . resizeThreshold ) ;
Reference < K , V > ref = this . referenceManager . pollForPurge ( ) ;
if ( ref ! = null | | ( needsResize & & allowResize ) ) {
lock ( ) ;
try {
int countAfterRestructure = this . count ;
Set < Reference < K , V > > toPurge = Collections . emptySet ( ) ;
if ( reference ! = null ) {
if ( ref ! = null ) {
toPurge = new HashSet < Reference < K , V > > ( ) ;
while ( reference ! = null ) {
toPurge . add ( reference ) ;
reference = this . referenceManager . pollForPurge ( ) ;
while ( ref ! = null ) {
toPurge . add ( ref ) ;
ref = this . referenceManager . pollForPurge ( ) ;
}
}
countAfterRestructure - = toPurge . size ( ) ;
@ -559,22 +571,22 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -559,22 +571,22 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
}
// Either create a new table or reuse the existing one
Reference < K , V > [ ] restructured = ( resizing ? createReferenceArray ( restructureSize ) : this . references ) ;
Reference < K , V > [ ] restructured =
( resizing ? createReferenceArray ( restructureSize ) : this . references ) ;
// Restructure
for ( int i = 0 ; i < this . references . length ; i + + ) {
reference = this . references [ i ] ;
ref = this . references [ i ] ;
if ( ! resizing ) {
restructured [ i ] = null ;
}
while ( reference ! = null ) {
if ( ! toPurge . contains ( reference ) & & ( reference . get ( ) ! = null ) ) {
int index = getIndex ( reference . getHash ( ) , restructured ) ;
while ( ref ! = null ) {
if ( ! toPurge . contains ( ref ) & & ( ref . get ( ) ! = null ) ) {
int index = getIndex ( ref . getHash ( ) , restructured ) ;
restructured [ index ] = this . referenceManager . createReference (
reference . get ( ) , reference . getHash ( ) ,
restructured [ index ] ) ;
ref . get ( ) , ref . getHash ( ) , restructured [ index ] ) ;
}
reference = reference . getNext ( ) ;
ref = ref . getNext ( ) ;
}
}
@ -590,8 +602,8 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -590,8 +602,8 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
}
}
private Reference < K , V > findInChain ( Reference < K , V > reference , Object key , int hash ) {
Reference < K , V > currRef = reference ;
private Reference < K , V > findInChain ( Reference < K , V > ref , Object key , int hash ) {
Reference < K , V > currRef = ref ;
while ( currRef ! = null ) {
if ( currRef . getHash ( ) = = hash ) {
Entry < K , V > entry = currRef . get ( ) ;
@ -744,24 +756,24 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -744,24 +756,24 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
/ * *
* Execute the task .
* @param reference the found reference or { @code null }
* @param ref the found reference or { @code null }
* @param entry the found entry or { @code null }
* @param entries access to the underlying entries
* @return the result of the task
* @see # execute ( Reference , Entry )
* /
protected T execute ( Reference < K , V > reference , Entry < K , V > entry , Entries entries ) {
return execute ( reference , entry ) ;
protected T execute ( Reference < K , V > ref , Entry < K , V > entry , Entries entries ) {
return execute ( ref , entry ) ;
}
/ * *
* Convenience method that can be used for tasks that do not need access to { @link Entries } .
* @param reference the found reference or { @code null }
* @param ref the found reference or { @code null }
* @param entry the found entry or { @code null }
* @return the result of the task
* @see # execute ( Reference , Entry , Entries )
* /
protected T execute ( Reference < K , V > reference , Entry < K , V > entry ) {
protected T execute ( Reference < K , V > ref , Entry < K , V > entry ) {
return null ;
}
}
@ -801,12 +813,12 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@@ -801,12 +813,12 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@Override
public boolean contains ( Object o ) {
if ( o ! = null & & o instanceof Map . Entry < ? , ? > ) {
Map . Entry < ? , ? > entry = ( java . util . Map . Entry < ? , ? > ) o ;
Reference < K , V > reference = ConcurrentReferenceHashMap . this . getReference ( entry . getKey ( ) , Restructure . NEVER ) ;
Entry < K , V > other = ( reference ! = null ? reference . get ( ) : null ) ;
if ( other ! = null ) {
return ObjectUtils . nullSafeEquals ( entry . getValue ( ) , other . getValue ( ) ) ;
if ( o instanceof Map . Entry < ? , ? > ) {
Map . Entry < ? , ? > entry = ( Map . Entry < ? , ? > ) o ;
Reference < K , V > ref = ConcurrentReferenceHashMap . this . getReference ( entry . getKey ( ) , Restructure . NEVER ) ;
Entry < K , V > otherEntry = ( ref ! = null ? ref . get ( ) : null ) ;
if ( otherEntry ! = null ) {
return ObjectUtils . nullSafeEquals ( oth erE ntry. getValue ( ) , otherEntry . getValue ( ) ) ;
}
}
return false ;