From 7f7ff1adc454152f8a301fa176dde0951def3a11 Mon Sep 17 00:00:00 2001 From: Richard Maw Date: Tue, 28 Jan 2025 21:24:06 +0000 Subject: [PATCH] Load assets in parallel The getAssetAsynchronous method uses a thread pool so that requests to load assets don't block networking threads etc. It has been a single thread pool through the existing git history but it is assumed that it is like this because it used to have a thread and then was converted to use a single thread fixed thread pool. Unfortunately having a single thread only means that if an asset load callback indirectly loads another asset then this can deadlock since the asset loader thread needs to be released before the load request can start, which it can't because that thread is waiting for the result of loading the new asset, thus it deadlocks if an AddOn includes a JavaScript onInit script since it deadlocks waiting to load that script. Changing the thread pool so that the threads load in parallel is an observable change that could cause problems, but if the AddOn isn't already loaded the addonLoader's thread pool loads it instead and that works fine, so MapTool should be alright with addons and other assets loading in parallel. --- src/main/java/net/rptools/maptool/model/AssetManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/rptools/maptool/model/AssetManager.java b/src/main/java/net/rptools/maptool/model/AssetManager.java index 8612202200..bf44066b95 100644 --- a/src/main/java/net/rptools/maptool/model/AssetManager.java +++ b/src/main/java/net/rptools/maptool/model/AssetManager.java @@ -39,6 +39,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.ForkJoinPool; import net.rptools.lib.FileUtil; import net.rptools.lib.MD5Key; import net.rptools.maptool.client.AppUtil; @@ -90,7 +91,7 @@ public class AssetManager { /** Used to load assets from storage */ private static AssetLoader assetLoader = new AssetLoader(); - private static ExecutorService assetLoaderThreadPool = Executors.newFixedThreadPool(1); + private static ExecutorService assetLoaderThreadPool = ForkJoinPool.commonPool(); private static ExecutorService assetWriterThreadPool = Executors.newFixedThreadPool(1); static {