9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-23 08:59:23 +00:00

shutdown mob spawning thread on exit

This commit is contained in:
hayanesuru
2025-06-04 00:39:42 +09:00
parent 8e48e51e76
commit 2cd4838b7e
2 changed files with 39 additions and 39 deletions

View File

@@ -22,7 +22,7 @@ and, in my opinion, worth the low risk of minor mob-spawning-related
inconsistencies. inconsistencies.
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 4ba85d704ffebae38f7a76a97a182e3674730c6f..a76b67a846b12a7b3d0c41b6ac4833d4f0372531 100644 index 4ba85d704ffebae38f7a76a97a182e3674730c6f..d19e31d3b280325defcaf46e7168eafb3d6587d2 100644
--- a/net/minecraft/server/MinecraftServer.java --- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java
@@ -286,6 +286,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -286,6 +286,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -33,6 +33,21 @@ index 4ba85d704ffebae38f7a76a97a182e3674730c6f..a76b67a846b12a7b3d0c41b6ac4833d4
public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) { public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) {
ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system
@@ -1055,6 +1056,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
io.papermc.paper.log.CustomLogManager.forceReset(); // Paper - Reset loggers after shutdown
this.onServerExit();
// Paper end - Improved watchdog support - move final shutdown items here
+ // Leaf start - Async mob spawning
+ if (this.mobSpawnExecutor != null) {
+ try {
+ this.mobSpawnExecutor.kill();
+ } catch (java.lang.InterruptedException ignored) {
+ }
+ }
+ // Leaf end - Async mob spawning
}
public String getLocalIp() {
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
index bd7f792c45059f0652e530608ef0c77c5caf7cfa..649403ef1d5d898052412d6d47783769f291b94f 100644 index bd7f792c45059f0652e530608ef0c77c5caf7cfa..649403ef1d5d898052412d6d47783769f291b94f 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java --- a/net/minecraft/server/dedicated/DedicatedServer.java

View File

@@ -1,74 +1,59 @@
package gg.pufferfish.pufferfish.util; package gg.pufferfish.pufferfish.util;
import com.google.common.collect.Queues; import it.unimi.dsi.fastutil.PriorityQueue;
import it.unimi.dsi.fastutil.PriorityQueues;
import it.unimi.dsi.fastutil.objects.ObjectArrayFIFOQueue;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.util.Queue; import java.util.NoSuchElementException;
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class AsyncExecutor implements Runnable { public class AsyncExecutor implements Runnable {
private final Logger LOGGER = LogManager.getLogger("Leaf"); private final Logger LOGGER = LogManager.getLogger("Leaf");
private final Queue<Runnable> jobs = Queues.newArrayDeque(); private final PriorityQueue<Runnable> jobs = PriorityQueues.synchronize(new ObjectArrayFIFOQueue<>());
private final Lock mutex = new ReentrantLock();
private final Condition cond = mutex.newCondition();
private final Thread thread; private final Thread thread;
private volatile boolean killswitch = false; private volatile boolean killswitch = false;
public AsyncExecutor(String threadName) { public AsyncExecutor(String threadName) {
this.thread = new Thread(this, threadName); this.thread = Thread.ofPlatform()
.name(threadName)
.priority(Thread.NORM_PRIORITY - 1)
.daemon(false)
.unstarted(this);
} }
public void start() { public void start() {
thread.start(); thread.start();
} }
public void kill() { public void kill() throws InterruptedException {
killswitch = true; killswitch = true;
cond.signalAll(); LockSupport.unpark(thread);
thread.join();
} }
public void submit(Runnable runnable) { public void submit(Runnable runnable) {
mutex.lock(); jobs.enqueue(runnable);
try { LockSupport.unpark(thread);
jobs.offer(runnable);
cond.signalAll();
} finally {
mutex.unlock();
}
} }
@Override @Override
public void run() { public void run() {
while (!killswitch) { while (!killswitch) {
try { try {
Runnable runnable = takeRunnable(); Runnable runnable;
if (runnable != null) { try {
runnable.run(); runnable = jobs.dequeue();
} catch (NoSuchElementException e) {
LockSupport.park();
continue;
} }
} catch (InterruptedException e) { runnable.run();
Thread.currentThread().interrupt();
} catch (Exception e) { } catch (Exception e) {
LOGGER.error("Failed to execute async job for thread {}", thread.getName(), e); LOGGER.error("Failed to execute async job for thread {}", thread.getName(), e);
} }
} }
} }
private Runnable takeRunnable() throws InterruptedException {
mutex.lock();
try {
while (jobs.isEmpty() && !killswitch) {
cond.await();
}
if (jobs.isEmpty()) return null; // We've set killswitch
return jobs.remove();
} finally {
mutex.unlock();
}
}
} }