Fix & complete automatic subsystem initialization

This commit is contained in:
JeremyStar™ 2024-07-07 12:55:56 +02:00
parent 3e167ac260
commit ecf0f94784
Signed by: JeremyStarTM
GPG key ID: E366BAEF67E4704D
6 changed files with 65 additions and 28 deletions

View file

@ -47,10 +47,7 @@ import org.reflections.scanners.Scanners;
import org.reflections.util.ClasspathHelper; import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder; import org.reflections.util.ConfigurationBuilder;
import java.util.HashMap; import java.util.*;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/** /**
* sos!engine management object.<br/> * sos!engine management object.<br/>
@ -98,7 +95,7 @@ public final class Engine implements SubsystemMainClass {
*/ */
@NotNull @NotNull
@Getter @Getter
private ImmutableMap<@NotNull Class<? extends SubsystemMainClass>, @NotNull DependencyVector> subsystems = new ImmutableMap<>(); private ImmutableMap<@NotNull SubsystemMainClass, @NotNull DependencyVector> subsystems = new ImmutableMap<>();
/** /**
* Indicates if the engine is shutting down. * Indicates if the engine is shutting down.
@ -115,7 +112,7 @@ public final class Engine implements SubsystemMainClass {
private boolean shuttingDown = false; private boolean shuttingDown = false;
/** /**
* Constructor, initializes the StarOpenSource Engine. * Initializes the StarOpenSource Engine.
* *
* @since 1-alpha0 * @since 1-alpha0
*/ */
@ -153,7 +150,7 @@ public final class Engine implements SubsystemMainClass {
try { try {
initializeSubsystems(); initializeSubsystems();
} catch (Exception exception) { } catch (Exception exception) {
logger.crash("Subsystem dependency resolution failed"); logger.crash("Subsystem dependency resolution failed", exception);
} }
}); });
@ -252,9 +249,9 @@ public final class Engine implements SubsystemMainClass {
* @since 1-alpha1 * @since 1-alpha1
*/ */
private void collectSubsystems() { private void collectSubsystems() {
Map<@NotNull Class<? extends SubsystemMainClass>, @NotNull DependencyVector> subsystemsMap = new HashMap<>(); Map<@NotNull SubsystemMainClass, @NotNull DependencyVector> subsystemsMap = new HashMap<>();
// Scan entire classpath through Reflections library // Scan entire classpath using the Reflections library
Reflections reflections = new Reflections( Reflections reflections = new Reflections(
new ConfigurationBuilder() new ConfigurationBuilder()
.setUrls(ClasspathHelper.forJavaClassPath()) .setUrls(ClasspathHelper.forJavaClassPath())
@ -264,16 +261,27 @@ public final class Engine implements SubsystemMainClass {
// Get annotated methods // Get annotated methods
Set<@NotNull Class<?>> annotatedClasses = reflections.getTypesAnnotatedWith(EngineSubsystem.class); Set<@NotNull Class<?>> annotatedClasses = reflections.getTypesAnnotatedWith(EngineSubsystem.class);
// Add to 'subsystemsMap' // Initialize class, get dependency vector and add to 'subsystemsMap'
for (Class<?> clazz : annotatedClasses) { for (Class<?> clazz : annotatedClasses) {
try { try {
//noinspection unchecked // Create new instance
subsystemsMap.put((Class<? extends SubsystemMainClass>) clazz, (DependencyVector) clazz.getMethod("getDependencyVector").invoke(null)); Object initializedClassRaw = clazz.getDeclaredConstructor().newInstance();
} catch (Exception ignored) {} SubsystemMainClass initializedClass = null;
// Check if class implements SubsystemMainClass
if (initializedClassRaw instanceof SubsystemMainClass subsystemInstance)
initializedClass = subsystemInstance;
else
logger.crash("Failed to initialize subsystem " + clazz.getName() + ": Does not implement " + SubsystemMainClass.class.getName());
subsystemsMap.put(Objects.requireNonNull(initializedClass), initializedClass.getDependencyVector());
} catch (Exception exception) {
logger.crash("Failed to initialize subsystem " + clazz.getName() + ": Method invocation error", exception);
}
} }
// Remove null values // Remove entries with null values
for (Class<? extends SubsystemMainClass> subsystem : subsystemsMap.keySet()) for (SubsystemMainClass subsystem : subsystemsMap.keySet())
if (subsystemsMap.get(subsystem) == null) if (subsystemsMap.get(subsystem) == null)
subsystemsMap.remove(subsystem); subsystemsMap.remove(subsystem);
@ -287,22 +295,25 @@ public final class Engine implements SubsystemMainClass {
* @since 1-alpha1 * @since 1-alpha1
*/ */
private void initializeSubsystems() throws Exception { private void initializeSubsystems() throws Exception {
logger.verb("Preparing subsystem initialization");
DependencyResolver resolver = new DependencyResolver(); DependencyResolver resolver = new DependencyResolver();
for (Class<? extends SubsystemMainClass> subsystem : subsystems.keySet()) for (SubsystemMainClass subsystem : subsystems.keySet())
resolver.addVector(subsystems.get(subsystem)); resolver.addVector(subsystems.get(subsystem));
/* logger.diag("Resolving dependencies");
try { try {
resolver.resolve(); resolver.resolve();
} catch (Exception exception) { } catch (Exception exception) {
logger.crash("An error occurred trying to initialize engine subsystems: " + exception.getClass().getName() + (exception.getMessage() == null ? "" : ": " + exception.getMessage())); logger.crash("An error occurred trying to initialize engine subsystems: " + exception.getClass().getName() + (exception.getMessage() == null ? "" : ": " + exception.getMessage()));
throw exception; throw exception;
} }
*/
for (Class<? extends SubsystemMainClass> subsystem : subsystems.keySet()) logger.info("Initializing engine subsystems");
subsystem.getDeclaredConstructor().newInstance(); for (SubsystemMainClass subsystem : subsystems.keySet()) {
logger.verb("Initializing subsystem " + subsystem.getClass().getName());
subsystem.initializeSubsystem();
}
} }
/** /**
@ -335,6 +346,10 @@ public final class Engine implements SubsystemMainClass {
Runtime.getRuntime().exit(exitCode); Runtime.getRuntime().exit(exitCode);
} }
/** {@inheritDoc} */
@Override
public void initializeSubsystem() {}
/** /**
* Returns the {@link DependencyVector} for this subsystem. * Returns the {@link DependencyVector} for this subsystem.
* *

View file

@ -40,6 +40,13 @@ public interface SubsystemMainClass {
*/ */
LoggerInstance logger = null; LoggerInstance logger = null;
/**
* Initializes this subsystem.
*
* @since 1-alpha1
*/
void initializeSubsystem();
/** /**
* Returns the {@link DependencyVector} for this subsystem. * Returns the {@link DependencyVector} for this subsystem.
* *

View file

@ -95,7 +95,11 @@ public final class OpenGlSubsystem implements ApiMainClass {
else { else {
instance.logger.crash("The subsystem tried to initialize twice"); instance.logger.crash("The subsystem tried to initialize twice");
} }
}
/** {@inheritDoc} */
@Override
public void initializeSubsystem() {
long initTime = Miscellaneous.measureExecutionTime(() -> { long initTime = Miscellaneous.measureExecutionTime(() -> {
// Precompute event listeners // Precompute event listeners
EventHelper.precomputeEventListeners(GraphicsErrorEvent.class); EventHelper.precomputeEventListeners(GraphicsErrorEvent.class);
@ -104,7 +108,7 @@ public final class OpenGlSubsystem implements ApiMainClass {
GraphicsSubsystem.getInstance().registerGraphicsApi(this); GraphicsSubsystem.getInstance().registerGraphicsApi(this);
}); });
logger.info("Initialized subsystem in " + initTime + "ms"); logger.verb("Initialized subsystem in " + initTime + "ms");
} }
/** {@inheritDoc} */ /** {@inheritDoc} */

View file

@ -120,9 +120,11 @@ public final class GraphicsSubsystem implements SubsystemMainClass {
instance.logger.crash("Graphics subsystem tried to initialize twice"); instance.logger.crash("Graphics subsystem tried to initialize twice");
return; return;
} }
}
logger.verb("Initializing subsystem"); /** {@inheritDoc} */
@Override
public void initializeSubsystem() {
long initTime = Miscellaneous.measureExecutionTime(() -> { long initTime = Miscellaneous.measureExecutionTime(() -> {
// Initialize GraphicsSubsystemConfiguration and load it // Initialize GraphicsSubsystemConfiguration and load it
new GraphicsSubsystemConfiguration(); new GraphicsSubsystemConfiguration();
@ -132,7 +134,7 @@ public final class GraphicsSubsystem implements SubsystemMainClass {
precomputeEventListeners(); precomputeEventListeners();
}); });
logger.info("Initialized subsystem in " + initTime + "ms"); logger.verb("Initialized subsystem in " + initTime + "ms");
} }
/** /**

View file

@ -93,7 +93,11 @@ public final class VulkanSubsystem implements ApiMainClass {
instance.logger.crash("The subsystem tried to initialize twice"); instance.logger.crash("The subsystem tried to initialize twice");
return; return;
} }
}
/** {@inheritDoc} */
@Override
public void initializeSubsystem() {
long initTime = Miscellaneous.measureExecutionTime(() -> { long initTime = Miscellaneous.measureExecutionTime(() -> {
// Warn about instability // Warn about instability
logger.warn("The Vulkan Graphics API is in an unfinished state. Trying to initialize the Graphics API will cause an engine crash."); logger.warn("The Vulkan Graphics API is in an unfinished state. Trying to initialize the Graphics API will cause an engine crash.");
@ -102,7 +106,7 @@ public final class VulkanSubsystem implements ApiMainClass {
GraphicsSubsystem.getInstance().registerGraphicsApi(this); GraphicsSubsystem.getInstance().registerGraphicsApi(this);
}); });
logger.info("Initialized subsystem in " + initTime + "ms"); logger.verb("Initialized subsystem in " + initTime + "ms");
} }
/** {@inheritDoc} */ /** {@inheritDoc} */

View file

@ -28,6 +28,7 @@ import de.staropensource.sosengine.base.events.LogEvent;
import de.staropensource.sosengine.base.logging.LoggerInstance; import de.staropensource.sosengine.base.logging.LoggerInstance;
import de.staropensource.sosengine.base.types.CodePart; import de.staropensource.sosengine.base.types.CodePart;
import de.staropensource.sosengine.base.types.DependencyVector; import de.staropensource.sosengine.base.types.DependencyVector;
import de.staropensource.sosengine.base.utility.Miscellaneous;
import lombok.Getter; import lombok.Getter;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -66,11 +67,15 @@ public class Slf4jCompatibilitySubsystem implements SubsystemMainClass {
instance = this; instance = this;
else { else {
instance.logger.crash("The subsystem tried to initialize twice"); instance.logger.crash("The subsystem tried to initialize twice");
return;
} }
}
LoggerFactory.getLogger(CompatibilityLogger.class).debug("If you see this then the SLF4J Compatibility Subsystem is working!"); /** {@inheritDoc} */
logger.info("Initialized subsystem"); @Override
public void initializeSubsystem() {
logger.verb("Initialized subsystem in " +
Miscellaneous.measureExecutionTime(() -> LoggerFactory.getLogger(CompatibilityLogger.class).debug("If you see this then the SLF4J Compatibility Subsystem is working!"))
+ "ms");
} }
/** {@inheritDoc} */ /** {@inheritDoc} */