Fix RenderSourceFileHandler threadPools not closing
Closes #543 (slowdown when moving between dimensions)
This commit is contained in:
+1
-3
@@ -1,8 +1,6 @@
|
||||
package com.seibel.distanthorizons.core.file.renderfile;
|
||||
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.CompleteFullDataSource;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IFullDataSource;
|
||||
import com.seibel.distanthorizons.core.file.metaData.AbstractMetaDataContainerFile;
|
||||
import com.seibel.distanthorizons.core.file.metaData.BaseMetaData;
|
||||
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||
@@ -134,7 +132,7 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
|
||||
});
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> flushAndSave(ExecutorService renderCacheThread)
|
||||
public CompletableFuture<Void> flushAndSaveAsync(ExecutorService renderCacheThread)
|
||||
{
|
||||
if (!this.file.exists())
|
||||
{
|
||||
|
||||
+42
-10
@@ -1,10 +1,8 @@
|
||||
package com.seibel.distanthorizons.core.file.renderfile;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IFullDataSource;
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataMetaFile;
|
||||
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.DhLodPos;
|
||||
@@ -26,7 +24,6 @@ import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@@ -39,7 +36,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
|
||||
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
private final ExecutorService fileHandlerThreadPool = ThreadUtil.makeSingleThreadPool("Render Source File Handler");
|
||||
private final ThreadPoolExecutor fileHandlerThreadPool;
|
||||
|
||||
private final ConcurrentHashMap<DhSectionPos, File> unloadedFiles = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<DhSectionPos, RenderMetaDataFile> filesBySectionPos = new ConcurrentHashMap<>();
|
||||
@@ -47,10 +44,15 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
|
||||
private final IDhClientLevel level;
|
||||
private final File saveDir;
|
||||
/** This is the lowest (highest numeric) detail level that this {@link RenderSourceFileHandler} is keeping track of. */
|
||||
AtomicInteger topDetailLevel = new AtomicInteger(6);
|
||||
AtomicInteger topDetailLevel = new AtomicInteger(DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL);
|
||||
private final IFullDataSourceProvider fullDataSourceProvider;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public RenderSourceFileHandler(IFullDataSourceProvider sourceProvider, IDhClientLevel level, AbstractSaveStructure saveStructure)
|
||||
{
|
||||
this.fullDataSourceProvider = sourceProvider;
|
||||
@@ -60,6 +62,8 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
|
||||
{
|
||||
LOGGER.warn("Unable to create render data folder, file saving may fail.");
|
||||
}
|
||||
this.fileHandlerThreadPool = ThreadUtil.makeSingleThreadPool("Render Source File Handler ["+this.level.getClientLevelWrapper().getDimensionType().getDimensionName()+"]");
|
||||
|
||||
FileScanUtil.scanFiles(saveStructure, level.getLevelWrapper(), null, this);
|
||||
}
|
||||
|
||||
@@ -356,7 +360,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
|
||||
ArrayList<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||
for (RenderMetaDataFile metaFile : this.filesBySectionPos.values())
|
||||
{
|
||||
futures.add(metaFile.flushAndSave(this.fileHandlerThreadPool));
|
||||
futures.add(metaFile.flushAndSaveAsync(this.fileHandlerThreadPool));
|
||||
}
|
||||
|
||||
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
|
||||
@@ -481,15 +485,43 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
|
||||
// clearing / shutdown //
|
||||
//=====================//
|
||||
|
||||
/** closes the handler after any necessary saving has been completed */
|
||||
public CompletableFuture<Void> saveAndCloseAsync()
|
||||
{
|
||||
CompletableFuture<Void> shutdownFuture = this.flushAndSaveAsync();
|
||||
shutdownFuture.whenComplete((voidObj, ex) -> { this.close(); });
|
||||
|
||||
return shutdownFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
LOGGER.info("Closing "+this.getClass().getSimpleName()+" with ["+this.filesBySectionPos.size()+"] files...");
|
||||
|
||||
// queue the file save futures
|
||||
ArrayList<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||
for (RenderMetaDataFile metaFile : this.filesBySectionPos.values())
|
||||
{
|
||||
futures.add(metaFile.flushAndSave(this.fileHandlerThreadPool));
|
||||
futures.add(metaFile.flushAndSaveAsync(this.fileHandlerThreadPool));
|
||||
}
|
||||
|
||||
|
||||
// if the save futures didn't already complete, wait for them and then shut down the thread pool
|
||||
CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
|
||||
combinedFuture.thenRun(() ->
|
||||
{
|
||||
LOGGER.info("Finished closing "+this.getClass().getSimpleName()+", ["+futures.size()+"] files were saved.");
|
||||
this.fileHandlerThreadPool.shutdown();
|
||||
});
|
||||
|
||||
// if the save futures were already completed, the above "thenRun" won't fire,
|
||||
// if the executor isn't currently running anything, shut it down
|
||||
if (!this.fileHandlerThreadPool.isTerminated() && this.fileHandlerThreadPool.getActiveCount() == 0)
|
||||
{
|
||||
LOGGER.info("Finished closing "+this.getClass().getSimpleName()+", thread pool manually shut down due to file save futures already being completed.");
|
||||
this.fileHandlerThreadPool.shutdown();
|
||||
}
|
||||
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -269,7 +269,7 @@ public class ClientLevelModule {
|
||||
|
||||
this.renderer.close();
|
||||
this.quadtree.close();
|
||||
return this.renderSourceFileHandler.flushAndSaveAsync();
|
||||
return this.renderSourceFileHandler.saveAndCloseAsync();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user