TickingThread class

Пакет: com.hypixel.hytale.server.core.util.thread

Файл: com/hypixel/hytale/server/core/util/thread/TickingThread.java

implements: Runnable

Поля (18)

МодификаторыТипИмя
final int NANOS_IN_ONE_MILLI
return
long var1
var1
var1
Thread var1
Object var10
long var13
long var14
int var2
long var3
var3
var3
StringBuilder var3
long var5
long var7
long var9
Object var9

Методы (22)

МодификаторыВозвратСигнатура
abstract throw new AssertionErrorthrow new AssertionError("Assert not in ticking thread!")
public void clearMetricsvoid clearMetrics()
public void debugAssertInTickingThreadvoid debugAssertInTickingThread()
public HistoricMetric getBufferedTickLengthMetricSetHistoricMetric getBufferedTickLengthMetricSet()
public int getTickStepNanosint getTickStepNanos()
public int getTpsint getTps()
if if(var9 > 0L)
if if(this.possibleFailureCause == null)
if if(this.thread == null)
if if(var1 != null)
if if(var2 > 30000)
if if(var1 > 0 && var1 <= 2048)
public boolean interruptboolean interrupt()
protected boolean isIdleboolean isIdle()
public boolean isInThreadboolean isInThread()
public boolean isStartedboolean isStarted()
abstract abstract void onShutdownvoid onShutdown()
protected void onStartvoid onStart()
public void setTpsvoid setTps(int var1)
public void stopvoid stop()
abstract this this(var1, 30, false)
abstract abstract void tickvoid tick(float var1)

Исходный код

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

class="kw">import com.hypixel.hytale.common.plugin.PluginIdentifier;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.metrics.metric.HistoricMetric;
class="kw">import java.util.concurrent.CompletableFuture;
class="kw">import java.util.concurrent.TimeUnit;
class="kw">import java.util.concurrent.atomic.AtomicBoolean;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;

class="kw">public class="kw">abstract class TickingThread class="kw">implements Runnable {
   class="kw">public class="kw">static class="kw">final int NANOS_IN_ONE_MILLI = 1000000;
   class="kw">public class="kw">static class="kw">final int NANOS_IN_ONE_SECOND = 1000000000;
   class="kw">public class="kw">static class="kw">final int TPS = 30;
   class="kw">public class="kw">static long SLEEP_OFFSET = 3000000L;
   class="kw">private class="kw">final String threadName;
   class="kw">private class="kw">final boolean daemon;
   class="kw">private class="kw">final AtomicBoolean needsShutdown = new AtomicBoolean(true);
   class="kw">private class="kw">final AtomicBoolean inShutdownHook = new AtomicBoolean();
   class="kw">private int tps;
   class="kw">private int tickStepNanos;
   class="kw">private HistoricMetric bufferedTickLengthMetricSet;
   @Nullable
   class="kw">private Thread thread;
   @Nonnull
   class="kw">private CompletableFuture<Void> startedFuture = new CompletableFuture<>();
   @Nullable
   class="kw">private PluginIdentifier possibleFailureCause;
   @Nullable
   class="kw">private Throwable failureException;

   class="kw">public TickingThread(String var1) {
      this(var1, 30, false);
   }

   class="kw">public TickingThread(String var1, int var2, boolean var3) {
      this.threadName = var1;
      this.daemon = var3;
      this.tps = var2;
      this.tickStepNanos = 1000000000 / var2;
      this.bufferedTickLengthMetricSet = HistoricMetric.builder(this.tickStepNanos, TimeUnit.NANOSECONDS)
         .addPeriod(10L, TimeUnit.SECONDS)
         .addPeriod(1L, TimeUnit.MINUTES)
         .addPeriod(5L, TimeUnit.MINUTES)
         .build();
   }

   @Override
   class="kw">public void run() {
      try {
         this.onStart();
         this.startedFuture.complete(null);
         long var1 = System.nanoTime() - this.tickStepNanos;

         while (this.thread != null && !this.thread.isInterrupted()) {
            long var3;
            if (this.isIdle()) {
               long var13 = System.nanoTime();
               var3 = var13 - var1;
               var1 = var13;
            } else {
               long var5;
               while ((var5 = System.nanoTime()) - var1 < this.tickStepNanos) {
                  Thread.onSpinWait();
               }

               var3 = var5 - var1;
               var1 = var5;
            }

            this.tick((float)var3 / 1.0E9F);
            long var14 = System.nanoTime();
            long var7 = var14 - var1;
            this.bufferedTickLengthMetricSet.add(var14, var7);
            long var9 = this.tickStepNanos - var7;
            if (!this.isIdle()) {
               var9 -= SLEEP_OFFSET;
            }

            if (var9 > 0L) {
               Thread.sleep(var9 / 1000000L);
            }
         }
      } catch (InterruptedException var11) {
         Thread.currentThread().interrupt();
      } catch (Throwable var12) {
         this.failureException = var12;
         this.possibleFailureCause = PluginIdentifier.identifyThirdPartyPlugin(var12);
         if (this.possibleFailureCause == null) {
            ((HytaleLogger.Api)HytaleLogger.getLogger().at(Level.SEVERE).withCause(var12)).log("Exception in thread %s:", this.thread);
         } else {
            ((HytaleLogger.Api)HytaleLogger.getLogger().at(Level.SEVERE).withCause(var12))
               .log("Exception in thread %s potentially caused by %s:", this.thread, this.possibleFailureCause);
         }
      }

