Optimize startup and fix shutdown logic
This commit is contained in:
parent
2899ba2e8a
commit
86e85356ba
5 changed files with 86 additions and 44 deletions
|
@ -355,6 +355,20 @@ public final class Engine implements SubsystemMainClass {
|
|||
* @since v1-alpha0
|
||||
*/
|
||||
public synchronized void shutdown(@Range(from = 0, to = 255) int exitCode) {
|
||||
if (shuttingDown) {
|
||||
logger.error("Already shutting down");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make engine single-threaded
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("sosengine.base.optimizeLogging", "false");
|
||||
properties.setProperty("sosengine.base.optimizeEvents", "false");
|
||||
EngineConfiguration.getInstance().loadConfiguration(properties);
|
||||
|
||||
// Flush log messages
|
||||
Logger.flushLogMessages();
|
||||
|
||||
logger.info("Shutting engine down");
|
||||
shuttingDown = true;
|
||||
|
||||
|
@ -365,10 +379,18 @@ public final class Engine implements SubsystemMainClass {
|
|||
new InternalEngineShutdownEvent().callEvent();
|
||||
|
||||
logger.verb("Shutting down JVM with code " + exitCode);
|
||||
Logger.flushLogMessages(); // Flush all log messages before exiting
|
||||
Runtime.getRuntime().exit(exitCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts the engine and JVM down.
|
||||
*
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
public void shutdown() {
|
||||
shutdown(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -393,13 +415,4 @@ public final class Engine implements SubsystemMainClass {
|
|||
public DependencyVector getDependencyVector() {
|
||||
return new DependencyVector("engine", StarOpenSourceVersioningSystem.class, EngineInformation.getVersioningString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts the engine and JVM down.
|
||||
*
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
public synchronized void shutdown() {
|
||||
shutdown(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -298,7 +298,8 @@ public final class EngineConfiguration implements SubsystemConfiguration {
|
|||
// Loop through all properties
|
||||
for (String property : properties.stringPropertyNames()) {
|
||||
// Check if property name starts with group
|
||||
if (!property.startsWith(group)) continue;
|
||||
if (!property.startsWith(group))
|
||||
continue;
|
||||
|
||||
// Skip to important stuff
|
||||
property = property.substring(group.length());
|
||||
|
|
|
@ -20,18 +20,17 @@
|
|||
package de.staropensource.sosengine.graphics.glfw;
|
||||
|
||||
import de.staropensource.sosengine.base.annotations.EngineSubsystem;
|
||||
import de.staropensource.sosengine.base.annotations.EventListener;
|
||||
import de.staropensource.sosengine.base.classes.SubsystemMainClass;
|
||||
import de.staropensource.sosengine.base.data.info.EngineInformation;
|
||||
import de.staropensource.sosengine.base.data.versioning.StarOpenSourceVersioningSystem;
|
||||
import de.staropensource.sosengine.base.internal.events.InternalEngineShutdownEvent;
|
||||
import de.staropensource.sosengine.base.logging.LoggerInstance;
|
||||
import de.staropensource.sosengine.base.types.CodePart;
|
||||
import de.staropensource.sosengine.base.types.DependencyVector;
|
||||
import de.staropensource.sosengine.base.types.EventPriority;
|
||||
import de.staropensource.sosengine.base.types.logging.LogIssuer;
|
||||
import de.staropensource.sosengine.base.utility.Miscellaneous;
|
||||
import de.staropensource.sosengine.graphics.glfw.events.GraphicsErrorEvent;
|
||||
import de.staropensource.sosengine.graphics.glfw.exceptions.GlfwInitializationException;
|
||||
import de.staropensource.sosengine.graphics.glfw.exceptions.NotOnMainThreadException;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFWErrorCallback;
|
||||
|
@ -70,6 +69,15 @@ public class GlfwSubsystem implements SubsystemMainClass {
|
|||
*/
|
||||
private final LoggerInstance logger = new LoggerInstance(new LogIssuer(getClass(), CodePart.ENGINE));
|
||||
|
||||
/**
|
||||
* The {@link GLFWErrorCallback} to use.
|
||||
* <p>
|
||||
* Only declared publicly for freeing during engine shutdown.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
private final GLFWErrorCallback errorCallback = GLFWErrorCallback.create(new GraphicsErrorEvent());
|
||||
|
||||
/**
|
||||
* Constructs this subsystem.
|
||||
*
|
||||
|
@ -107,11 +115,16 @@ public class GlfwSubsystem implements SubsystemMainClass {
|
|||
* @since v1-alpha2
|
||||
*/
|
||||
public void initializeGlfw() {
|
||||
// Set error callback
|
||||
try (GLFWErrorCallback errorCallback = GLFWErrorCallback.create(new GraphicsErrorEvent())) {
|
||||
errorCallback.set();
|
||||
logger.verb("Initializing GLFW");
|
||||
|
||||
if (!Miscellaneous.onMainThread()) {
|
||||
logger.crash("Unable to initialize GLFW on a non-main thread", new NotOnMainThreadException(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set error callback
|
||||
errorCallback.set();
|
||||
|
||||
// Initialize GLFW
|
||||
if (!glfwInit())
|
||||
throw new GlfwInitializationException();
|
||||
|
@ -125,19 +138,12 @@ public class GlfwSubsystem implements SubsystemMainClass {
|
|||
public void terminateGlfw() {
|
||||
logger.verb("Terminating GLFW");
|
||||
|
||||
glfwTerminate();
|
||||
//noinspection DataFlowIssue,resource
|
||||
glfwSetErrorCallback(null).free();
|
||||
}
|
||||
if (!Miscellaneous.onMainThread()) {
|
||||
logger.crash("Unable to terminate GLFW on a non-main thread. Did you call Engine#shutdown or Logger#crash from another thread?", new NotOnMainThreadException(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the engine shuts down.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@EventListener(event = InternalEngineShutdownEvent.class, priority = EventPriority.EXTREMELY_UNIMPORTANT)
|
||||
private static void shutdownApiFromEvent() {
|
||||
if (instance != null)
|
||||
instance.terminateGlfw();
|
||||
glfwTerminate();
|
||||
errorCallback.free();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import de.staropensource.sosengine.base.internal.events.InternalEngineShutdownEv
|
|||
import de.staropensource.sosengine.base.logging.LoggerInstance;
|
||||
import de.staropensource.sosengine.base.types.CodePart;
|
||||
import de.staropensource.sosengine.base.types.DependencyVector;
|
||||
import de.staropensource.sosengine.base.types.EventPriority;
|
||||
import de.staropensource.sosengine.base.types.logging.LogIssuer;
|
||||
import de.staropensource.sosengine.base.utility.ListFormatter;
|
||||
import de.staropensource.sosengine.base.utility.Miscellaneous;
|
||||
|
@ -161,12 +160,17 @@ public final class GraphicsSubsystem implements SubsystemMainClass {
|
|||
*
|
||||
* @since v1-alpha0
|
||||
*/
|
||||
@EventListener(event = InternalEngineShutdownEvent.class, priority = EventPriority.EXTREMELY_UNIMPORTANT)
|
||||
public static void shutdown() {
|
||||
@EventListener(event = InternalEngineShutdownEvent.class)
|
||||
private static void shutdown() {
|
||||
LoggerInstance logger = instance.logger;
|
||||
logger.verb("Shutting down");
|
||||
|
||||
long shutdownTime = Miscellaneous.measureExecutionTime(() -> new GraphicsApiShutdownEvent().callEvent());
|
||||
long shutdownTime = Miscellaneous.measureExecutionTime(() -> {
|
||||
new GraphicsApiShutdownEvent().callEvent();
|
||||
|
||||
if (instance.api != null)
|
||||
instance.api.shutdownApi();
|
||||
});
|
||||
|
||||
logger.info("Shut down in " + shutdownTime + "ms");
|
||||
}
|
||||
|
@ -201,7 +205,7 @@ public final class GraphicsSubsystem implements SubsystemMainClass {
|
|||
// Check if registered apis are compatible
|
||||
for (String apiName : registeredApis.keySet())
|
||||
if (registeredApis.get(apiName).isCompatible()) {
|
||||
logger.diag("" + apiName + " is compatible");
|
||||
logger.diag(apiName + " is compatible");
|
||||
compatibleApis.add(apiName);
|
||||
} else
|
||||
logger.diag(apiName + " is not compatible");
|
||||
|
|
|
@ -20,16 +20,20 @@
|
|||
package de.staropensource.sosengine.testapp;
|
||||
|
||||
import de.staropensource.sosengine.base.Engine;
|
||||
import de.staropensource.sosengine.base.annotations.EventListener;
|
||||
import de.staropensource.sosengine.base.events.ThrowableCatchEvent;
|
||||
import de.staropensource.sosengine.base.logging.LoggerInstance;
|
||||
import de.staropensource.sosengine.base.types.CodePart;
|
||||
import de.staropensource.sosengine.base.types.logging.LogIssuer;
|
||||
import de.staropensource.sosengine.base.types.vectors.Vec2i;
|
||||
import de.staropensource.sosengine.base.utility.Miscellaneous;
|
||||
import de.staropensource.sosengine.graphics.GraphicsSubsystem;
|
||||
import de.staropensource.sosengine.graphics.classes.ApiMainClass;
|
||||
import de.staropensource.sosengine.graphics.classes.ApiManagementClass;
|
||||
import de.staropensource.sosengine.graphics.classes.Window;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* The initialization class for sos!engine's development application.
|
||||
|
@ -78,7 +82,7 @@ public class Main {
|
|||
|
||||
/**
|
||||
* The program's entrypoint.
|
||||
* Calls {@code run()} after invocation.
|
||||
* Calls {@link #run(String[])} after invocation.
|
||||
*
|
||||
* @see Main#run(String[])
|
||||
* @param args program's command line arguments
|
||||
|
@ -88,15 +92,15 @@ public class Main {
|
|||
}
|
||||
|
||||
/**
|
||||
* The program's entrypoint but not static.
|
||||
* Here's where the "real magic" happens-
|
||||
* The program's entrypoint except it's not static.
|
||||
* Here's where the "real magic" happens.
|
||||
*
|
||||
* @see Main#main(String[])
|
||||
* @param args program's command line arguments
|
||||
*/
|
||||
@SneakyThrows
|
||||
public void run(String[] args) {
|
||||
try {
|
||||
Miscellaneous.executeSafely(() -> {
|
||||
// Initialize sos!engine
|
||||
engine = new Engine();
|
||||
|
||||
|
@ -124,13 +128,27 @@ public class Main {
|
|||
}
|
||||
|
||||
// Sleep for five seconds
|
||||
Thread.sleep(5000);
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException exception) {
|
||||
logger.crash("Was unable to sleep for 5000ms", exception);
|
||||
}
|
||||
|
||||
// Shutdown
|
||||
Engine.getInstance().shutdown(0);
|
||||
} catch (Throwable throwable) {
|
||||
Thread.ofVirtual().start(() -> Engine.getInstance().shutdown(69));
|
||||
throw throwable;
|
||||
Engine.getInstance().shutdown();
|
||||
}, "mainThread");
|
||||
}
|
||||
|
||||
/**
|
||||
* Crashes the application when a throwable
|
||||
* is thrown in {@link #run(String[])}.
|
||||
*
|
||||
* @since v1-alpha2
|
||||
*/
|
||||
@EventListener(event = ThrowableCatchEvent.class)
|
||||
public static void onThrowable(@NotNull Throwable throwable, @NotNull String identifier) {
|
||||
if (identifier.equals("mainThread")) {
|
||||
instance.logger.crash("The main thread threw an exception", throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue