Move logging thread-related stuff into separate class
This commit is contained in:
parent
390a5cd227
commit
21973ffe6c
4 changed files with 132 additions and 60 deletions
|
@ -344,7 +344,7 @@ public final class Engine extends SubsystemClass {
|
||||||
public void startThreads() {
|
public void startThreads() {
|
||||||
logger.diag("Starting threads");
|
logger.diag("Starting threads");
|
||||||
|
|
||||||
Logger.startLoggingThread();
|
LoggingThread.startLoggingThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,6 +24,7 @@ import de.staropensource.sosengine.base.implementable.Configuration;
|
||||||
import de.staropensource.sosengine.base.implementable.helper.EventHelper;
|
import de.staropensource.sosengine.base.implementable.helper.EventHelper;
|
||||||
import de.staropensource.sosengine.base.logging.CrashHandler;
|
import de.staropensource.sosengine.base.logging.CrashHandler;
|
||||||
import de.staropensource.sosengine.base.logging.Logger;
|
import de.staropensource.sosengine.base.logging.Logger;
|
||||||
|
import de.staropensource.sosengine.base.logging.LoggingThread;
|
||||||
import de.staropensource.sosengine.base.type.EngineState;
|
import de.staropensource.sosengine.base.type.EngineState;
|
||||||
import de.staropensource.sosengine.base.type.logging.LogLevel;
|
import de.staropensource.sosengine.base.type.logging.LogLevel;
|
||||||
import de.staropensource.sosengine.base.type.vector.Vec2f;
|
import de.staropensource.sosengine.base.type.vector.Vec2f;
|
||||||
|
@ -327,7 +328,7 @@ public final class EngineConfiguration extends Configuration {
|
||||||
|
|
||||||
// Start logging thread automatically
|
// Start logging thread automatically
|
||||||
if (optimizeLogging && Engine.getInstance().getState() == EngineState.RUNNING)
|
if (optimizeLogging && Engine.getInstance().getState() == EngineState.RUNNING)
|
||||||
Logger.startLoggingThread();
|
LoggingThread.startLoggingThread();
|
||||||
}
|
}
|
||||||
case "optimizeEvents" -> optimizeEvents = parser.getBoolean(group + property);
|
case "optimizeEvents" -> optimizeEvents = parser.getBoolean(group + property);
|
||||||
case "optimizeSubsystemInitialization" -> optimizeSubsystemInitialization = parser.getBoolean(group + property);
|
case "optimizeSubsystemInitialization" -> optimizeSubsystemInitialization = parser.getBoolean(group + property);
|
||||||
|
|
|
@ -21,18 +21,17 @@ package de.staropensource.sosengine.base.logging;
|
||||||
|
|
||||||
import de.staropensource.sosengine.base.Engine;
|
import de.staropensource.sosengine.base.Engine;
|
||||||
import de.staropensource.sosengine.base.EngineConfiguration;
|
import de.staropensource.sosengine.base.EngineConfiguration;
|
||||||
|
import de.staropensource.sosengine.base.event.LogEvent;
|
||||||
import de.staropensource.sosengine.base.implementable.LoggingAdapter;
|
import de.staropensource.sosengine.base.implementable.LoggingAdapter;
|
||||||
import de.staropensource.sosengine.base.implementable.helper.EventHelper;
|
import de.staropensource.sosengine.base.implementable.helper.EventHelper;
|
||||||
import de.staropensource.sosengine.base.event.LogEvent;
|
import de.staropensource.sosengine.base.implementation.logging.PlainLoggingAdapter;
|
||||||
|
import de.staropensource.sosengine.base.implementation.shortcode.EmptyShortcodeConverter;
|
||||||
import de.staropensource.sosengine.base.internal.implementation.placeholder.logger.*;
|
import de.staropensource.sosengine.base.internal.implementation.placeholder.logger.*;
|
||||||
import de.staropensource.sosengine.base.internal.type.QueuedLogMessage;
|
import de.staropensource.sosengine.base.internal.type.QueuedLogMessage;
|
||||||
import de.staropensource.sosengine.base.implementation.logging.PlainLoggingAdapter;
|
|
||||||
import de.staropensource.sosengine.base.type.EngineState;
|
|
||||||
import de.staropensource.sosengine.base.type.logging.LogLevel;
|
import de.staropensource.sosengine.base.type.logging.LogLevel;
|
||||||
import de.staropensource.sosengine.base.type.logging.LogRule;
|
import de.staropensource.sosengine.base.type.logging.LogRule;
|
||||||
import de.staropensource.sosengine.base.type.logging.LogRuleType;
|
import de.staropensource.sosengine.base.type.logging.LogRuleType;
|
||||||
import de.staropensource.sosengine.base.utility.PlaceholderEngine;
|
import de.staropensource.sosengine.base.utility.PlaceholderEngine;
|
||||||
import de.staropensource.sosengine.base.implementation.shortcode.EmptyShortcodeConverter;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
@ -53,20 +52,6 @@ import java.util.Scanner;
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "JavadocDeclaration" })
|
@SuppressWarnings({ "JavadocDeclaration" })
|
||||||
public final class Logger {
|
public final class Logger {
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains a reference to the logging thread.
|
|
||||||
*
|
|
||||||
* @since v1-alpha1
|
|
||||||
* -- GETTER --
|
|
||||||
* Returns a reference the logging thread.
|
|
||||||
*
|
|
||||||
* @return logging thread reference
|
|
||||||
* @since v1-alpha1
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private static @Nullable Thread loggingThread;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains a list of {@link QueuedLogMessage}s.
|
* Contains a list of {@link QueuedLogMessage}s.
|
||||||
*
|
*
|
||||||
|
@ -116,46 +101,6 @@ public final class Logger {
|
||||||
*/
|
*/
|
||||||
public Logger() {}
|
public Logger() {}
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the logging thread.
|
|
||||||
*
|
|
||||||
* @since v1-alpha1
|
|
||||||
* @see #getLoggingThread()
|
|
||||||
*/
|
|
||||||
public static void startLoggingThread() {
|
|
||||||
if (loggingThread == null) {
|
|
||||||
// Logging thread not defined, create and start new one
|
|
||||||
Runnable threadLogic = () -> {
|
|
||||||
while (true) { // Run in loop
|
|
||||||
// Stop thread when engine is shutting down
|
|
||||||
if (Engine.getInstance().getState() == EngineState.SHUTDOWN
|
|
||||||
|| Engine.getInstance().getState() == EngineState.CRASHED
|
|
||||||
|| !EngineConfiguration.getInstance().isOptimizeLogging())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Process all log messages
|
|
||||||
flushLogMessages();
|
|
||||||
|
|
||||||
// Sleep for whatever has been configured
|
|
||||||
long sleepDuration = System.currentTimeMillis() + EngineConfiguration.getInstance().getLoggerPollingSpeed();
|
|
||||||
while (System.currentTimeMillis() < sleepDuration)
|
|
||||||
Thread.onSpinWait();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
loggingThread = Thread
|
|
||||||
.ofPlatform()
|
|
||||||
.daemon()
|
|
||||||
.name("Logging thread")
|
|
||||||
.group(Engine.getThreadGroup())
|
|
||||||
.stackSize(10)
|
|
||||||
.start(threadLogic);
|
|
||||||
} else
|
|
||||||
// Restart logging thread if dead
|
|
||||||
if (!loggingThread.isAlive())
|
|
||||||
loggingThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints all queued log messages.
|
* Prints all queued log messages.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
* STAROPENSOURCE ENGINE SOURCE FILE
|
||||||
|
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
||||||
|
* Licensed under the GNU Affero General Public License v3
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.staropensource.sosengine.base.logging;
|
||||||
|
|
||||||
|
import de.staropensource.sosengine.base.Engine;
|
||||||
|
import de.staropensource.sosengine.base.EngineConfiguration;
|
||||||
|
import de.staropensource.sosengine.base.type.EngineState;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls the logging thread of the engine.
|
||||||
|
*
|
||||||
|
* @since v1-alpha4
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@SuppressWarnings({ "JavadocDeclaration" })
|
||||||
|
public class LoggingThread {
|
||||||
|
/**
|
||||||
|
* Contains the {@link LoggerInstance} for this instance.
|
||||||
|
*
|
||||||
|
* @see LoggerInstance
|
||||||
|
* @since v1-alpha4
|
||||||
|
*/
|
||||||
|
protected static final @NotNull LoggerInstance logger = new LoggerInstance.Builder().setClazz(LoggingThread.class).setOrigin("ENGINE").build();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the logic of the logging thread.
|
||||||
|
*
|
||||||
|
* @since v1-alpha4
|
||||||
|
*/
|
||||||
|
private static final @NotNull Runnable loggingThreadLogic = () -> {
|
||||||
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
|
// Stop thread when engine is shutting down
|
||||||
|
if (Engine.getInstance().getState() == EngineState.SHUTDOWN
|
||||||
|
|| Engine.getInstance().getState() == EngineState.CRASHED
|
||||||
|
|| !EngineConfiguration.getInstance().isOptimizeLogging())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Process all log messages
|
||||||
|
Logger.flushLogMessages();
|
||||||
|
|
||||||
|
// Sleep for whatever has been configured
|
||||||
|
if (EngineConfiguration.getInstance().getLoggerPollingSpeed() > 0) {
|
||||||
|
long sleepDuration = System.currentTimeMillis() + EngineConfiguration.getInstance().getLoggerPollingSpeed();
|
||||||
|
while (System.currentTimeMillis() < sleepDuration)
|
||||||
|
Thread.onSpinWait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains a reference to the logging thread.
|
||||||
|
*
|
||||||
|
* @since v1-alpha1
|
||||||
|
*/
|
||||||
|
private static Thread loggingThread;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reconstructs the {@link #loggingThread} thread.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if the logging thread's state is not {@link Thread.State#TERMINATED}
|
||||||
|
* @since v1-alpha4
|
||||||
|
*/
|
||||||
|
private static void reconstructThread() throws IllegalStateException {
|
||||||
|
if (loggingThread != null && loggingThread.getState() != Thread.State.TERMINATED)
|
||||||
|
throw new IllegalStateException("The logging thread needs to be terminated before reconstruction");
|
||||||
|
|
||||||
|
loggingThread = Thread
|
||||||
|
.ofPlatform()
|
||||||
|
.daemon()
|
||||||
|
.name("Logging thread")
|
||||||
|
.group(Engine.getThreadGroup())
|
||||||
|
.stackSize(10)
|
||||||
|
.unstarted(loggingThreadLogic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the logging thread.
|
||||||
|
*
|
||||||
|
* @since v1-alpha4
|
||||||
|
* @see #loggingThread
|
||||||
|
*/
|
||||||
|
public static void startLoggingThread() {
|
||||||
|
if (loggingThread == null)
|
||||||
|
reconstructThread();
|
||||||
|
|
||||||
|
if (loggingThread.isAlive()) {
|
||||||
|
// Executing the thread restart logic prevents blocking the current thread
|
||||||
|
// while still ensuring that the logging thread is properly restarted
|
||||||
|
Thread
|
||||||
|
.ofVirtual()
|
||||||
|
.name("Logging thread restart thread")
|
||||||
|
.start(() -> {
|
||||||
|
logger.diag("Restarting the logging thread");
|
||||||
|
|
||||||
|
loggingThread.interrupt();
|
||||||
|
|
||||||
|
// Make sure that the logging thread is dead before reconstructing and starting it
|
||||||
|
while (loggingThread.isAlive())
|
||||||
|
Thread.onSpinWait();
|
||||||
|
|
||||||
|
reconstructThread();
|
||||||
|
loggingThread.start();
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
loggingThread.start();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue