From 88533118bcb20f288f33c245d40fc6a3f9805ab3 Mon Sep 17 00:00:00 2001 From: Jordan Date: Mon, 19 Jun 2023 22:46:10 +0200 Subject: [PATCH] fix: uncache the chunk SET at a better time in ChunkHolder to prevent "lost" changes (#2300) - blocks could still be set to the ChunkHolder during a call - create a new chunk SET in that case - make cached get/set volatile to improve thread safety --- .../queue/implementation/chunk/ChunkHolder.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java index 7390758bc..9172d8b3e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java @@ -45,8 +45,8 @@ public class ChunkHolder> implements IQueueChunk { private final ReentrantWrappedStampedLock calledLock = new ReentrantWrappedStampedLock(); - private IChunkGet chunkExisting; // The existing chunk (e.g. a clipboard, or the world, before changes) - private IChunkSet chunkSet; // The blocks to be set to the chunkExisting + private volatile IChunkGet chunkExisting; // The existing chunk (e.g. a clipboard, or the world, before changes) + private volatile IChunkSet chunkSet; // The blocks to be set to the chunkExisting private IBlockDelegate delegate; // delegate handles the abstraction of the chunk layers private IQueueExtent extent; // the parent queue extent which has this chunk private int chunkX; @@ -1042,13 +1042,12 @@ public class ChunkHolder> implements IQueueChunk { calledLock.lock(); final long stamp = calledLock.getStampChecked(); if (chunkSet != null && !chunkSet.isEmpty()) { + this.delegate = GET; chunkSet.setBitMask(bitMask); try { - return this.call(chunkSet.createCopy(), () -> { - this.delegate = NULL; - chunkSet = null; - calledLock.unlock(stamp); - }); + IChunkSet copy = chunkSet.createCopy(); + chunkSet = null; + return this.call(copy, () -> calledLock.unlock(stamp)); } catch (Throwable t) { calledLock.unlock(); throw t;