feat(compat): expose shared DistanceManager lock for cross-mod ticket iteration
将 DistanceManagerMixin 的私有 static LOCK 抽到公开的 dev.modzuozhi.core.compat.DistanceManagerLock.LOCK,供 ServerWarashi 的 TicketScanService 通过反射共用,实现 ticket 表「读-写互斥」。 背景:DR 维度线程在 tick 中并发增删 DistanceManager.tickets (Long2ObjectOpenHashMap),warashi 主线程遍历同表做采样归属快照时, fastutil fail-fast 迭代器内部 wrapped 被置 null -> nextEntry NPE 崩服。 DR 原有锁保护所有写路径,但读路径(warashi 遍历)不在锁内。 - 新增 DistanceManagerLock(公开 ReentrantLock) - DistanceManagerMixin 的 LOCK 指向该共享锁
This commit is contained in:
1 parent
72936288d9
commit
d76d6593bd
2 files changed
+24
-3
No files matched your search
@@ -0,0 +1,22 @@
|
||||
package dev.modzuozhi.core.compat;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* DistanceManager ticket 表的共享锁。
|
||||
* <p>
|
||||
* DR 让维度 tick 跑在独立线程后,多个线程会并发修改 {@code DistanceManager.tickets}
|
||||
* ({@code Long2ObjectOpenHashMap},非线程安全)。{@link dev.modzuozhi.mixin.DistanceManagerMixin}
|
||||
* 用它串行化所有 ticket 写路径。
|
||||
* <p>
|
||||
* <b>跨 mod 可见性</b>:ServerWarashi 的 {@code TicketScanService} 在主线程遍历同一张 ticket 表
|
||||
* (性能采样归属快照),若不持同一把锁,遍历会与维度线程的写并发 → fastutil fail-fast 迭代器
|
||||
* NPE。因此本锁<b>公开</b>,warashi 通过反射获取并共用,实现「读-写互斥」。
|
||||
*/
|
||||
public final class DistanceManagerLock {
|
||||
/** 所有 DistanceManager ticket 读/写路径共用的锁。 */
|
||||
public static final ReentrantLock LOCK = new ReentrantLock();
|
||||
|
||||
private DistanceManagerLock() {
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,7 @@ import net.minecraft.server.level.Ticket;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import dev.modzuozhi.core.compat.DistanceManagerLock;
|
||||
/**
|
||||
* {@code DistanceManager}(区块 ticket 调度)并发保护。
|
||||
* <p>
|
||||
@@ -26,7 +25,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
*/
|
||||
@Mixin(DistanceManager.class)
|
||||
public class DistanceManagerMixin {
|
||||
private static final ReentrantLock LOCK = new ReentrantLock();
|
||||
private static final java.util.concurrent.locks.ReentrantLock LOCK = DistanceManagerLock.LOCK;
|
||||
|
||||
@WrapMethod(method = "addTicket")
|
||||
private void modzuozhi_lockAddTicket(long chunkPos, Ticket<?> ticket, Operation<Void> original) {
|
||||
|
||||
Reference in new issue
Block a user