Spaces:
Build error
Build error
File size: 5,149 Bytes
d46f4a3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
package net.minecraft.util.thread;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Queues;
import com.mojang.jtracy.TracyClient;
import com.mojang.jtracy.Zone;
import com.mojang.logging.LogUtils;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.locks.LockSupport;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
import javax.annotation.CheckReturnValue;
import net.minecraft.ReportedException;
import net.minecraft.SharedConstants;
import net.minecraft.util.profiling.metrics.MetricCategory;
import net.minecraft.util.profiling.metrics.MetricSampler;
import net.minecraft.util.profiling.metrics.MetricsRegistry;
import net.minecraft.util.profiling.metrics.ProfilerMeasured;
import org.slf4j.Logger;
public abstract class BlockableEventLoop<R extends Runnable> implements ProfilerMeasured, TaskScheduler<R>, Executor {
public static final long BLOCK_TIME_NANOS = 100000L;
private final String name;
private static final Logger LOGGER = LogUtils.getLogger();
private final Queue<R> pendingRunnables = Queues.newConcurrentLinkedQueue();
private int blockingCount;
protected BlockableEventLoop(String p_18686_) {
this.name = p_18686_;
MetricsRegistry.INSTANCE.add(this);
}
protected abstract boolean shouldRun(R p_18703_);
public boolean isSameThread() {
return Thread.currentThread() == this.getRunningThread();
}
protected abstract Thread getRunningThread();
protected boolean scheduleExecutables() {
return !this.isSameThread();
}
public int getPendingTasksCount() {
return this.pendingRunnables.size();
}
@Override
public String name() {
return this.name;
}
public <V> CompletableFuture<V> submit(Supplier<V> p_18692_) {
return this.scheduleExecutables() ? CompletableFuture.supplyAsync(p_18692_, this) : CompletableFuture.completedFuture(p_18692_.get());
}
private CompletableFuture<Void> submitAsync(Runnable p_18690_) {
return CompletableFuture.supplyAsync(() -> {
p_18690_.run();
return null;
}, this);
}
@CheckReturnValue
public CompletableFuture<Void> submit(Runnable p_18708_) {
if (this.scheduleExecutables()) {
return this.submitAsync(p_18708_);
} else {
p_18708_.run();
return CompletableFuture.completedFuture(null);
}
}
public void executeBlocking(Runnable p_18710_) {
if (!this.isSameThread()) {
this.submitAsync(p_18710_).join();
} else {
p_18710_.run();
}
}
@Override
public void schedule(R p_18712_) {
this.pendingRunnables.add(p_18712_);
LockSupport.unpark(this.getRunningThread());
}
@Override
public void execute(Runnable p_18706_) {
if (this.scheduleExecutables()) {
this.schedule(this.wrapRunnable(p_18706_));
} else {
p_18706_.run();
}
}
public void executeIfPossible(Runnable p_201937_) {
this.execute(p_201937_);
}
protected void dropAllTasks() {
this.pendingRunnables.clear();
}
protected void runAllTasks() {
while (this.pollTask()) {
}
}
public boolean pollTask() {
R r = this.pendingRunnables.peek();
if (r == null) {
return false;
} else if (this.blockingCount == 0 && !this.shouldRun(r)) {
return false;
} else {
this.doRunTask(this.pendingRunnables.remove());
return true;
}
}
public void managedBlock(BooleanSupplier p_18702_) {
this.blockingCount++;
try {
while (!p_18702_.getAsBoolean()) {
if (!this.pollTask()) {
this.waitForTasks();
}
}
} finally {
this.blockingCount--;
}
}
protected void waitForTasks() {
Thread.yield();
LockSupport.parkNanos("waiting for tasks", 100000L);
}
protected void doRunTask(R p_18700_) {
try (Zone zone = TracyClient.beginZone("Task", SharedConstants.IS_RUNNING_IN_IDE)) {
p_18700_.run();
} catch (Exception exception) {
LOGGER.error(LogUtils.FATAL_MARKER, "Error executing task on {}", this.name(), exception);
if (isNonRecoverable(exception)) {
throw exception;
}
}
}
@Override
public List<MetricSampler> profiledMetrics() {
return ImmutableList.of(MetricSampler.create(this.name + "-pending-tasks", MetricCategory.EVENT_LOOPS, this::getPendingTasksCount));
}
public static boolean isNonRecoverable(Throwable p_366916_) {
return p_366916_ instanceof ReportedException reportedexception
? isNonRecoverable(reportedexception.getCause())
: p_366916_ instanceof OutOfMemoryError || p_366916_ instanceof StackOverflowError;
}
} |