Bucket class

Пакет: com.hypixel.hytale.server.worldgen.util.cache

Файл: com/hypixel/hytale/server/worldgen/util/cache/ConcurrentSizedTimeoutCache.java

Поля (24)

МодификаторыТипИмя
private final int capacity
private final StampedLock lock
private final Object2ObjectOpenHashMap<K, ConcurrentSizedTimeoutCache.CacheEntry<K, V>> map
private final ArrayDeque<ConcurrentSizedTimeoutCache.CacheEntry<K, V>> pool
private final long timeout_ns
private final int trimThreshold
Object var10
Object var11
var11
long var12
ConcurrentSizedTimeoutCache.CacheEntry var14
ConcurrentSizedTimeoutCache.CacheEntry var15
long var2
long var2
Object var23
boolean var4
ObjectIterator var4
long var5
long var5
ConcurrentSizedTimeoutCache.CacheEntry var5
long var7
ObjectIterator var7
ConcurrentSizedTimeoutCache.CacheEntry var8
ConcurrentSizedTimeoutCache.CacheEntry var9

Методы (8)

МодификаторыВозвратСигнатура
public void cleanuppublic void cleanup(@Nullable BiConsumer<K, V> var1)
public void clearpublic void clear(@Nonnull BiConsumer<K, V> var1)
public V computepublic V compute(@Nonnull K var1, @Nonnull Function<K, K> var2, @Nonnull Function<K, V> var3, @Nonnull BiConsumer<K, V> var4)
if if(var9 != null)
if if(var15 != null)
if if(var10 != var11)
if if(var8 == null)
if if(var1 != null)

Исходный код

Показать/скрыть
class="kw">package com.hypixel.hytale.server.worldgen.util.cache;

class="kw">import com.hypixel.hytale.math.util.MathUtil;
class="kw">import com.hypixel.hytale.server.core.HytaleServer;
class="kw">import com.hypixel.hytale.server.worldgen.util.LogUtil;
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 it.unimi.dsi.fastutil.objects.Object2ObjectMap.Entry;
class="kw">import java.lang.invoke.MethodHandles;
class="kw">import java.lang.invoke.VarHandle;
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.Objects;
class="kw">import java.util.concurrent.ScheduledFuture;
class="kw">import java.util.concurrent.TimeUnit;
class="kw">import java.util.concurrent.locks.StampedLock;
class="kw">import java.util.function.BiConsumer;
class="kw">import java.util.function.Function;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;

