mirror of
https://github.com/Dreeam-qwq/Gale.git
synced 2025-12-27 10:39:12 +00:00
Use timeout instead of notifications after chunk worker task
This commit is contained in:
@@ -2163,7 +2163,7 @@ index 0000000000000000000000000000000000000000..e9d778a078bee6b6f1c21078c445b48f
|
||||
+}
|
||||
diff --git a/src/main/java/org/galemc/gale/executor/MinecraftServerBlockableEventLoop.java b/src/main/java/org/galemc/gale/executor/MinecraftServerBlockableEventLoop.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..84aa4f8e3f823cedc8cf958663fa2168f29d1d9c
|
||||
index 0000000000000000000000000000000000000000..2da7a1a787bed2e03039796d56201870548ad0e4
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/galemc/gale/executor/MinecraftServerBlockableEventLoop.java
|
||||
@@ -0,0 +1,187 @@
|
||||
@@ -2338,7 +2338,7 @@ index 0000000000000000000000000000000000000000..84aa4f8e3f823cedc8cf958663fa2168
|
||||
+ //noinspection NonAtomicOperationOnVolatileField
|
||||
+ ++blockingCount;
|
||||
+ try {
|
||||
+ MinecraftServer.serverThread.runTasksUntil(stopCondition, null);
|
||||
+ MinecraftServer.serverThread.runTasksUntil(null, stopCondition, null);
|
||||
+ } finally {
|
||||
+ //noinspection NonAtomicOperationOnVolatileField
|
||||
+ --blockingCount;
|
||||
@@ -2750,7 +2750,7 @@ index 0000000000000000000000000000000000000000..686e16da8372085196d8f92adb881f82
|
||||
+}
|
||||
diff --git a/src/main/java/org/galemc/gale/executor/lock/YieldingLock.java b/src/main/java/org/galemc/gale/executor/lock/YieldingLock.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..799608befb739d051153b5321598ea87b50fd6bd
|
||||
index 0000000000000000000000000000000000000000..4b40afe88f166491f74f99bab96092d04e77fe02
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/galemc/gale/executor/lock/YieldingLock.java
|
||||
@@ -0,0 +1,202 @@
|
||||
@@ -2862,7 +2862,7 @@ index 0000000000000000000000000000000000000000..799608befb739d051153b5321598ea87
|
||||
+ return;
|
||||
+ }
|
||||
+ // Otherwise, we yield to other tasks until the lock can be acquired
|
||||
+ yieldingThread.yieldUntil(null, this);
|
||||
+ yieldingThread.yieldUntil(null, null, this);
|
||||
+ }
|
||||
+ // Increment the YieldingLock count of the current thread
|
||||
+ if (this.canBeHeld) {
|
||||
@@ -4190,7 +4190,7 @@ index 0000000000000000000000000000000000000000..fb4f9c047fc71a9a01aa47871254c6a9
|
||||
+}
|
||||
diff --git a/src/main/java/org/galemc/gale/executor/thread/AbstractYieldingThread.java b/src/main/java/org/galemc/gale/executor/thread/AbstractYieldingThread.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..24a30760982244fb0d3fa1933751a8286c27014c
|
||||
index 0000000000000000000000000000000000000000..fd4082f1d8fe558bbaaf3b17da18b361e34c81ed
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/galemc/gale/executor/thread/AbstractYieldingThread.java
|
||||
@@ -0,0 +1,147 @@
|
||||
@@ -4249,7 +4249,7 @@ index 0000000000000000000000000000000000000000..24a30760982244fb0d3fa1933751a828
|
||||
+
|
||||
+ @ThisThreadOnly
|
||||
+ @PotentiallyYielding("this method is meant to yield")
|
||||
+ void yieldUntil(@Nullable BooleanSupplier stopCondition, @Nullable YieldingLock yieldingLock);
|
||||
+ void yieldUntil(@Nullable Long timeoutTime, @Nullable BooleanSupplier stopCondition, @Nullable YieldingLock yieldingLock);
|
||||
+
|
||||
+ /**
|
||||
+ * Calls {@link #yieldUntil(BooleanSupplier, YieldingLock)}, but creates a {@link YieldingLock}
|
||||
@@ -4261,7 +4261,7 @@ index 0000000000000000000000000000000000000000..24a30760982244fb0d3fa1933751a828
|
||||
+ */
|
||||
+ @ThisThreadOnly
|
||||
+ @PotentiallyYielding("this method is meant to yield")
|
||||
+ default void yieldUntilFuture(@Nullable BooleanSupplier stopCondition, @NotNull CompletableFuture<?> future, @Nullable Consumer<YieldingLock> autoCompletingLockConsumer) {
|
||||
+ default void yieldUntilFuture(@Nullable Long timeoutTime, @Nullable BooleanSupplier stopCondition, @NotNull CompletableFuture<?> future, @Nullable Consumer<YieldingLock> autoCompletingLockConsumer) {
|
||||
+
|
||||
+ /*
|
||||
+ Here, we abuse the Lock interface to create a YieldingLock
|
||||
@@ -4317,12 +4317,12 @@ index 0000000000000000000000000000000000000000..24a30760982244fb0d3fa1933751a828
|
||||
+ future.thenRun(autoCompletingLock::unlock);
|
||||
+
|
||||
+ // Yield while necessary
|
||||
+ this.yieldUntil(null, autoCompletingLock);
|
||||
+ this.yieldUntil(timeoutTime, null, autoCompletingLock);
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ @ThisThreadOnly
|
||||
+ void runTasksUntil(@Nullable BooleanSupplier stopCondition, @Nullable YieldingLock yieldingLock);
|
||||
+ void runTasksUntil(@Nullable Long timeoutTime, @Nullable BooleanSupplier stopCondition, @Nullable YieldingLock yieldingLock);
|
||||
+
|
||||
+ @AnyThreadSafe
|
||||
+ @YieldFree
|
||||
@@ -4343,7 +4343,7 @@ index 0000000000000000000000000000000000000000..24a30760982244fb0d3fa1933751a828
|
||||
+}
|
||||
diff --git a/src/main/java/org/galemc/gale/executor/thread/AssistThread.java b/src/main/java/org/galemc/gale/executor/thread/AssistThread.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a5605765f6be0b75e5df5613e8b393b64f88fc3c
|
||||
index 0000000000000000000000000000000000000000..eab769d7319f26db1f4db9599a3c263c507641bd
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/galemc/gale/executor/thread/AssistThread.java
|
||||
@@ -0,0 +1,78 @@
|
||||
@@ -4392,7 +4392,7 @@ index 0000000000000000000000000000000000000000..a5605765f6be0b75e5df5613e8b393b6
|
||||
+ */
|
||||
+ @ThisThreadOnly
|
||||
+ protected void runForever() {
|
||||
+ this.runTasksUntil(() -> false, null);
|
||||
+ this.runTasksUntil(null, () -> false, null);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
@@ -4427,10 +4427,10 @@ index 0000000000000000000000000000000000000000..a5605765f6be0b75e5df5613e8b393b6
|
||||
+}
|
||||
diff --git a/src/main/java/org/galemc/gale/executor/thread/BaseThread.java b/src/main/java/org/galemc/gale/executor/thread/BaseThread.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..1c7275dd53e29594d25c63d3df54311a300a08fb
|
||||
index 0000000000000000000000000000000000000000..17ae524053949073fcdcbccc53327c42ba1903c6
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/galemc/gale/executor/thread/BaseThread.java
|
||||
@@ -0,0 +1,719 @@
|
||||
@@ -0,0 +1,722 @@
|
||||
+// Gale - base thread pool
|
||||
+
|
||||
+package org.galemc.gale.executor.thread;
|
||||
@@ -4675,14 +4675,14 @@ index 0000000000000000000000000000000000000000..1c7275dd53e29594d25c63d3df54311a
|
||||
+ * <br>
|
||||
+ * Exactly one of {@code stopCondition} and {@code yieldingLock} must be non-null.
|
||||
+ */
|
||||
+ public final void yieldUntil(@Nullable BooleanSupplier stopCondition, @Nullable YieldingLock yieldingLock) {
|
||||
+ public final void yieldUntil(@Nullable Long timeoutTime, @Nullable BooleanSupplier stopCondition, @Nullable YieldingLock yieldingLock) {
|
||||
+ int oldYieldDepth = this.yieldDepth;
|
||||
+ int newYieldDepth = oldYieldDepth + 1;
|
||||
+ this.yieldDepth = newYieldDepth;
|
||||
+ if (newYieldDepth == maximumYieldDepth) {
|
||||
+ this.updateCanStartYieldingTasks();
|
||||
+ }
|
||||
+ this.runTasksUntil(stopCondition, yieldingLock);
|
||||
+ this.runTasksUntil(timeoutTime, stopCondition, yieldingLock);
|
||||
+ this.yieldDepth = oldYieldDepth;
|
||||
+ if (newYieldDepth == maximumYieldDepth) {
|
||||
+ this.updateCanStartYieldingTasks();
|
||||
@@ -4691,7 +4691,8 @@ index 0000000000000000000000000000000000000000..1c7275dd53e29594d25c63d3df54311a
|
||||
+
|
||||
+ /**
|
||||
+ * This method will keep attempting to find a task to do, and execute it, and if none is found, start waiting
|
||||
+ * until signalled by {@link BaseThreadPool} or by a {@link YieldingLock}.
|
||||
+ * until the {@code timeoutTime} is reached (which is compared to {@link System#nanoTime}),
|
||||
+ * or the thread is signalled by {@link BaseThreadPool} or by a {@link YieldingLock}.
|
||||
+ * The loop is broken as soon as the stop condition becomes true, or the given lock is successfully acquired.
|
||||
+ * <br>
|
||||
+ * The above is the same as {@link #yieldUntil}, except it may be called in situations that is not 'yielding',
|
||||
@@ -4704,7 +4705,8 @@ index 0000000000000000000000000000000000000000..1c7275dd53e29594d25c63d3df54311a
|
||||
+ */
|
||||
+ @ThisThreadOnly
|
||||
+ @PotentiallyYielding("may yield further if an executed task is potentially yielding")
|
||||
+ public final void runTasksUntil(@Nullable BooleanSupplier stopCondition, @Nullable YieldingLock yieldingLock) {
|
||||
+ public final void runTasksUntil(@Nullable Long timeoutTime, @Nullable BooleanSupplier stopCondition, @Nullable YieldingLock yieldingLock) {
|
||||
+ if (TickThread.isTickThread()) MinecraftServer.THREAD_DEBUG_LOGGER.ifPresent(it -> it.info("running tasks until"));
|
||||
+ this.isPollingTaskOrCheckingStopCondition = true;
|
||||
+
|
||||
+ /*
|
||||
@@ -4798,7 +4800,7 @@ index 0000000000000000000000000000000000000000..1c7275dd53e29594d25c63d3df54311a
|
||||
+ or for the given yielding lock to be released. This is the only time we should ever block inside
|
||||
+ a potentially yielding procedure.
|
||||
+ */
|
||||
+ this.waitUntilSignalled(yieldingLock);
|
||||
+ this.waitUntilSignalled(timeoutTime, yieldingLock);
|
||||
+
|
||||
+ }
|
||||
+
|
||||
@@ -4928,12 +4930,13 @@ index 0000000000000000000000000000000000000000..1c7275dd53e29594d25c63d3df54311a
|
||||
+ /**
|
||||
+ * Starts waiting on something to do.
|
||||
+ *
|
||||
+ * @param timeoutTime The maximum time to wait until (compared to {@link System#nanoTime}).
|
||||
+ * @param yieldingLock A {@link YieldingLock} to register with, or null if this thread is not waiting for
|
||||
+ * a yielding lock.
|
||||
+ */
|
||||
+ @ThisThreadOnly
|
||||
+ @PotentiallyBlocking
|
||||
+ private void waitUntilSignalled(@Nullable YieldingLock yieldingLock) {
|
||||
+ private void waitUntilSignalled(@Nullable Long timeoutTime, @Nullable YieldingLock yieldingLock) {
|
||||
+
|
||||
+ // Remember whether we registered to wait with the lock, to unregister later
|
||||
+ // Register this thread with the lock if necessary
|
||||
@@ -4999,57 +5002,57 @@ index 0000000000000000000000000000000000000000..1c7275dd53e29594d25c63d3df54311a
|
||||
+ // Wait
|
||||
+ try {
|
||||
+
|
||||
+ /*
|
||||
+ Check if we should wait with a timeout: this only happens if this thread is the server thread, in
|
||||
+ which case we do not want to wait past the start of the next tick.
|
||||
+ */
|
||||
+ boolean waitedWithTimeout = false;
|
||||
+ if (this == MinecraftServer.serverThread) {
|
||||
+ // -1 indicates to not use a timeout (this value is not later set to any other negative value)
|
||||
+ long waitForNanos = -1;
|
||||
+ if (MinecraftServer.isWaitingUntilNextTick) {
|
||||
+ /*
|
||||
+ During waiting until the next tick, we wait until the next tick start.
|
||||
+ If it already passed, we do not have to use a timeout, because we will be notified
|
||||
+ when the stop condition becomes true.
|
||||
+ */
|
||||
+ waitForNanos = MinecraftServer.nextTickStartNanoTime - System.nanoTime();
|
||||
+ if (waitForNanos < 0) {
|
||||
+ waitForNanos = -1;
|
||||
+ }
|
||||
+ } else if (MinecraftServer.SERVER.isOversleep) {
|
||||
+ /*
|
||||
+ During this phase, MinecraftServer#mayHaveDelayedTasks() is checked, and we may not
|
||||
+ be notified when it changes. Therefore, if the next tick start has not passed, we will
|
||||
+ wait until then, but if it has, we wait for a short interval to make sure we keep
|
||||
+ checking the stop condition (but not for longer than until the last time we can be
|
||||
+ executing extra delayed tasks).
|
||||
+ */
|
||||
+ waitForNanos = MinecraftServer.nextTickStartNanoTime - System.nanoTime();
|
||||
+ if (waitForNanos < 0) {
|
||||
+ waitForNanos = Math.min(Math.max(0, MinecraftServer.delayedTasksMaxNextTickNanoTime - System.nanoTime()), SERVER_THREAD_WAIT_NANOS_DURING_OVERSLEEP_WITH_DELAYED_TASKS);
|
||||
+ }
|
||||
+ }
|
||||
+ if (waitForNanos >= 0) {
|
||||
+ // Set the last signal reason to null in case the timeout elapses without a signal
|
||||
+ this.lastSignalReason = null;
|
||||
+ // Wait, but at most for the determined time
|
||||
+ waitedWithTimeout = true;
|
||||
+ // Skip if the time is too short
|
||||
+ if (waitForNanos >= SERVER_THREAD_WAIT_NANOS_MINIMUM) {
|
||||
+ //noinspection ResultOfMethodCallIgnored
|
||||
+ this.waitCondition.await(waitForNanos, TimeUnit.NANOSECONDS);
|
||||
+ // -1 indicates to not use a timeout (this value is not later set to any other negative value)
|
||||
+ long waitForNanos = -1;
|
||||
+ if (timeoutTime != null) {
|
||||
+ waitForNanos = Math.max(timeoutTime - System.nanoTime(), SERVER_THREAD_WAIT_NANOS_MINIMUM);
|
||||
+ } else {
|
||||
+ /*
|
||||
+ Check if we should wait with a tick-based timeout:
|
||||
+ this only happens if this thread is the server thread, in
|
||||
+ which case we do not want to wait past the start of the next tick.
|
||||
+ */
|
||||
+ if (this == MinecraftServer.serverThread) {
|
||||
+ if (MinecraftServer.isWaitingUntilNextTick) {
|
||||
+ /*
|
||||
+ During waiting until the next tick, we wait until the next tick start.
|
||||
+ If it already passed, we do not have to use a timeout, because we will be notified
|
||||
+ when the stop condition becomes true.
|
||||
+ */
|
||||
+ waitForNanos = MinecraftServer.nextTickStartNanoTime - System.nanoTime();
|
||||
+ if (waitForNanos < 0) {
|
||||
+ waitForNanos = -1;
|
||||
+ }
|
||||
+ } else if (MinecraftServer.SERVER.isOversleep) {
|
||||
+ /*
|
||||
+ During this phase, MinecraftServer#mayHaveDelayedTasks() is checked, and we may not
|
||||
+ be notified when it changes. Therefore, if the next tick start has not passed, we will
|
||||
+ wait until then, but if it has, we wait for a short interval to make sure we keep
|
||||
+ checking the stop condition (but not for longer than until the last time we can be
|
||||
+ executing extra delayed tasks).
|
||||
+ */
|
||||
+ waitForNanos = MinecraftServer.nextTickStartNanoTime - System.nanoTime();
|
||||
+ if (waitForNanos < 0) {
|
||||
+ waitForNanos = Math.min(Math.max(0, MinecraftServer.delayedTasksMaxNextTickNanoTime - System.nanoTime()), SERVER_THREAD_WAIT_NANOS_DURING_OVERSLEEP_WITH_DELAYED_TASKS);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ If we did not wait with a timeout, wait indefinitely. If this thread is the server thread,
|
||||
+ and the intended start time of the next tick has already passed, but the stop condition to stop
|
||||
+ running tasks is still not true, this thread must be signalled when a change in conditions causes
|
||||
+ the stop condition to become true.
|
||||
+ */
|
||||
+ if (!waitedWithTimeout) {
|
||||
+ if (waitForNanos >= 0) {
|
||||
+ // Set the last signal reason to null in case the timeout elapses without a signal
|
||||
+ this.lastSignalReason = null;
|
||||
+ // Skip if the time is too short
|
||||
+ if (waitForNanos >= SERVER_THREAD_WAIT_NANOS_MINIMUM) {
|
||||
+ //noinspection ResultOfMethodCallIgnored
|
||||
+ this.waitCondition.await(waitForNanos, TimeUnit.NANOSECONDS);
|
||||
+ }
|
||||
+ } else {
|
||||
+ /*
|
||||
+ If we did not wait with a timeout, wait indefinitely. If this thread is the server thread,
|
||||
+ and the intended start time of the next tick has already passed, but the stop condition to stop
|
||||
+ running tasks is still not true, this thread must be signalled when a change in conditions causes
|
||||
+ the stop condition to become true.
|
||||
+ */
|
||||
+ this.waitCondition.await();
|
||||
+ }
|
||||
+
|
||||
@@ -5301,7 +5304,7 @@ index 0000000000000000000000000000000000000000..a73aafc64dc60b57e2e5a91565e1aff6
|
||||
+}
|
||||
diff --git a/src/main/java/org/galemc/gale/executor/thread/deferral/ServerThreadDeferral.java b/src/main/java/org/galemc/gale/executor/thread/deferral/ServerThreadDeferral.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..57f672f9f81aeb6ce0ef44fa47db80602b03a5d4
|
||||
index 0000000000000000000000000000000000000000..8c4855c931ccc285768eabcff9d1f2b752d45bf6
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/galemc/gale/executor/thread/deferral/ServerThreadDeferral.java
|
||||
@@ -0,0 +1,151 @@
|
||||
@@ -5399,7 +5402,7 @@ index 0000000000000000000000000000000000000000..57f672f9f81aeb6ce0ef44fa47db8060
|
||||
+ }
|
||||
+ yieldingThread.signal(null);
|
||||
+ }, span);
|
||||
+ yieldingThread.yieldUntil(future::isDone, null);
|
||||
+ yieldingThread.yieldUntil(null, future::isDone, null);
|
||||
+ return future.getNow(null);
|
||||
+ } else {
|
||||
+ // Block until the task completes
|
||||
|
||||
@@ -27,7 +27,7 @@ index 4b8da38db72d7ebc2d498ec3d711d3b30911096c..80f9e70d5c4330e079feccc9a4b1b595
|
||||
1, 1, 0L, TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<>(),
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index fe2892e20dcb0b76d30b81bca7a13e29a1c45723..313d45dae086ac7c1bd0dd71540020c18a9e5d86 100644
|
||||
index fe2892e20dcb0b76d30b81bca7a13e29a1c45723..c2930cc38d02fb62cf7b1a8bdde53753cb4bc64e 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1081,9 +1081,6 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop
|
||||
@@ -47,7 +47,7 @@ index fe2892e20dcb0b76d30b81bca7a13e29a1c45723..313d45dae086ac7c1bd0dd71540020c1
|
||||
+ // Gale start - base thread pool - remove Paper async executor
|
||||
+ long startTime = Util.getMillis();
|
||||
+ LOGGER.info("Waiting 30 seconds for asynchronous tasks to finish...");
|
||||
+ serverThread.runTasksUntil(() -> Util.getMillis() - startTime >= 30 || !BaseTaskQueues.scheduledAsync.hasTasks(), null); // Paper
|
||||
+ serverThread.runTasksUntil(null, () -> Util.getMillis() - startTime >= 30 || !BaseTaskQueues.scheduledAsync.hasTasks(), null); // Paper
|
||||
+ LOGGER.info("Shutting down IO executor...");
|
||||
+ // Gale end - base thread pool - remove Paper async executor
|
||||
Util.shutdownExecutors(); // Paper
|
||||
|
||||
@@ -7,7 +7,7 @@ License: AGPL-3.0 (https://www.gnu.org/licenses/agpl-3.0.html)
|
||||
Gale - https://galemc.org
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 83a57b9bc59063ed8299f98bc33e14b57f2ea0de..f1aaf1cae3335f7c7340104cfd6dbc3dd62f6ab3 100644
|
||||
index 83a57b9bc59063ed8299f98bc33e14b57f2ea0de..5187fd95577afa4ddf4544206ec6bb467bcdce81 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -11,7 +11,6 @@ import java.util.Collections;
|
||||
@@ -44,26 +44,23 @@ index 83a57b9bc59063ed8299f98bc33e14b57f2ea0de..f1aaf1cae3335f7c7340104cfd6dbc3d
|
||||
} else {
|
||||
completablefuture = CompletableFuture.supplyAsync(() -> {
|
||||
return this.getChunkFutureMainThread(chunkX, chunkZ, leastStatus, create);
|
||||
@@ -973,6 +973,18 @@ public class ServerChunkCache extends ChunkSource {
|
||||
@@ -973,6 +973,15 @@ public class ServerChunkCache extends ChunkSource {
|
||||
|
||||
public final class MainThreadExecutor extends BlockableEventLoop<Runnable> {
|
||||
|
||||
+ // Gale start - base thread pool
|
||||
+ private static volatile boolean chunkWorkerTasksWereCompletedSinceLastDoChunkCacheTasksInYield;
|
||||
+ public static @Nullable YieldingLock yieldingLockToNotifyForNewChunkCacheTasks;
|
||||
+
|
||||
+ public static void notifyOfCompletedChunkWorkerTasks() {
|
||||
+ if (yieldingLockToNotifyForNewChunkCacheTasks != null) {
|
||||
+ chunkWorkerTasksWereCompletedSinceLastDoChunkCacheTasksInYield = true;
|
||||
+ yieldingLockToNotifyForNewChunkCacheTasks.unlock();
|
||||
+ }
|
||||
+ }
|
||||
+ /**
|
||||
+ * The time interval for the server thread to yield when this executor is performing
|
||||
+ * a {@link #managedYield} but failed to perform any other tasks from this executor itself.
|
||||
+ */
|
||||
+ private static final long MANAGED_YIELD_TIMEOUT_TIME = 50_000L;
|
||||
+ private static @Nullable YieldingLock yieldingLockToNotifyForNewChunkCacheTasks;
|
||||
+ // Gale end - base thread pool
|
||||
+
|
||||
MainThreadExecutor(Level world) {
|
||||
super("Chunk source main thread executor for " + world.dimension().location());
|
||||
}
|
||||
@@ -1002,6 +1014,40 @@ public class ServerChunkCache extends ChunkSource {
|
||||
@@ -1002,6 +1011,40 @@ public class ServerChunkCache extends ChunkSource {
|
||||
super.doRunTask(task);
|
||||
}
|
||||
|
||||
@@ -89,8 +86,8 @@ index 83a57b9bc59063ed8299f98bc33e14b57f2ea0de..f1aaf1cae3335f7c7340104cfd6dbc3d
|
||||
+ var currentThread = AbstractYieldingThread.currentYieldingThread();
|
||||
+ while (!future.isDone()) {
|
||||
+ if (!this.pollTask()) {
|
||||
+ currentThread.yieldUntilFuture(() -> this.hasPendingTasks() || chunkWorkerTasksWereCompletedSinceLastDoChunkCacheTasksInYield, future, autoCompletingLock -> yieldingLockToNotifyForNewChunkCacheTasks = autoCompletingLock);
|
||||
+ chunkWorkerTasksWereCompletedSinceLastDoChunkCacheTasksInYield = false;
|
||||
+ long timeoutTime = System.nanoTime() + MANAGED_YIELD_TIMEOUT_TIME;
|
||||
+ currentThread.yieldUntilFuture(timeoutTime, () -> this.hasPendingTasks(), future, autoCompletingLock -> yieldingLockToNotifyForNewChunkCacheTasks = autoCompletingLock);
|
||||
+ }
|
||||
+ }
|
||||
+ yieldingLockToNotifyForNewChunkCacheTasks = null;
|
||||
|
||||
@@ -480,7 +480,7 @@ index f5c15d40094c2ddc6220b0595597d12103fcf425..79ef41d2bb30beee2355d1de3dc99c9e
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 313d45dae086ac7c1bd0dd71540020c18a9e5d86..c14b593bd450d244209d17b637fe7c03a1f746f4 100644
|
||||
index c2930cc38d02fb62cf7b1a8bdde53753cb4bc64e..29c86b4ee9b147a7645f6577ce22b7a2e6f0b213 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1070,6 +1070,10 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop
|
||||
@@ -489,7 +489,7 @@ index 313d45dae086ac7c1bd0dd71540020c18a9e5d86..c14b593bd450d244209d17b637fe7c03
|
||||
|
||||
+ // Gale start - base thread pool - chunk worker task queue
|
||||
+ LOGGER.info("Waiting for chunk worker tasks to finish...");
|
||||
+ serverThread.runTasksUntil(() -> !BaseTaskQueues.chunkWorker.hasTasks(), null);
|
||||
+ serverThread.runTasksUntil(null, () -> !BaseTaskQueues.chunkWorker.hasTasks(), null);
|
||||
+ // Gale end - base thread pool - chunk worker task queue
|
||||
this.saveAllChunks(false, true, false, true); // Paper - rewrite chunk system - move closing into here
|
||||
|
||||
@@ -545,10 +545,10 @@ index ed3ccf2e64539363a7be2d507c68c40b5913f75c..a12250e5aaed02995b7bf09a8018a93f
|
||||
}
|
||||
diff --git a/src/main/java/org/galemc/gale/executor/queue/ChunkWorkerTaskQueue.java b/src/main/java/org/galemc/gale/executor/queue/ChunkWorkerTaskQueue.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..221f9e6f10c56c92e00fc8f41e09a977a7ed9e76
|
||||
index 0000000000000000000000000000000000000000..9c36119b03ba9a20dc6994ef2d2704ebe9cc4800
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/galemc/gale/executor/queue/ChunkWorkerTaskQueue.java
|
||||
@@ -0,0 +1,106 @@
|
||||
@@ -0,0 +1,103 @@
|
||||
+// Gale - base thread pool - chunk worker task queue
|
||||
+
|
||||
+package org.galemc.gale.executor.queue;
|
||||
@@ -621,11 +621,8 @@ index 0000000000000000000000000000000000000000..221f9e6f10c56c92e00fc8f41e09a977
|
||||
+ return () -> {
|
||||
+ var workerAgent = currentThread.getChunkWorkerAgent();
|
||||
+ ChunkTaskScheduler.workerThreads.activeThreads.add(workerAgent);
|
||||
+ boolean performedTasks = workerAgent.pollTasks();
|
||||
+ workerAgent.pollTasks();
|
||||
+ ChunkTaskScheduler.workerThreads.activeThreads.remove(workerAgent);
|
||||
+ if (performedTasks) {
|
||||
+ ServerChunkCache.MainThreadExecutor.notifyOfCompletedChunkWorkerTasks();
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
+
|
||||
@@ -656,7 +653,7 @@ index 0000000000000000000000000000000000000000..221f9e6f10c56c92e00fc8f41e09a977
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/org/galemc/gale/executor/thread/BaseThread.java b/src/main/java/org/galemc/gale/executor/thread/BaseThread.java
|
||||
index 1c7275dd53e29594d25c63d3df54311a300a08fb..00a52c8c21ebfa95cfd3e6e9d9d76c5789ea6d83 100644
|
||||
index 17ae524053949073fcdcbccc53327c42ba1903c6..a01ce790927ff79071c582ca84d64207fd850dfa 100644
|
||||
--- a/src/main/java/org/galemc/gale/executor/thread/BaseThread.java
|
||||
+++ b/src/main/java/org/galemc/gale/executor/thread/BaseThread.java
|
||||
@@ -2,6 +2,8 @@
|
||||
@@ -676,7 +673,7 @@ index 1c7275dd53e29594d25c63d3df54311a300a08fb..00a52c8c21ebfa95cfd3e6e9d9d76c57
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -696,6 +699,20 @@ public abstract class BaseThread extends Thread implements AbstractYieldingThrea
|
||||
@@ -699,6 +702,20 @@ public abstract class BaseThread extends Thread implements AbstractYieldingThrea
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user