diff --git a/loader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/BackgroundScanHandler.java b/loader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/BackgroundScanHandler.java index c148dd08..a2e658af 100644 --- a/loader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/BackgroundScanHandler.java +++ b/loader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/BackgroundScanHandler.java @@ -6,6 +6,7 @@ package net.minecraftforge.fml.loading.moddiscovery; import com.mojang.logging.LogUtils; +import net.minecraftforge.fml.loading.FMLConfig; import net.minecraftforge.fml.loading.ImmediateWindowHandler; import net.minecraftforge.fml.loading.LoadingModList; import net.minecraftforge.fml.loading.LogMarkers; @@ -18,6 +19,7 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; public class BackgroundScanHandler { @@ -41,10 +43,14 @@ private enum ScanStatus { public BackgroundScanHandler(final List modFiles) { this.modFiles = modFiles; - modContentScanner = Executors.newSingleThreadExecutor(r -> { + int maxThreads = FMLConfig.getIntConfigValue(FMLConfig.ConfigValue.MAX_THREADS); + // Leave 1 thread for Minecraft's own bootstrap + int poolSize = Math.max(1, maxThreads - 1); + AtomicInteger threadCount = new AtomicInteger(); + modContentScanner = Executors.newFixedThreadPool(poolSize, r -> { final Thread thread = Executors.defaultThreadFactory().newThread(r); thread.setDaemon(true); - thread.setName("Background Scan Handler"); + thread.setName("background-scan-handler-" + threadCount.getAndIncrement()); return thread; }); scannedFiles = new ArrayList<>(); @@ -72,7 +78,7 @@ public void submitForScanning(final ModFile file) { file.setFutureScanResult(future); } - private void addCompletedFile(final ModFile file, final ModFileScanData modFileScanData, final Throwable throwable) { + private synchronized void addCompletedFile(final ModFile file, final ModFileScanData modFileScanData, final Throwable throwable) { if (throwable != null) { status = ScanStatus.ERRORED; LOGGER.error(LogMarkers.SCAN,"An error occurred scanning file {}", file, throwable); diff --git a/loader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java b/loader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java index f95c4ded..1a8a4f42 100644 --- a/loader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java +++ b/loader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java @@ -57,7 +57,7 @@ public class ModFile implements IModFile { private final IModProvider provider; private IModFileInfo modFileInfo; private ModFileScanData fileModFileScanData; - private CompletableFuture futureScanResult; + private volatile CompletableFuture futureScanResult; private List coreMods; private Path accessTransformer; @@ -152,11 +152,11 @@ public ModFileScanData getScanResult() { } public void setScanResult(final ModFileScanData modFileScanData, final Throwable throwable) { - this.futureScanResult = null; this.fileModFileScanData = modFileScanData; if (throwable != null) { this.scanError = throwable; } + this.futureScanResult = null; } public void setFileProperties(Map fileProperties) { diff --git a/loader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/Scanner.java b/loader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/Scanner.java index 1114da2d..88ae4e9c 100644 --- a/loader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/Scanner.java +++ b/loader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/Scanner.java @@ -34,7 +34,11 @@ public ModFileScanData scan() { if (loaders != null) { loaders.forEach(loader -> { LOGGER.debug(LogMarkers.SCAN, "Scanning {} with language loader {}", fileToScan.getFilePath(), loader.name()); - loader.getFileVisitor().accept(result); + // Since we now scan files concurrently, but language loaders may not have been written with that in mind, + // synchronize on the language loader so it only scans one file at a time + synchronized (loader) { + loader.getFileVisitor().accept(result); + } }); } return result;