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
Dieser Commit ist enthalten in:
Jordan 2023-06-19 22:46:10 +02:00 committet von GitHub
Ursprung 8ca25fa7d7
Commit 88533118bc
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 4AEE18F83AFDEB23

Datei anzeigen

@ -45,8 +45,8 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
private final ReentrantWrappedStampedLock calledLock = new ReentrantWrappedStampedLock(); private final ReentrantWrappedStampedLock calledLock = new ReentrantWrappedStampedLock();
private IChunkGet chunkExisting; // The existing chunk (e.g. a clipboard, or the world, before changes) private volatile 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 IChunkSet chunkSet; // The blocks to be set to the chunkExisting
private IBlockDelegate delegate; // delegate handles the abstraction of the chunk layers private IBlockDelegate delegate; // delegate handles the abstraction of the chunk layers
private IQueueExtent<? extends IChunk> extent; // the parent queue extent which has this chunk private IQueueExtent<? extends IChunk> extent; // the parent queue extent which has this chunk
private int chunkX; private int chunkX;
@ -1042,13 +1042,12 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
calledLock.lock(); calledLock.lock();
final long stamp = calledLock.getStampChecked(); final long stamp = calledLock.getStampChecked();
if (chunkSet != null && !chunkSet.isEmpty()) { if (chunkSet != null && !chunkSet.isEmpty()) {
this.delegate = GET;
chunkSet.setBitMask(bitMask); chunkSet.setBitMask(bitMask);
try { try {
return this.call(chunkSet.createCopy(), () -> { IChunkSet copy = chunkSet.createCopy();
this.delegate = NULL;
chunkSet = null; chunkSet = null;
calledLock.unlock(stamp); return this.call(copy, () -> calledLock.unlock(stamp));
});
} catch (Throwable t) { } catch (Throwable t) {
calledLock.unlock(); calledLock.unlock();
throw t; throw t;