diff --git a/leaf-server/minecraft-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch b/leaf-server/minecraft-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch index ab709291..bb16fab5 100644 --- a/leaf-server/minecraft-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch +++ b/leaf-server/minecraft-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch @@ -22,7 +22,7 @@ and, in my opinion, worth the low risk of minor mob-spawning-related inconsistencies. 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 +++ b/net/minecraft/server/MinecraftServer.java @@ -286,6 +286,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function threadFunction) { ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system +@@ -1055,6 +1056,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop jobs = Queues.newArrayDeque(); - private final Lock mutex = new ReentrantLock(); - private final Condition cond = mutex.newCondition(); + private final PriorityQueue jobs = PriorityQueues.synchronize(new ObjectArrayFIFOQueue<>()); private final Thread thread; private volatile boolean killswitch = false; 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() { thread.start(); } - public void kill() { + public void kill() throws InterruptedException { killswitch = true; - cond.signalAll(); + LockSupport.unpark(thread); + thread.join(); } public void submit(Runnable runnable) { - mutex.lock(); - try { - jobs.offer(runnable); - cond.signalAll(); - } finally { - mutex.unlock(); - } + jobs.enqueue(runnable); + LockSupport.unpark(thread); } @Override public void run() { while (!killswitch) { try { - Runnable runnable = takeRunnable(); - if (runnable != null) { - runnable.run(); + Runnable runnable; + try { + runnable = jobs.dequeue(); + } catch (NoSuchElementException e) { + LockSupport.park(); + continue; } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + runnable.run(); } catch (Exception 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(); - } - } }