ConcurrentSingleFlightCache class
Пакет: com.hypixel.hytale.builtin.hytalegenerator.cache
Файл: com/hypixel/hytale/builtin/hytalegenerator/cache/ConcurrentSingleFlightCache.java
Поля (36)
| Модификаторы | Тип | Имя |
|---|---|---|
final |
int |
BUCKET_MIN_CAPACITY |
|
private static final VarHandle |
TIMESTAMP |
|
|
TIMESTAMP |
|
private final CompletableFuture<V> |
future |
|
private final K |
key |
|
private final StampedLock |
lock |
|
private final Object2ObjectOpenHashMap<K, ConcurrentSingleFlightCache.Entry<K, V>> |
map |
|
|
return |
|
private long |
timestamp |
|
private final int |
trimThreshold |
|
Object |
var10 |
|
|
var10 |
|
long |
var11 |
|
long |
var13 |
|
Throwable |
var2 |
|
ConcurrentSingleFlightCache.Entry |
var2 |
|
|
var2 |
|
long |
var2 |
|
int |
var3 |
|
long |
var3 |
|
|
var3 |
|
long |
var3 |
|
ObjectIterator |
var4 |
|
ObjectIterator |
var5 |
|
ConcurrentSingleFlightCache.Entry |
var5 |
|
int |
var6 |
|
long |
var6 |
|
ConcurrentSingleFlightCache.Entry |
var6 |
|
int |
var7 |
|
long |
var7 |
|
ConcurrentSingleFlightCache.Entry |
var8 |
|
|
var8 |
|
|
var8 |
|
|
var8 |
|
boolean |
var9 |
|
|
var9 |
Методы (23)
| Модификаторы | Возврат | Сигнатура |
|---|---|---|
|
public |
Bucketpublic Bucket(int var1) |
|
public |
Entrypublic Entry(@Nonnull K var1, long var2) |
abstract |
throw new |
ExceptionInInitializerErrorthrow new ExceptionInInitializerError(var1) |
public |
void |
clearvoid clear() |
|
public void |
clearpublic void clear(@Nonnull BiConsumer<K, V> var1) |
|
private static <K, V> void |
destroyprivate static <K, V> void destroy(@Nonnull ConcurrentSingleFlightCache.Entry<K, V> var0, @Nonnull BiConsumer<K, V> var1) |
abstract |
|
destroy destroy(var2, var1) |
abstract |
|
destroy destroy(var5, var1) |
|
|
for for(int var8 = 0; var8 < var6; var8++) |
|
|
for for(ConcurrentSingleFlightCache.Bucket var4 : this.buckets) |
|
public V |
getpublic V get(@Nonnull K var1, @Nonnull C var2, @Nonnull Function<K, K> var3, @Nonnull BiFunction<K, C, V> var4, @Nonnull BiConsumer<K, V> var5) |
|
|
if if(var2 instanceof RuntimeException var5) |
|
|
if if(var8 != null) |
|
|
if if(var8 == null) |
|
|
if if(var8 == null) |
|
|
if if(var9) |
|
|
if if(var7 < var3) |
|
|
if if(var2 == null) |
|
protected void |
markprotected void mark(long var1) |
static |
<K, V> void |
noopDestroy<K, V> void noopDestroy(K var0, V var1) |
|
protected long |
recencyprotected long recency() |
|
private void |
removeprivate void remove(@Nonnull K var1, @Nonnull ConcurrentSingleFlightCache.Entry<K, V> var2) |
|
private void |
trimprivate void trim(@Nonnull BiConsumer<K, V> var1) |
Исходный код
Показать/скрыть
class="kw">package com.hypixel.hytale.builtin.hytalegenerator.cache;
class="kw">import com.hypixel.hytale.math.util.MathUtil;
class="kw">import it.unimi.dsi.fastutil.HashCommon;
class="kw">import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectIterator;
class="kw">import java.lang.invoke.MethodHandles;
class="kw">import java.lang.invoke.VarHandle;
class="kw">import java.util.Objects;
class="kw">import java.util.concurrent.CompletableFuture;
class="kw">import java.util.concurrent.CompletionException;
class="kw">import java.util.concurrent.locks.StampedLock;
class="kw">import java.util.function.BiConsumer;
class="kw">import java.util.function.BiFunction;
class="kw">import java.util.function.Function;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">public class ConcurrentSingleFlightCache<K, C, V> {
class="kw">private class="kw">static class="kw">final int BUCKET_MIN_CAPACITY = 16;
class="kw">private class="kw">static class="kw">final float BUCKET_LOAD_FACTOR = 0.75F;
class="kw">private class="kw">final int bucketMask;
@Nonnull
class="kw">private class="kw">final ConcurrentSingleFlightCache.Bucket<K, C, V>[] buckets;
@Nonnull
class="kw">private class="kw">final Function<K, K> copyKey;
@Nonnull
class="kw">private class="kw">final BiFunction<K, C, V> computeValue;
@Nonnull
class="kw">private class="kw">final BiConsumer<K, V> destroyer;
class="kw">public ConcurrentSingleFlightCache(int var1, int var2, @Nonnull Function<K, K> var3, @Nonnull BiFunction<K, C, V> var4, @Nullable BiConsumer<K, V> var5) {
int var6 = HashCommon.nextPowerOfTwo(var2);
int var7 = Math.max(16, HashCommon.nextPowerOfTwo(var1 / var6));
this.bucketMask = var6 - 1;
this.buckets = new ConcurrentSingleFlightCache.Bucket[var6];
for (int var8 = 0; var8 < var6; var8++) {
this.buckets[var8] = new ConcurrentSingleFlightCache.Bucket<>(var7);
}
this.copyKey = var3;
this.computeValue = var4;
this.destroyer = var5 != null ? var5 : ConcurrentSingleFlightCache::noopDestroy;
}
@Nullable
class="kw">public V get(@Nonnull K var1, @Nonnull C var2) {
int var3 = HashCommon.mix(var1.hashCode());
class="kw">return this.buckets[var3 & this.bucketMask].get(var1, var2, this.copyKey, this.computeValue, this.destroyer);
}
class="kw">public void clear() {
for (ConcurrentSingleFlightCache.Bucket var4 : this.buckets) {
var4.clear(this.destroyer);
}
}
@Nullable
class="kw">private class="kw">static <V> V await(@Nonnull CompletableFuture<V> var0) {
try {
class="kw">return var0.join();
} catch (CompletionException var4) {
Throwable var2 = var4.getCause();
if (var2 class="kw">instanceof RuntimeException var5) {
throw var5;
} else if (var2 class="kw">instanceof Error var3) {
throw var3;
} else {
throw var4;
}
}
}
class="kw">private class="kw">static <K, V> void noopDestroy(K var0, V var1) {
}
class="kw">private class="kw">static class Bucket<K, C, V> {
class="kw">private class="kw">final int trimThreshold;
class="kw">private class="kw">final Object2ObjectOpenHashMap<K, ConcurrentSingleFlightCache.Entry<K, V>> map;
class="kw">private class="kw">final StampedLock lock = new StampedLock();
class="kw">public Bucket(int var1) {
this.trimThreshold = MathUtil.fastFloor(var1 * 0.75F);
this.map = new Object2ObjectOpenHashMap(var1, 0.75F);
}
@Nullable
class="kw">public V get(@Nonnull K var1, @Nonnull C var2, @Nonnull Function<K, K> var3, @Nonnull BiFunction<K, C, V> var4, @Nonnull BiConsumer<K, V> var5) {
long var6 = System.nanoTime();
boolean var9 = false;
Object var10 = null;
long var11 = this.lock.readLock();
ConcurrentSingleFlightCache.Entry var8;
try {
var8 = (ConcurrentSingleFlightCache.Entry<K, V>)this.map.get(var1);
if (var8 != null) {
var8.mark(var6);
}
} class="kw">finally {
this.lock.unlockRead(var11);
}
if (var8 == null) {
long var13 = this.lock.writeLock();
try {
var8 = (ConcurrentSingleFlightCache.Entry<K, V>)this.map.get(var1);
if (var8 == null) {
var10 = var3.apply(var1);
var8 = new ConcurrentSingleFlightCache.Entry<>(var10, var6);
this.map.put(var10, var8);
var9 = true;
this.trim(var5);
} else {
var8.mark(var6);
}
} class="kw">finally {
this.lock.unlockWrite(var13);
}
}
if (var9) {
try {
var8.future.complete(var4.apply(var1, var2));
} catch (Throwable var22) {
this.remove(var10, var8);
var8.future.completeExceptionally(var22);
}
}
class="kw">return ConcurrentSingleFlightCache.await(var8.future);
}
class="kw">private void trim(@Nonnull BiConsumer<K, V> var1) {
while (this.map.size() > this.trimThreshold) {
ConcurrentSingleFlightCache.Entry var2 = null;
long var3 = Long.MAX_VALUE;
ObjectIterator var5 = this.map.object2ObjectEntrySet().fastIterator();
while (var5.hasNext()) {
ConcurrentSingleFlightCache.Entry var6 = (ConcurrentSingleFlightCache.Entry<K, V>)((it.unimi.dsi.fastutil.objects.Object2ObjectMap.Entry)var5.next())
.getValue();
if (var6.future.isDone()) {
long var7 = var6.recency();
if (var7 < var3) {
var3 = var7;
var2 = var6;
}
}
}
if (var2 == null) {
class="kw">return;
}
this.map.remove(var2.key);
destroy(var2, var1);
}
}
class="kw">private void remove(@Nonnull K var1, @Nonnull ConcurrentSingleFlightCache.Entry<K, V> var2) {
long var3 = this.lock.writeLock();
try {
if (this.map.get(var1) == var2) {
this.map.remove(var1);
}
} class="kw">finally {
this.lock.unlockWrite(var3);
}
}
class="kw">public void clear(@Nonnull BiConsumer<K, V> var1) {
long var2 = this.lock.writeLock();
try {
ObjectIterator var4 = this.map.object2ObjectEntrySet().fastIterator();
while (var4.hasNext()) {
ConcurrentSingleFlightCache.Entry var5 = (ConcurrentSingleFlightCache.Entry<K, V>)((it.unimi.dsi.fastutil.objects.Object2ObjectMap.Entry)var4.next())
.getValue();
destroy(var5, var1);
var4.remove();
}
} class="kw">finally {
this.lock.unlockWrite(var2);
}
}
class="kw">private class="kw">static <K, V> void destroy(@Nonnull ConcurrentSingleFlightCache.Entry<K, V> var0, @Nonnull BiConsumer<K, V> var1) {
if (var0.future.isDone() && !var0.future.isCompletedExceptionally()) {
var1.accept(var0.key, var0.future.join());
}
}
}
class="kw">private class="kw">static class Entry<K, V> {
class="kw">private class="kw">static class="kw">final VarHandle TIMESTAMP;
@Nonnull
class="kw">private class="kw">final K key;
@Nonnull
class="kw">private class="kw">final CompletableFuture<V> future = new CompletableFuture<>();
class="kw">private long timestamp;
class="kw">public Entry(@Nonnull K var1, long var2) {
this.key = Objects.requireNonNull(var1);
this.timestamp = var2;
}
class="kw">protected void mark(long var1) {
TIMESTAMP.setVolatile((ConcurrentSingleFlightCache.Entry)this, (long)var1);
}
class="kw">protected long recency() {
class="kw">return (long)TIMESTAMP.getVolatile((ConcurrentSingleFlightCache.Entry)this);
}
class="kw">static {
try {
TIMESTAMP = MethodHandles.lookup().findVarHandle(ConcurrentSingleFlightCache.Entry.class, "timestamp", long.class);
} catch (ReflectiveOperationException var1) {
throw new ExceptionInInitializerError(var1);
}
}
}
}