class="kw">public class ConcurrentSizedTimeoutCache<K, V> class="kw">implements Cache<K, 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 ConcurrentSizedTimeoutCache.Bucket<K, V>[] buckets;
   @Nonnull
   class="kw">private class="kw">final Function<K, K> computeKey;
   @Nonnull
   class="kw">private class="kw">final Function<K, V> computeValue;
   @Nonnull
   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 ConcurrentSizedTimeoutCache(
      int var1, int var2, long var3, @Nonnull TimeUnit var5, @Nonnull Function<K, K> var6, @Nonnull Function<K, V> var7, @Nullable BiConsumer<K, V> var8
   ) {
      long var9 = var5.toNanos(var3);
      int var11 = HashCommon.nextPowerOfTwo(var2);
      int var12 = Math.max(16, HashCommon.nextPowerOfTwo(var1 / var11));
      this.bucketMask = var11 - 1;
      this.buckets = new ConcurrentSizedTimeoutCache.Bucket[var11];

      for (int var13 = 0; var13 < var11; var13++) {
         this.buckets[var13] = new ConcurrentSizedTimeoutCache.Bucket<>(var12, var9);
      }

      this.computeKey = var6;
      this.computeValue = var7;
      this.destroyer = var8 != null ? var8 : ConcurrentSizedTimeoutCache::noopDestroy;
      this.future = HytaleServer.SCHEDULED_EXECUTOR.scheduleWithFixedDelay(new CleanupRunnable(new WeakReference<>(this)), var3, var3, var5);
      this.cleanable = CleanupFutureAction.CLEANER.register(this, new CleanupFutureAction(this.future));
   }

   @Override
   class="kw">public void shutdown() {
      this.cleanable.clean();

      for (ConcurrentSizedTimeoutCache.Bucket var4 : this.buckets) {
         var4.clear(this.destroyer);
      }
   }

   @Override
   class="kw">public void cleanup() {
      for (ConcurrentSizedTimeoutCache.Bucket var4 : this.buckets) {
         var4.cleanup(this.destroyer);
      }
   }

   @Nonnull
   @Override
   class="kw">public V get(K var1) {
      if (this.future.isCancelled()) {
         throw new IllegalStateException("Cache has been shutdown!");
      }

      int var2 = HashCommon.mix(var1.hashCode());
      class="kw">return this.buckets[var2 & this.bucketMask].compute(var1, this.computeKey, this.computeValue, this.destroyer);
   }

   class="kw">private class="kw">static <K, V> void noopDestroy(K var0, V var1) {
   }

   class="kw">private class="kw">static class Bucket<K, V> {
      class="kw">private class="kw">final int capacity;
      class="kw">private class="kw">final int trimThreshold;
      class="kw">private class="kw">final long timeout_ns;
      class="kw">private class="kw">final ArrayDeque<ConcurrentSizedTimeoutCache.CacheEntry<K, V>> pool;
      class="kw">private class="kw">final Object2ObjectOpenHashMap<K, ConcurrentSizedTimeoutCache.CacheEntry<K, V>> map;
      class="kw">private class="kw">final StampedLock lock = new StampedLock();

      class="kw">public Bucket(int var1, long var2) {
         this.capacity = var1;
         this.trimThreshold = MathUtil.fastFloor(var1 * 0.75F);
         this.timeout_ns = var2;
         this.pool = new ArrayDeque<>(var1);
         this.map = new Object2ObjectOpenHashMap(var1, 0.75F);
      }

      @Nonnull
      class="kw">public V compute(@Nonnull K var1, @Nonnull Function<K, K> var2, @Nonnull Function<K, V> var3, @Nonnull BiConsumer<K, V> var4) {
         long var5 = System.nanoTime();
         long var7 = this.lock.readLock();

         try {
            ConcurrentSizedTimeoutCache.CacheEntry var9 = (ConcurrentSizedTimeoutCache.CacheEntry<K, V>)this.map.get(var1);
            if (var9 != null) {
               class="kw">return var9.markAndGet(var5);
            }
         } class="kw">finally {
            this.lock.unlockRead(var7);
         }

         Object var23 = var2.apply(var1);
         Object var10 = var3.apply(var1);
         Object var11 = var10;
         long var12 = this.lock.writeLock();

         try {
            ConcurrentSizedTimeoutCache.CacheEntry var14 = this.pool.isEmpty() ? new ConcurrentSizedTimeoutCache.CacheEntry<>() : this.pool.poll();
            Objects.requireNonNull(var14, "CacheEntry pool returned null entry!");
            var14.key = (K)var23;
            var14.value = var10;
            var14.timestamp = var5;
            ConcurrentSizedTimeoutCache.CacheEntry var15 = (ConcurrentSizedTimeoutCache.CacheEntry<K, V>)this.map.putIfAbsent(var23, var14);
            if (var15 != null) {
               Objects.requireNonNull(var15.value);
               var11 = var15.value;
               var15.timestamp = var5;
               var14.key = null;
               var14.value = null;
               if (this.pool.size() < this.capacity) {
                  this.pool.offer(var14);
               }
            }
         } class="kw">finally {
            this.lock.unlockWrite(var12);
         }

         if (var10 != var11) {
            var4.accept((K)var23, var10);
         }

         class="kw">return (V)var11;
      }

      class="kw">public void cleanup(@Nullable BiConsumer<K, V> var1) {
         long var2 = this.lock.writeLock();

         try {
            boolean var4 = this.map.size() >= this.trimThreshold;
            long var5 = System.nanoTime() - this.timeout_ns;
            ObjectIterator var7 = this.map.object2ObjectEntrySet().fastIterator();

            while (var7.hasNext()) {
               ConcurrentSizedTimeoutCache.CacheEntry var8 = (ConcurrentSizedTimeoutCache.CacheEntry<K, V>)((Entry)var7.next()).getValue();
               if (var8 == null) {
                  LogUtil.getLogger().at(Level.SEVERE).log("Found null entry in cache bucket during cleanup!");
                  var7.remove();
               } else if (var8.timestamp < var5) {
                  var7.remove();
                  if (var1 != null) {
                     var1.accept(var8.key, var8.value);
                  }

                  var8.key = null;
                  var8.value = null;
                  if (this.pool.size() < this.capacity) {
                     this.pool.offer(var8);
                  }
               }
            }

            if (var4 && this.map.size() < this.capacity) {
               this.map.trim(this.capacity);
            }
         } class="kw">finally {
            this.lock.unlockWrite(var2);
         }
      }

      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()) {
               ConcurrentSizedTimeoutCache.CacheEntry var5 = (ConcurrentSizedTimeoutCache.CacheEntry<K, V>)((Entry)var4.next()).getValue();
               var1.accept(var5.key, var5.value);
               var4.remove();
            }
         } class="kw">finally {
            this.lock.unlockWrite(var2);
         }
      }
   }

   class="kw">private class="kw">static class CacheEntry<K, V> {
      class="kw">private class="kw">static class="kw">final VarHandle TIMESTAMP;
      @Nullable
      class="kw">public K key = (K)null;
      @Nullable
      class="kw">public V value = (V)null;
      class="kw">public long timestamp = 0L;

      class="kw">private CacheEntry() {
      }

      @Nonnull
      class="kw">protected V markAndGet(long var1) {
         Objects.requireNonNull(this.value);
         TIMESTAMP.setVolatile((ConcurrentSizedTimeoutCache.CacheEntry)this, (long)var1);
         class="kw">return this.value;
      }

      class="kw">static {
         try {
            TIMESTAMP = MethodHandles.lookup().findVarHandle(ConcurrentSizedTimeoutCache.CacheEntry.class, "timestamp", long.class);
         } catch (ReflectiveOperationException var1) {
            throw new ExceptionInInitializerError(var1);
         }
      }
   }
}