From ed596955f732530784f087d56c1cd6c9dd386829 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 3 Sep 2023 17:42:47 -0500 Subject: [PATCH] Remove CacheQueryResult from RenderMetaDataFile --- .../file/renderfile/RenderMetaDataFile.java | 66 ++++++------------- 1 file changed, 20 insertions(+), 46 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderMetaDataFile.java b/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderMetaDataFile.java index 764cd00d3..a606e20c3 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderMetaDataFile.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderMetaDataFile.java @@ -174,16 +174,27 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements public CompletableFuture getOrLoadCachedDataSourceAsync(Executor fileReaderThreads, IDhLevel level) { - CacheQueryResult cacheQueryResult = this.getOrStartCachedDataSourceAsync(); - if (cacheQueryResult.cacheQueryAlreadyInProcess) + CompletableFuture renderSourceLoadFuture = this.getCachedDataSourceAsync(true); + if (renderSourceLoadFuture != null) { // return the in-process future - return cacheQueryResult.future; + return renderSourceLoadFuture; + } + else + { + // there is no cached data, we'll have to load it + + renderSourceLoadFuture = new CompletableFuture<>(); + if (!this.renderSourceLoadFutureRef.compareAndSet(null, renderSourceLoadFuture)) + { + // two threads attempted to start this job at the same time, only use the first future + renderSourceLoadFuture = this.renderSourceLoadFutureRef.get(); + } } - CompletableFuture getSourceFuture = cacheQueryResult.future; + final CompletableFuture getSourceFuture = renderSourceLoadFuture; if (!this.doesFileExist) { // create a new Meta file and render source @@ -256,27 +267,6 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements return getSourceFuture; } - // TODO why is this being used vs just // this.getCachedDataSourceAsync(true); ? - private CacheQueryResult getOrStartCachedDataSourceAsync() - { - CompletableFuture renderSourceLoadFuture = this.getCachedDataSourceAsync(true); - if (renderSourceLoadFuture != null) - { - // return the existing load future - return new CacheQueryResult(renderSourceLoadFuture, true); - } - else - { - // Create a new future if one doesn't already exist - CompletableFuture newFuture = new CompletableFuture<>(); - CompletableFuture oldFuture = AtomicsUtil.compareAndExchange(this.renderSourceLoadFutureRef, null, newFuture); - - CompletableFuture activeFuture = (oldFuture == null) ? newFuture : oldFuture; - // if a loading future is already active we don't need to trigger another load - boolean cacheQueryAlreadyInProcess = (oldFuture != null); - return new CacheQueryResult(activeFuture, cacheQueryAlreadyInProcess); - } - } private FileInputStream getFileInputStream() throws IOException { FileInputStream inputStream = new FileInputStream(this.file); @@ -473,10 +463,11 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements // helper methods // //================// + /** @return returns null if {@link RenderMetaDataFile#renderSourceLoadFutureRef} is empty and no cached {@link ColumnRenderSource} exists. */ @Nullable private CompletableFuture getCachedDataSourceAsync(boolean triggerAndWaitForListener) { - // use the existing future + // check if another thread is already loading the data source CompletableFuture renderSourceLoadFuture = this.renderSourceLoadFutureRef.get(); if (renderSourceLoadFuture != null) { @@ -488,10 +479,13 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements ColumnRenderSource cachedRenderDataSource = this.cachedRenderDataSource.get(); if (cachedRenderDataSource == null) { + // no cached data exists and no one is trying to load it return null; } else { + // cached data exists + if (!triggerAndWaitForListener) { // immediately return the render source @@ -524,24 +518,4 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements } } - - - //================// - // helper classes // - //================// - - /** TODO couldn't this just be made into an atomic future or something? */ - private static final class CacheQueryResult - { - public final CompletableFuture future; - public final boolean cacheQueryAlreadyInProcess; - - public CacheQueryResult(CompletableFuture future, boolean cacheQueryAlreadyInProcess) - { - this.future = future; - this.cacheQueryAlreadyInProcess = cacheQueryAlreadyInProcess; - } - - } - }