From fd85b785ea0b202c99d862f7f83bab47b75b5c9c Mon Sep 17 00:00:00 2001 From: Aikar Date: Sat, 6 Oct 2018 00:15:40 -0400 Subject: [PATCH] Don't stop chunk executors, cancel pending chunks instead Fixes #1532 --- .../Async-Chunk-Loading-and-Generation.patch | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/Spigot-Server-Patches/Async-Chunk-Loading-and-Generation.patch b/Spigot-Server-Patches/Async-Chunk-Loading-and-Generation.patch index 2f80327df1..add9d1b583 100644 --- a/Spigot-Server-Patches/Async-Chunk-Loading-and-Generation.patch +++ b/Spigot-Server-Patches/Async-Chunk-Loading-and-Generation.patch @@ -599,7 +599,7 @@ index bdfc7d81ff..a5c4564d60 100644 public IBlockData getType(int i, int j, int k) { return this.blockIds.a(i, j, k); diff --git a/src/main/java/net/minecraft/server/ChunkTaskScheduler.java b/src/main/java/net/minecraft/server/ChunkTaskScheduler.java -index 34019bd1b3..4ca977645f 100644 +index 34019bd1b3..d7b9ca3ee7 100644 --- a/src/main/java/net/minecraft/server/ChunkTaskScheduler.java +++ b/src/main/java/net/minecraft/server/ChunkTaskScheduler.java @@ -0,0 +0,0 @@ public class ChunkTaskScheduler extends Scheduler progressCache = new ExpiringMap(8192, 5000) { // CraftBukkit - decompile error -+ final Long2ObjectMap progressCache = new ExpiringMap(8192, 5000) { // CraftBukkit - decompile error // Paper - synchronize ++ final Long2ObjectMap progressCache = new ExpiringMap(8192, 5000) { // CraftBukkit - decompile error // Paper - protected protected boolean a(Scheduler.a scheduler_a) { ProtoChunk protochunk = (ProtoChunk) scheduler_a.a(); @@ -855,7 +855,7 @@ index 98d182fdb8..487d98eb1b 100644 diff --git a/src/main/java/net/minecraft/server/PaperAsyncChunkProvider.java b/src/main/java/net/minecraft/server/PaperAsyncChunkProvider.java new file mode 100644 -index 0000000000..7fb95330fa +index 0000000000..1916bf372e --- /dev/null +++ b/src/main/java/net/minecraft/server/PaperAsyncChunkProvider.java @@ -0,0 +0,0 @@ @@ -908,9 +908,8 @@ index 0000000000..7fb95330fa +@SuppressWarnings("unused") +public class PaperAsyncChunkProvider extends ChunkProviderServer { + -+ private static final PriorityQueuedExecutor.RejectionHandler IGNORE_HANDLER = (run, executor) -> {}; -+ private static final PriorityQueuedExecutor EXECUTOR = new PriorityQueuedExecutor("PaperChunkLoader", PaperConfig.asyncChunks ? PaperConfig.asyncChunkLoadThreads : 0, IGNORE_HANDLER); -+ private static final PriorityQueuedExecutor SINGLE_GEN_EXECUTOR = new PriorityQueuedExecutor("PaperChunkGenerator", PaperConfig.asyncChunks && PaperConfig.asyncChunkGeneration && !PaperConfig.asyncChunkGenThreadPerWorld ? 1 : 0, IGNORE_HANDLER); ++ private static final PriorityQueuedExecutor EXECUTOR = new PriorityQueuedExecutor("PaperChunkLoader", PaperConfig.asyncChunks ? PaperConfig.asyncChunkLoadThreads : 0); ++ private static final PriorityQueuedExecutor SINGLE_GEN_EXECUTOR = new PriorityQueuedExecutor("PaperChunkGenerator", PaperConfig.asyncChunks && PaperConfig.asyncChunkGeneration && !PaperConfig.asyncChunkGenThreadPerWorld ? 1 : 0); + + private final PriorityQueuedExecutor generationExecutor; + //private static final PriorityQueuedExecutor generationExecutor = new PriorityQueuedExecutor("PaperChunkGen", 1); @@ -932,7 +931,7 @@ index 0000000000..7fb95330fa + this.chunkLoader = chunkLoader; + String worldName = this.world.getWorld().getName(); + this.shouldGenSync = generator instanceof CustomChunkGenerator && !(((CustomChunkGenerator) generator).asyncSupported) || !PaperConfig.asyncChunkGeneration; -+ this.generationExecutor = PaperConfig.asyncChunkGenThreadPerWorld ? new PriorityQueuedExecutor("PaperChunkGen-" + worldName, shouldGenSync ? 0 : 1, IGNORE_HANDLER) : SINGLE_GEN_EXECUTOR; ++ this.generationExecutor = PaperConfig.asyncChunkGenThreadPerWorld ? new PriorityQueuedExecutor("PaperChunkGen-" + worldName, shouldGenSync ? 0 : 1) : SINGLE_GEN_EXECUTOR; + } + + static void processChunkLoads(MinecraftServer server) { @@ -949,12 +948,8 @@ index 0000000000..7fb95330fa + } + + static void stop(MinecraftServer server) { -+ EXECUTOR.shutdownNow(); + for (WorldServer world : server.getWorlds()) { -+ IChunkProvider chunkProvider = world.getChunkProvider(); -+ if (chunkProvider instanceof PaperAsyncChunkProvider) { -+ ((PaperAsyncChunkProvider) chunkProvider).generationExecutor.shutdownNow(); -+ } ++ world.getPlayerChunkMap().shutdown(); + } + } + @@ -1432,7 +1427,7 @@ index 0000000000..7fb95330fa + +} diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java -index 2c7c8adf7c..6d18cdeaf7 100644 +index 2c7c8adf7c..aabd107fe1 100644 --- a/src/main/java/net/minecraft/server/PlayerChunk.java +++ b/src/main/java/net/minecraft/server/PlayerChunk.java @@ -0,0 +0,0 @@ public class PlayerChunk { @@ -1445,7 +1440,7 @@ index 2c7c8adf7c..6d18cdeaf7 100644 - loadInProgress = false; - PlayerChunk.this.chunk = PlayerChunk.this.playerChunkMap.getWorld().getChunkProviderServer().getChunkAt(location.x, location.z, true, true); - markChunkUsed(); // Paper - delay chunk unloads -+ private PaperAsyncChunkProvider.CancellableChunkRequest chunkRequest; ++ PaperAsyncChunkProvider.CancellableChunkRequest chunkRequest; + // Paper start + private java.util.function.Consumer chunkLoadedConsumer = chunk -> { + chunkRequest = null; @@ -1537,7 +1532,7 @@ index 2c7c8adf7c..6d18cdeaf7 100644 } } diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java -index d1a443ca8d..1201a2758e 100644 +index d1a443ca8d..1504bd113b 100644 --- a/src/main/java/net/minecraft/server/PlayerChunkMap.java +++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java @@ -0,0 +0,0 @@ public class PlayerChunkMap { @@ -1548,7 +1543,11 @@ index d1a443ca8d..1201a2758e 100644 + }; static final Predicate CAN_GEN_CHUNKS = b; // Paper - OBFHELPER private final WorldServer world; private final List managedPlayers = Lists.newArrayList(); - private final Long2ObjectMap e = new Long2ObjectOpenHashMap(4096); +- private final Long2ObjectMap e = new Long2ObjectOpenHashMap(4096); ++ private final Long2ObjectMap e = new Long2ObjectOpenHashMap(4096); Long2ObjectMap getChunks() { return e; } // Paper - OBFHELPER + private final Set f = Sets.newHashSet(); + private final List g = Lists.newLinkedList(); + private final List h = Lists.newLinkedList(); @@ -0,0 +0,0 @@ public class PlayerChunkMap { if (playerchunk != null) { playerchunk.b(entityplayer); @@ -1576,6 +1575,22 @@ index d1a443ca8d..1201a2758e 100644 } // CraftBukkit end } +@@ -0,0 +0,0 @@ public class PlayerChunkMap { + } + } + } ++ ++ void shutdown() { ++ getChunks().values().forEach(pchunk -> { ++ PaperAsyncChunkProvider.CancellableChunkRequest chunkRequest = pchunk.chunkRequest; ++ if (chunkRequest != null) { ++ chunkRequest.cancel(); ++ } ++ }); ++ } + // Paper end + + private void e() { diff --git a/src/main/java/net/minecraft/server/RegionLimitedWorldAccess.java b/src/main/java/net/minecraft/server/RegionLimitedWorldAccess.java index 3c35c0f481..187ca2813a 100644 --- a/src/main/java/net/minecraft/server/RegionLimitedWorldAccess.java