CacheEntry class
Пакет: com.hypixel.hytale.server.worldgen.util.cache
Файл: com/hypixel/hytale/server/worldgen/util/cache/SizedTimeoutCache.java
Поля (3)
| Модификаторы | Тип | Имя |
|---|---|---|
|
private K |
key |
|
private long |
timestamp |
|
private V |
value |
Исходный код
Показать/скрыть
class="kw">package com.hypixel.hytale.server.worldgen.util.cache;
class="kw">import com.hypixel.hytale.server.core.HytaleServer;
class="kw">import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
class="kw">import java.lang.ref.WeakReference;
class="kw">import java.lang.ref.Cleaner.Cleanable;
class="kw">import java.util.ArrayDeque;
class="kw">import java.util.concurrent.ScheduledFuture;
class="kw">import java.util.concurrent.TimeUnit;
class="kw">import java.util.function.BiConsumer;
class="kw">import java.util.function.Function;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">public class SizedTimeoutCache<K, V> class="kw">implements Cache<K, V> {
class="kw">private class="kw">final ArrayDeque<SizedTimeoutCache.CacheEntry<K, V>> pool = new ArrayDeque<>();
class="kw">private class="kw">final Object2ObjectLinkedOpenHashMap<K, SizedTimeoutCache.CacheEntry<K, V>> map = new Object2ObjectLinkedOpenHashMap();
class="kw">private class="kw">final long timeout;
class="kw">private class="kw">final int maxSize;
@Nullable
class="kw">private class="kw">final Function<K, V> func;
@Nullable
class="kw">private class="kw">final BiConsumer<K, V> destroyer;
@Nonnull
class="kw">private class="kw">final ScheduledFuture<?> future;
@Nonnull
class="kw">private class="kw">final Cleanable cleanable;
class="kw">public SizedTimeoutCache(long var1, @Nonnull TimeUnit var3, int var4, @Nullable Function<K, V> var5, @Nullable BiConsumer<K, V> var6) {
this.timeout = var3.toNanos(var1);
this.maxSize = var4;
this.func = var5;
this.destroyer = var6;
this.future = HytaleServer.SCHEDULED_EXECUTOR.scheduleWithFixedDelay(new CleanupRunnable(new WeakReference<>(this)), var1, var1, var3);
this.cleanable = CleanupFutureAction.CLEANER.register(this, new CleanupFutureAction(this.future));
}
@Override
class="kw">public void cleanup() {
this.reduceLength(this.maxSize);
long var1 = System.nanoTime() - this.timeout;
while (true) {
Object var3;
Object var4;
class="kw">synchronized (this.map) {
label37: {
if (!this.map.isEmpty()) {
var3 = (K)this.map.lastKey();
SizedTimeoutCache.CacheEntry var6 = (SizedTimeoutCache.CacheEntry<K, V>)this.map.get(var3);
if (var6.timestamp <= var1) {
this.map.remove(var3);
var4 = var6.value;
if (this.pool.size() < this.maxSize) {
var6.key = null;
var6.value = null;
var6.timestamp = 0L;
this.pool.addLast(var6);
}
break label37;
}
}
class="kw">return;
}
}
if (this.destroyer != null) {
this.destroyer.accept(var3, var4);
}
}
}
class="kw">private void reduceLength(int var1) {
while (true) {
Object var2;
Object var3;
class="kw">synchronized (this.map) {
if (this.map.size() <= var1) {
class="kw">return;
}
SizedTimeoutCache.CacheEntry var5 = (SizedTimeoutCache.CacheEntry<K, V>)this.map.removeLast();
var2 = var5.key;
var3 = var5.value;
if (this.pool.size() < this.maxSize) {
var5.key = null;
var5.value = null;
var5.timestamp = 0L;
this.pool.addLast(var5);
}
}
if (this.destroyer != null) {
this.destroyer.accept(var2, var3);
}
}
}
@Override
class="kw">public void shutdown() {
this.cleanable.clean();
if (this.destroyer != null) {
this.reduceLength(0);
} else {
class="kw">synchronized (this.map) {
this.map.clear();
}
}
}
@Nullable
@Override
class="kw">public V get(K var1) {
if (this.future.isCancelled()) {
throw new IllegalStateException("Cache has been shutdown!");
}
long var2 = System.nanoTime();
class="kw">synchronized (this.map) {
SizedTimeoutCache.CacheEntry var5 = (SizedTimeoutCache.CacheEntry<K, V>)this.map.getAndMoveToFirst(var1);
if (var5 != null) {
var5.timestamp = var2;
class="kw">return var5.value;
}
}
if (this.func == null) {
class="kw">return null;
}
Object var13 = this.func.apply(var1);
var2 = System.nanoTime();
SizedTimeoutCache.CacheEntry var6;
Object var7;
SizedTimeoutCache.CacheEntry var14;
class="kw">synchronized (this.map) {
var14 = this.pool.isEmpty() ? new SizedTimeoutCache.CacheEntry<>() : this.pool.removeLast();
var14.key = var1;
var14.value = var13;
var14.timestamp = var2;
var6 = (SizedTimeoutCache.CacheEntry<K, V>)this.map.getAndMoveToFirst(var1);
if (var6 != null) {
var6.timestamp = var2;
} else {
var6 = var14;
this.map.put(var1, var6);
}
var7 = var6.value;
}
if (var6 != var14 && this.destroyer != null) {
this.destroyer.accept(var1, var13);
}
class="kw">return var7;
}
class="kw">public void put(K var1, V var2) {
if (this.future.isCancelled()) {
throw new IllegalStateException("Cache has been shutdown!");
}
long var3 = System.nanoTime();
SizedTimeoutCache.CacheEntry var6;
class="kw">synchronized (this.map) {
SizedTimeoutCache.CacheEntry var5 = this.pool.isEmpty() ? new SizedTimeoutCache.CacheEntry<>() : this.pool.removeLast();
var5.key = var1;
var5.value = var2;
var5.timestamp = var3;
var6 = (SizedTimeoutCache.CacheEntry<K, V>)this.map.putAndMoveToFirst(var1, var5);
if (var6 != null) {
var5.key = var6.key;
}
}
if (var6 != null && this.destroyer != null) {
this.destroyer.accept(var1, var6.value);
}
}
@Nullable
class="kw">public V getWithReusedKey(K var1, @Nonnull Function<K, K> var2) {
if (this.future.isCancelled()) {
throw new IllegalStateException("Cache has been shutdown!");
}
long var3 = System.nanoTime();
class="kw">synchronized (this.map) {
SizedTimeoutCache.CacheEntry var6 = (SizedTimeoutCache.CacheEntry<K, V>)this.map.getAndMoveToFirst(var1);
if (var6 != null) {
var6.timestamp = var3;
class="kw">return var6.value;
}
}
if (this.func == null) {
class="kw">return null;
}
Object var15 = var2.apply(var1);
Object var16 = this.func.apply(var15);
var3 = System.nanoTime();
SizedTimeoutCache.CacheEntry var7;
SizedTimeoutCache.CacheEntry var8;
Object var9;
class="kw">synchronized (this.map) {
var7 = this.pool.isEmpty() ? new SizedTimeoutCache.CacheEntry<>() : this.pool.removeLast();
var7.key = var15;
var7.value = var16;
var7.timestamp = var3;
var8 = (SizedTimeoutCache.CacheEntry<K, V>)this.map.getAndMoveToFirst(var15);
if (var8 != null) {
var8.timestamp = var3;
} else {
var8 = var7;
this.map.put(var15, var8);
}
var9 = var8.value;
}
if (var8 != var7 && this.destroyer != null) {
this.destroyer.accept(var15, var16);
}
class="kw">return var9;
}
class="kw">private class="kw">static class CacheEntry<K, V> {
@Nullable
class="kw">private V value;
@Nullable
class="kw">private K key;
class="kw">private long timestamp;
class="kw">private CacheEntry() {
}
}
}