only iterates over elements when at least one element can be evicted
This commit is contained in:
@@ -98,8 +98,8 @@ public class HotEntryCache<K, V> {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void touch(final Clock clock) {
|
||||
lastAccessed = Instant.now(clock);
|
||||
public void touch(final Instant instant) {
|
||||
lastAccessed = instant;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +114,8 @@ public class HotEntryCache<K, V> {
|
||||
|
||||
private Clock clock;
|
||||
|
||||
private Instant nextEviction = Instant.MAX;
|
||||
|
||||
HotEntryCache(final Duration timeToLive, final Clock clock, final long delayForEvictionThread,
|
||||
final TimeUnit timeUnit) {
|
||||
this.timeToLive = timeToLive;
|
||||
@@ -131,12 +133,13 @@ public class HotEntryCache<K, V> {
|
||||
|
||||
public V get(final K key) {
|
||||
final Entry<V> entry = cache.computeIfPresent(key, (k, e) -> {
|
||||
if (isExpired(e)) {
|
||||
final Instant now = Instant.now(clock);
|
||||
if (isExpired(e, now)) {
|
||||
handleEvent(EventType.EVICTED, k, e.getValue());
|
||||
return null;
|
||||
}
|
||||
|
||||
e.touch(clock);
|
||||
touch(e);
|
||||
return e;
|
||||
});
|
||||
return entry != null ? entry.getValue() : null;
|
||||
@@ -147,7 +150,9 @@ public class HotEntryCache<K, V> {
|
||||
final AtomicReference<Entry<V>> oldValue = new AtomicReference<>();
|
||||
cache.compute(key, (k, v) -> {
|
||||
oldValue.set(v);
|
||||
return new Entry<>(value, clock);
|
||||
final Entry<V> newEntry = new Entry<>(value, clock);
|
||||
touch(newEntry);
|
||||
return newEntry;
|
||||
});
|
||||
return oldValue.get() != null ? oldValue.get().getValue() : null;
|
||||
}
|
||||
@@ -172,9 +177,8 @@ public class HotEntryCache<K, V> {
|
||||
return new Entry<>(value, clock);
|
||||
});
|
||||
|
||||
if (entry != null) {
|
||||
entry.touch(clock);
|
||||
}
|
||||
touch(entry);
|
||||
|
||||
return entry != null ? entry.getValue() : null;
|
||||
}
|
||||
|
||||
@@ -197,16 +201,18 @@ public class HotEntryCache<K, V> {
|
||||
|
||||
public void forEach(final Consumer<V> consumer) {
|
||||
cache.forEachValue(Long.MAX_VALUE, entry -> {
|
||||
entry.touch(clock);
|
||||
touch(entry);
|
||||
consumer.accept(entry.getValue());
|
||||
});
|
||||
}
|
||||
|
||||
private void evict() {
|
||||
for (final K key : cache.keySet()) {
|
||||
final Instant now = Instant.now(clock);
|
||||
if (nextEviction.isBefore(now)) {
|
||||
|
||||
for (final K key : cache.keySet()) {
|
||||
cache.computeIfPresent(key, (k, e) -> {
|
||||
if (isExpired(e)) {
|
||||
if (isExpired(e, now)) {
|
||||
handleEvent(EventType.EVICTED, k, e.getValue());
|
||||
return null;
|
||||
}
|
||||
@@ -214,9 +220,18 @@ public class HotEntryCache<K, V> {
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isExpired(final Entry<V> entry) {
|
||||
return entry.getLastAccessed().plus(timeToLive).isBefore(Instant.now(clock));
|
||||
private void touch(final Entry<V> entry) {
|
||||
if (entry != null) {
|
||||
final Instant now = Instant.now(clock);
|
||||
entry.touch(now);
|
||||
nextEviction = now.plus(timeToLive);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isExpired(final Entry<V> entry, final Instant now) {
|
||||
return entry.getLastAccessed().plus(timeToLive).isBefore(now);
|
||||
}
|
||||
|
||||
private void handleEvent(final EventType eventType, final K key, final V value) {
|
||||
@@ -227,5 +242,4 @@ public class HotEntryCache<K, V> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user