Polishing

(cherry picked from commit 8965d9bccf)
This commit is contained in:
Juergen Hoeller
2026-04-21 20:35:25 +02:00
parent cba8f225d9
commit 9f431e2eac
@@ -102,7 +102,7 @@ public final class ConcurrentLruCache<K, V> {
if (this.capacity == 0) {
return this.generator.apply(key);
}
final Node<K, V> node = this.cache.get(key);
Node<K, V> node = this.cache.get(key);
if (node == null) {
V value = this.generator.apply(key);
put(key, value);
@@ -115,9 +115,9 @@ public final class ConcurrentLruCache<K, V> {
private void put(K key, V value) {
Assert.notNull(key, "key must not be null");
Assert.notNull(value, "value must not be null");
final CacheEntry<V> cacheEntry = new CacheEntry<>(value, CacheEntryState.ACTIVE);
final Node<K, V> node = new Node<>(key, cacheEntry);
final Node<K, V> prior = this.cache.putIfAbsent(node.key, node);
CacheEntry<V> cacheEntry = new CacheEntry<>(value, CacheEntryState.ACTIVE);
Node<K, V> node = new Node<>(key, cacheEntry);
Node<K, V> prior = this.cache.putIfAbsent(node.key, node);
if (prior == null) {
processWrite(new AddTask(node));
}
@@ -128,7 +128,7 @@ public final class ConcurrentLruCache<K, V> {
private void processRead(Node<K, V> node) {
boolean drainRequested = this.readOperations.recordRead(node);
final DrainStatus status = this.drainStatus.get();
DrainStatus status = this.drainStatus.get();
if (status.shouldDrainBuffers(drainRequested)) {
drainOperations();
}
@@ -229,7 +229,7 @@ public final class ConcurrentLruCache<K, V> {
*/
@Nullable
public boolean remove(K key) {
final Node<K, V> node = this.cache.remove(key);
Node<K, V> node = this.cache.remove(key);
if (node == null) {
return false;
}
@@ -238,27 +238,29 @@ public final class ConcurrentLruCache<K, V> {
return true;
}
/*
/**
* Transition the node from the {@code active} state to the {@code pending removal} state,
* if the transition is valid.
*/
private void markForRemoval(Node<K, V> node) {
for (; ; ) {
final CacheEntry<V> current = node.get();
while (true) {
CacheEntry<V> current = node.get();
if (!current.isActive()) {
return;
}
final CacheEntry<V> pendingRemoval = new CacheEntry<>(current.value, CacheEntryState.PENDING_REMOVAL);
CacheEntry<V> pendingRemoval = new CacheEntry<>(current.value, CacheEntryState.PENDING_REMOVAL);
if (node.compareAndSet(current, pendingRemoval)) {
return;
}
}
}
/**
* Write operation recorded when a new entry is added to the cache.
*/
private final class AddTask implements Runnable {
final Node<K, V> node;
AddTask(Node<K, V> node) {
@@ -276,7 +278,7 @@ public final class ConcurrentLruCache<K, V> {
private void evictEntries() {
while (currentSize.get() > capacity) {
final Node<K, V> node = evictionQueue.poll();
Node<K, V> node = evictionQueue.poll();
if (node == null) {
return;
}
@@ -284,7 +286,6 @@ public final class ConcurrentLruCache<K, V> {
markAsRemoved(node);
}
}
}
@@ -292,6 +293,7 @@ public final class ConcurrentLruCache<K, V> {
* Write operation recorded when an entry is removed to the cache.
*/
private final class RemovalTask implements Runnable {
final Node<K, V> node;
RemovalTask(Node<K, V> node) {
@@ -311,7 +313,7 @@ public final class ConcurrentLruCache<K, V> {
*/
private enum DrainStatus {
/*
/**
* No drain operation currently running.
*/
IDLE {
@@ -321,7 +323,7 @@ public final class ConcurrentLruCache<K, V> {
}
},
/*
/**
* A drain operation is required due to a pending write modification.
*/
REQUIRED {
@@ -331,7 +333,7 @@ public final class ConcurrentLruCache<K, V> {
}
},
/*
/**
* A drain operation is in progress.
*/
PROCESSING {
@@ -368,12 +370,6 @@ public final class ConcurrentLruCache<K, V> {
private static final int BUFFER_COUNT = detectNumberOfBuffers();
private static int detectNumberOfBuffers() {
int availableProcessors = Runtime.getRuntime().availableProcessors();
int nextPowerOfTwo = 1 << (Integer.SIZE - Integer.numberOfLeadingZeros(availableProcessors - 1));
return Math.min(4, nextPowerOfTwo);
}
private static final int BUFFERS_MASK = BUFFER_COUNT - 1;
private static final int MAX_PENDING_OPERATIONS = 32;
@@ -384,19 +380,13 @@ public final class ConcurrentLruCache<K, V> {
private static final int BUFFER_INDEX_MASK = BUFFER_SIZE - 1;
/*
* Number of operations recorded, for each buffer
*/
// Number of operations recorded, for each buffer
private final AtomicLongArray recordedCount = new AtomicLongArray(BUFFER_COUNT);
/*
* Number of operations read, for each buffer
*/
// Number of operations read, for each buffer
private final long[] readCount = new long[BUFFER_COUNT];
/*
* Number of operations processed, for each buffer
*/
// Number of operations processed, for each buffer
private final AtomicLongArray processedCount = new AtomicLongArray(BUFFER_COUNT);
@SuppressWarnings("rawtypes")
@@ -404,10 +394,11 @@ public final class ConcurrentLruCache<K, V> {
private final EvictionQueue<K, V> evictionQueue;
@SuppressWarnings("rawtypes")
ReadOperations(EvictionQueue<K, V> evictionQueue) {
this.evictionQueue = evictionQueue;
for (int i = 0; i < BUFFER_COUNT; i++) {
this.buffers[i] = new AtomicReferenceArray<>(BUFFER_SIZE);
this.buffers[i] = new AtomicReferenceArray(BUFFER_SIZE);
}
}
@@ -459,6 +450,12 @@ public final class ConcurrentLruCache<K, V> {
}
this.processedCount.lazySet(bufferIndex, writeCount);
}
private static int detectNumberOfBuffers() {
int availableProcessors = Runtime.getRuntime().availableProcessors();
int nextPowerOfTwo = 1 << (Integer.SIZE - Integer.numberOfLeadingZeros(availableProcessors - 1));
return Math.min(4, nextPowerOfTwo);
}
}
@@ -544,10 +541,9 @@ public final class ConcurrentLruCache<K, V> {
if (this.first == null) {
return null;
}
final Node<K, V> f = this.first;
final Node<K, V> next = f.getNext();
Node<K, V> f = this.first;
Node<K, V> next = f.getNext();
f.setNext(null);
this.first = next;
if (next == null) {
this.last = null;
@@ -566,13 +562,12 @@ public final class ConcurrentLruCache<K, V> {
}
private boolean contains(Node<K, V> e) {
return (e.getPrevious() != null) || (e.getNext() != null) || (e == this.first);
return (e.getPrevious() != null || e.getNext() != null || e == this.first);
}
private void linkLast(final Node<K, V> e) {
final Node<K, V> l = this.last;
private void linkLast(Node<K, V> e) {
Node<K, V> l = this.last;
this.last = e;
if (l == null) {
this.first = e;
}
@@ -583,8 +578,8 @@ public final class ConcurrentLruCache<K, V> {
}
private void unlink(Node<K, V> e) {
final Node<K, V> prev = e.getPrevious();
final Node<K, V> next = e.getNext();
Node<K, V> prev = e.getPrevious();
Node<K, V> next = e.getNext();
if (prev == null) {
this.first = next;
}