From b9092149744d609b289eb369c719ed67430a3c15 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 21 Nov 2024 17:21:14 -0600 Subject: [PATCH 1/2] Fix caught null pointer --- .../seibel/distanthorizons/core/render/LodRenderSection.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java index 7e4bb84fc..4ff96f6e0 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java @@ -272,7 +272,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable } this.bufferUploadFuture = ColumnRenderBufferBuilder.uploadBuffersAsync(this.level, this.pos, lodQuadBuilder); - return this.bufferUploadFuture.thenCompose((buffer) -> + return this.bufferUploadFuture.thenAccept((buffer) -> { // needed to clean up the old data ColumnRenderBuffer previousBuffer = this.renderBuffer; @@ -286,8 +286,6 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable { previousBuffer.close(); } - - return null; }); } From 7455893ef8bea2e15dc6c516113ed53094ac67ea Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 21 Nov 2024 19:00:27 -0600 Subject: [PATCH 2/2] Fix race condition in LodRenderSection loading --- .../core/render/LodRenderSection.java | 55 ++++++++++++++----- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java index 4ff96f6e0..daa9b4fa1 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java @@ -334,9 +334,8 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable // use the already loading future if one is present ReferencedRenderSourceFutureWrapper oldFuture = this.renderSourceLoadingRefFuture; - if (oldFuture != null) + if (oldFuture != null && oldFuture.tryIncrementRefCount()) { - oldFuture.incrementRefCount(); return oldFuture; } @@ -642,23 +641,49 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable public ReferencedRenderSourceFutureWrapper(CompletableFuture future) { this.future = future; } - public void incrementRefCount() { this.refCount.incrementAndGet(); } + + + /** @return true if this {@link ReferencedRenderSourceFutureWrapper} can be acquired, false if it has already been freed */ + public boolean tryIncrementRefCount() + { + // synchronized to prevent incrementing/decrementing at the same time + synchronized (this.refCount) + { + int refCount = this.refCount.get(); + if (refCount <= 0) + { + // there are no references to this data source and it has been returned to the pool + // a new reference will be needed + return false; + } + else + { + // at least one other + this.refCount.getAndIncrement(); + return true; + } + } + } public void decrementRefCount() { - int refCount = this.refCount.decrementAndGet(); - if (refCount <= 0) + // synchronized to prevent incrementing/decrementing at the same time + synchronized (this.refCount) { - // this render section should only be released once - if (refCount < 0) + int refCount = this.refCount.decrementAndGet(); + if (refCount <= 0) { - LodUtil.assertNotReach("ReferencedRenderSourceFutureWrapper was released more than once! Ref Count ["+refCount+"]."); - } - - // return data source to the pool - ColumnRenderSource source = this.future.getNow(null); - if (source != null) - { - ColumnRenderSource.DATA_SOURCE_POOL.returnPooledDataSource(source); + // this should only be released once + if (refCount < 0) + { + LodUtil.assertNotReach("ReferencedRenderSourceFutureWrapper was released more than once! Ref Count [" + refCount + "]."); + } + + // return data source to the pool + ColumnRenderSource source = this.future.getNow(null); + if (source != null) + { + ColumnRenderSource.DATA_SOURCE_POOL.returnPooledDataSource(source); + } } } }