mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-23 08:59:23 +00:00
134 lines
6.9 KiB
Diff
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);
|