9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-23 08:59:23 +00:00
Files
Leaf/patches/server/0072-Hearse-Add-locks-when-calling-getChunk-in-worker-thr.patch
2023-01-27 08:39:13 -05:00

134 lines
6.9 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: wangxyper <wangxyper@163.com>
Date: Thu, 19 Jan 2023 10:03:10 +0800
Subject: [PATCH] Hearse: Add locks when calling getChunk in worker thread
Original license: MIT
Original project: https://github.com/Era4FunMC/Hearse
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index e311724d2e723115bc9549a61e6206a8aed835d8..b151339cc56418f82f9b75b39b8fc6ab6686993e 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -1,5 +1,6 @@
package net.minecraft.server.level;
+import co.earthme.hearse.concurrent.thread.Worker;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.mojang.datafixers.DataFixer;
@@ -377,57 +378,68 @@ public class ServerChunkCache extends ChunkSource {
}
// Paper end - async chunk io
+ private final Object workerGetChunkLock = new Object();
+
@Nullable
@Override
public ChunkAccess getChunk(int x, int z, ChunkStatus leastStatus, boolean create) {
- final int x1 = x; final int z1 = z; // Paper - conflict on variable change
if (!io.papermc.paper.util.TickThread.isTickThread()) { // Paper - rewrite chunk system
return (ChunkAccess) CompletableFuture.supplyAsync(() -> {
return this.getChunk(x, z, leastStatus, create);
}, this.mainThreadProcessor).join();
} else {
- // Paper start - optimise for loaded chunks
- LevelChunk ifLoaded = this.getChunkAtIfLoadedMainThread(x, z);
- if (ifLoaded != null) {
- return ifLoaded;
+ if (Thread.currentThread() instanceof Worker){
+ synchronized (this.workerGetChunkLock){
+ return this.getChunkUnsafe(x,z,leastStatus,create);
+ }
}
- // Paper end
- //ProfilerFiller gameprofilerfiller = this.level.getProfiler(); // Purpur
+ return this.getChunkUnsafe(x,z,leastStatus,create);
+ }
+ }
- //gameprofilerfiller.incrementCounter("getChunk"); // Purpur
- long k = ChunkPos.asLong(x, z);
+ private ChunkAccess getChunkUnsafe(int x,int z,ChunkStatus leastStatus,boolean create){
+ final int x1 = x; final int z1 = z; // Paper - conflict on variable change
+ // Paper start - optimise for loaded chunks
+ LevelChunk ifLoaded = this.getChunkAtIfLoadedMainThread(x, z);
+ if (ifLoaded != null) {
+ return ifLoaded;
+ }
+ // Paper end
+ //ProfilerFiller gameprofilerfiller = this.level.getProfiler(); // Purpur
- ChunkAccess ichunkaccess;
+ //gameprofilerfiller.incrementCounter("getChunk"); // Purpur
+ long k = ChunkPos.asLong(x, z);
- // Paper - rewrite chunk system - there are no correct callbacks to remove items from cache in the new chunk system
+ ChunkAccess ichunkaccess;
- //gameprofilerfiller.incrementCounter("getChunkCacheMiss"); // Purpur
- CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create, true); // Paper
- ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor;
+ // Paper - rewrite chunk system - there are no correct callbacks to remove items from cache in the new chunk system
- Objects.requireNonNull(completablefuture);
- if (!completablefuture.isDone()) { // Paper
- // Paper start - async chunk io/loading
- io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.pushChunkWait(this.level, x1, z1); // Paper - rewrite chunk system
- // Paper end
- com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x1, z1); // Paper - sync load info
- //this.level.timings.syncChunkLoad.startTiming(); // Paper // Purpur
- chunkproviderserver_b.managedBlock(completablefuture::isDone);
- io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.popChunkWait(); // Paper - async chunk debug // Paper - rewrite chunk system
- //this.level.timings.syncChunkLoad.stopTiming(); // Paper // Purpur
- } // Paper
- ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> {
- return ichunkaccess1;
- }, (playerchunk_failure) -> {
- if (create) {
- throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("Chunk not there when requested: " + playerchunk_failure));
- } else {
- return null;
- }
- });
- this.storeInCache(k, ichunkaccess, leastStatus);
- return ichunkaccess;
- }
+ //gameprofilerfiller.incrementCounter("getChunkCacheMiss"); // Purpur
+ CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create, true); // Paper
+ ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor;
+
+ Objects.requireNonNull(completablefuture);
+ if (!completablefuture.isDone()) { // Paper
+ // Paper start - async chunk io/loading
+ io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.pushChunkWait(this.level, x1, z1); // Paper - rewrite chunk system
+ // Paper end
+ com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x1, z1); // Paper - sync load info
+ //this.level.timings.syncChunkLoad.startTiming(); // Paper // Purpur
+ chunkproviderserver_b.managedBlock(completablefuture::isDone);
+ io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.popChunkWait(); // Paper - async chunk debug // Paper - rewrite chunk system
+ //this.level.timings.syncChunkLoad.stopTiming(); // Paper // Purpur
+ } // Paper
+ ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> {
+ return ichunkaccess1;
+ }, (playerchunk_failure) -> {
+ if (create) {
+ throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("Chunk not there when requested: " + playerchunk_failure));
+ } else {
+ return null;
+ }
+ });
+ this.storeInCache(k, ichunkaccess, leastStatus);
+ return ichunkaccess;
}
@Nullable
@@ -440,6 +452,7 @@ public class ServerChunkCache extends ChunkSource {
}
}
+
private void clearCache() {
Arrays.fill(this.lastChunkPos, ChunkPos.INVALID_CHUNK_POS);
Arrays.fill(this.lastChunkStatus, (Object) null);