From 35f5bce14939606d9301fc722a73a2b0fd713081 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 20 Aug 2023 17:59:58 -0500 Subject: [PATCH] Clean up World Gen Threads after termination --- .../core/generation/WorldGenerationQueue.java | 12 +++++++++-- .../RateLimitedThreadPoolExecutor.java | 21 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java index 68eac6257..20338b160 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java @@ -18,6 +18,7 @@ import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable; import com.seibel.distanthorizons.core.util.ThreadUtil; import com.seibel.distanthorizons.core.util.objects.DhThreadFactory; +import com.seibel.distanthorizons.core.util.objects.RateLimitedThreadPoolExecutor; import com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; @@ -34,7 +35,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public static final DhThreadFactory THREAD_FACTORY = new DhThreadFactory(ThreadUtil.THREAD_NAME_PREFIX + "Gen-Worker-Thread", Thread.MIN_PRIORITY); + public static final DhThreadFactory THREAD_FACTORY = new DhThreadFactory(ThreadUtil.THREAD_NAME_PREFIX + "World-Gen-Worker-Thread", Thread.MIN_PRIORITY); private final IDhApiWorldGenerator generator; @@ -73,7 +74,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable private final HashMap alreadyGeneratedPosHashSet = new HashMap<>(MAX_ALREADY_GENERATED_COUNT); private final Queue alreadyGeneratedPosQueue = new LinkedList<>(); - private static ExecutorService worldGeneratorThreadPool; + private static RateLimitedThreadPoolExecutor worldGeneratorThreadPool; private static ConfigChangeListener configListener; @@ -527,6 +528,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable } worldGeneratorThreadPool = ThreadUtil.makeRateLimitedThreadPool(threadPoolSize, THREAD_FACTORY, Config.Client.Advanced.MultiThreading.runTimeRatioForWorldGenerationThreads); + worldGeneratorThreadPool.setOnTerminatedEventHandler(WorldGenerationQueue::onWorldGenThreadPoolTerminated); } /** @@ -542,6 +544,12 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable } } + private static void onWorldGenThreadPoolTerminated() + { + LOGGER.debug("World generator thread pool terminated. Suggesting the JVM runs a garbage collection to clean up any loose world generation objects..."); + System.gc(); + } + //=========// diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/RateLimitedThreadPoolExecutor.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/RateLimitedThreadPoolExecutor.java index a732842f9..ee77c442c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/RateLimitedThreadPoolExecutor.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/RateLimitedThreadPoolExecutor.java @@ -15,6 +15,8 @@ public class RateLimitedThreadPoolExecutor extends ThreadPoolExecutor /** How long it took this thread to run its last task */ private final ThreadLocal lastRunDurationNanoTimeRef = ThreadLocal.withInitial(() -> -1L); + private Runnable onTerminatedEventHandler = null; + //==============// @@ -63,4 +65,23 @@ public class RateLimitedThreadPoolExecutor extends ThreadPoolExecutor this.lastRunDurationNanoTimeRef.set(System.nanoTime() - this.runStartNanoTimeRef.get()); } + @Override + protected void terminated() + { + super.terminated(); + if (this.onTerminatedEventHandler != null) + { + this.onTerminatedEventHandler.run(); + } + } + + + + //==============// + // custom logic // + //==============// + + /** only one event handler can be present at a time */ + public void setOnTerminatedEventHandler(Runnable runnable) { this.onTerminatedEventHandler = runnable; } + } \ No newline at end of file