Weak cache optimization (#5344)
This commit is contained in:
parent
36b758e600
commit
54e6b1223e
|
@ -18,27 +18,7 @@ final class WeakLockFreeCache<K, V> implements Cache<K, V> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
|
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
|
||||||
V value = get(key);
|
return delegate.computeIfAbsent(key, mappingFunction);
|
||||||
if (value != null) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
// Best we can do, we don't expect high contention with this implementation. Note, this
|
|
||||||
// prevents executing mappingFunction twice but it does not prevent executing mappingFunction
|
|
||||||
// if there is a concurrent put operation as would be the case for ConcurrentHashMap. However,
|
|
||||||
// we would never expect an order guarantee in this case anyways so it still has the same
|
|
||||||
// safety.
|
|
||||||
synchronized (delegate) {
|
|
||||||
value = get(key);
|
|
||||||
if (value != null) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
value = mappingFunction.apply(key);
|
|
||||||
V previous = delegate.putIfAbsent(key, value);
|
|
||||||
if (previous != null) {
|
|
||||||
return previous;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -33,6 +33,7 @@ import java.util.Map;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.function.Function;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -161,6 +162,22 @@ abstract class AbstractWeakConcurrentMap<K, V, L> extends ReferenceQueue<K>
|
||||||
return previous == null ? target.putIfAbsent(new WeakKey<>(key, this), value) : previous;
|
return previous == null ? target.putIfAbsent(new WeakKey<>(key, this), value) : previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
|
||||||
|
if (key == null || mappingFunction == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
V previous;
|
||||||
|
L lookupKey = getLookupKey(key);
|
||||||
|
try {
|
||||||
|
previous = target.get(lookupKey);
|
||||||
|
} finally {
|
||||||
|
resetLookupKey(lookupKey);
|
||||||
|
}
|
||||||
|
return previous == null
|
||||||
|
? target.computeIfAbsent(new WeakKey<>(key, this), ignored -> mappingFunction.apply(key))
|
||||||
|
: previous;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param key The key of the entry.
|
* @param key The key of the entry.
|
||||||
* @param value The value of the entry.
|
* @param value The value of the entry.
|
||||||
|
|
Loading…
Reference in New Issue