      if (this.needsShutdown.getAndSet(false)) {
         this.inShutdownHook.set(true);
         Thread.interrupted();
         this.onShutdown();
      }
   }

   class="kw">protected boolean isIdle() {
      class="kw">return false;
   }

   class="kw">protected class="kw">abstract void tick(float var1);

   class="kw">protected void onStart() {
   }

   class="kw">protected class="kw">abstract void onShutdown();

   @Nonnull
   class="kw">public CompletableFuture<Void> start() {
      if (this.thread == null) {
         this.thread = new Thread(this, this.threadName);
         this.thread.setDaemon(this.daemon);
      } else if (this.thread.isAlive()) {
         throw new IllegalStateException("Thread '" + this.thread.getName() + "' is already started!");
      }

      this.thread.start();
      class="kw">return this.startedFuture;
   }

   class="kw">public boolean interrupt() {
      if (this.thread != null && this.thread.isAlive()) {
         this.thread.interrupt();
         class="kw">return true;
      } else {
         class="kw">return false;
      }
   }

   class="kw">public void stop() {
      Thread var1 = this.thread;
      if (var1 != null) {
         try {
            int var2 = 0;

            while (var1.isAlive()) {
               if (!this.inShutdownHook.get()) {
                  var1.interrupt();
               }

               var1.join(this.tickStepNanos / 1000000);
               var2 += this.tickStepNanos / 1000000;
               if (var2 > 30000) {
                  StringBuilder var3 = new StringBuilder();

                  for (StackTraceElement var7 : var1.getStackTrace()) {
                     var3.append("\tat ").append(var7).append('\n');
                  }

                  HytaleLogger.getLogger().at(Level.SEVERE).log("Abandoning TickingThread %s (stuck for >30s):\n%s", var1, var3.toString());
                  Object var9 = null;
                  if (this.needsShutdown.getAndSet(false)) {
                     this.onShutdown();
                  }

                  class="kw">return;
               }
            }

            Object var10 = null;
         } catch (InterruptedException var8) {
            Thread.currentThread().interrupt();
         }
      }
   }

   class="kw">public void setTps(int var1) {
      this.debugAssertInTickingThread();
      if (var1 > 0 && var1 <= 2048) {
         this.tps = var1;
         this.tickStepNanos = 1000000000 / var1;
         this.bufferedTickLengthMetricSet = HistoricMetric.builder(this.tickStepNanos, TimeUnit.NANOSECONDS)
            .addPeriod(10L, TimeUnit.SECONDS)
            .addPeriod(1L, TimeUnit.MINUTES)
            .addPeriod(5L, TimeUnit.MINUTES)
            .build();
      } else {
         throw new IllegalArgumentException("UpdatesPerSecond is out of bounds (<=0 or >2048): " + var1);
      }
   }

   class="kw">public int getTps() {
      class="kw">return this.tps;
   }

   class="kw">public int getTickStepNanos() {
      class="kw">return this.tickStepNanos;
   }

   class="kw">public HistoricMetric getBufferedTickLengthMetricSet() {
      class="kw">return this.bufferedTickLengthMetricSet;
   }

   class="kw">public void clearMetrics() {
      this.bufferedTickLengthMetricSet.clear();
   }

   class="kw">public void debugAssertInTickingThread() {
      if (this.thread != null && Thread.currentThread() != this.thread) {
         throw new AssertionError("Assert not in ticking thread!");
      }
   }

   class="kw">public boolean isInThread() {
      class="kw">return Thread.currentThread() == this.thread;
   }

   class="kw">public boolean isStarted() {
      class="kw">return this.thread != null && this.thread.isAlive() && this.needsShutdown.get();
   }

   @Nullable
   class="kw">public PluginIdentifier getPossibleFailureCause() {
      class="kw">return this.possibleFailureCause;
   }

   @Nullable
   class="kw">public Throwable getFailureException() {
      class="kw">return this.failureException;
   }

   @Deprecated
   class="kw">protected void setThread(Thread var1) {
      this.thread = var1;
   }

   @Nullable
   class="kw">protected Thread getThread() {
      class="kw">return this.thread;
   }
}