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);
         }
      }
   }
}