564 lines
21 KiB
Java
564 lines
21 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* javax.baja.nre.util.SortUtil
|
|
*/
|
|
package com.tridium.sys.engine;
|
|
|
|
import com.tridium.sys.Nre;
|
|
import com.tridium.sys.engine.ActionQueue;
|
|
import com.tridium.sys.engine.EngineUtil;
|
|
import com.tridium.sys.engine.NClockTicket;
|
|
import com.tridium.sys.engine.TicketQueue;
|
|
import com.tridium.sys.resource.ResourceReport;
|
|
import java.text.DecimalFormat;
|
|
import java.util.Iterator;
|
|
import javax.baja.log.Log;
|
|
import javax.baja.nre.util.SortUtil;
|
|
import javax.baja.spy.Spy;
|
|
import javax.baja.spy.SpyDir;
|
|
import javax.baja.spy.SpyWriter;
|
|
import javax.baja.sys.Action;
|
|
import javax.baja.sys.BAbsTime;
|
|
import javax.baja.sys.BComponent;
|
|
import javax.baja.sys.BLink;
|
|
import javax.baja.sys.BObject;
|
|
import javax.baja.sys.BRelTime;
|
|
import javax.baja.sys.BStation;
|
|
import javax.baja.sys.BValue;
|
|
import javax.baja.sys.Clock;
|
|
import javax.baja.sys.Flags;
|
|
import javax.baja.sys.NotRunningException;
|
|
import javax.baja.sys.SlotCursor;
|
|
import javax.baja.sys.Sys;
|
|
|
|
/*
|
|
* Illegal identifiers - consider using --renameillegalidents true
|
|
*/
|
|
public class EngineManager {
|
|
static DecimalFormat timeFormat = new DecimalFormat("#.000 ms");
|
|
public static final Log log = Log.getLog("sys.engine");
|
|
public static long engineSleepPeriod = 20L;
|
|
private static final int SYSTEM_CLOCK_CHANGE_TOLERANCE = 1000;
|
|
public static long shortTimerThreshold = 2100L;
|
|
public static long mediumTimerThreshold = 61000L;
|
|
private long startTicks;
|
|
private volatile int scanCount;
|
|
private int ticketScanCount;
|
|
private long totalTicksInsideScan;
|
|
private long lastTotalTicksInsideScan;
|
|
private long deltaTicksInsideScan;
|
|
private long peakTicksInsideScan;
|
|
private boolean suspended;
|
|
private ActionQueue actionQueue;
|
|
private BComponent currentComponent;
|
|
private Action currentAction;
|
|
private long lastMillisVsTicksDelta;
|
|
public TicketQueue shortTimers;
|
|
public TicketQueue mediumTimers;
|
|
public TicketQueue longTimers;
|
|
|
|
public void start(BComponent bComponent) {
|
|
if (!bComponent.isRunning()) {
|
|
throw new IllegalStateException();
|
|
}
|
|
this.activateLinks(bComponent);
|
|
EngineUtil.started(bComponent);
|
|
SlotCursor slotCursor = bComponent.getProperties();
|
|
while (slotCursor.nextComponent()) {
|
|
if (Flags.isNoRun(bComponent, slotCursor.property())) continue;
|
|
slotCursor.get().asComponent().start();
|
|
}
|
|
EngineUtil.descendantsStarted(bComponent);
|
|
}
|
|
|
|
private final void activateLinks(BComponent bComponent) {
|
|
SlotCursor slotCursor = bComponent.getProperties();
|
|
while (slotCursor.nextObject()) {
|
|
BObject bObject = slotCursor.get();
|
|
if (!(bObject instanceof BLink)) continue;
|
|
EngineUtil.activate((BLink)bObject);
|
|
}
|
|
}
|
|
|
|
public void stop(BComponent bComponent) {
|
|
if (bComponent.isRunning()) {
|
|
throw new IllegalStateException();
|
|
}
|
|
this.deactivateLinks(bComponent);
|
|
EngineUtil.stopped(bComponent);
|
|
SlotCursor slotCursor = bComponent.getProperties();
|
|
while (slotCursor.nextComponent()) {
|
|
slotCursor.get().asComponent().stop();
|
|
}
|
|
EngineUtil.descendantsStopped(bComponent);
|
|
}
|
|
|
|
private final void deactivateLinks(BComponent bComponent) {
|
|
SlotCursor slotCursor = bComponent.getProperties();
|
|
while (slotCursor.nextObject()) {
|
|
BObject bObject = slotCursor.get();
|
|
if (!(bObject instanceof BLink)) continue;
|
|
EngineUtil.deactivate((BLink)bObject);
|
|
}
|
|
}
|
|
|
|
public void stationStarted(BComponent bComponent) {
|
|
EngineUtil.stationStarted(bComponent);
|
|
SlotCursor slotCursor = bComponent.getProperties();
|
|
while (slotCursor.nextComponent()) {
|
|
this.stationStarted(slotCursor.get().asComponent());
|
|
}
|
|
}
|
|
|
|
public void atSteadyState(BComponent bComponent) {
|
|
if (!bComponent.isRunning()) {
|
|
log.warning("Not running: " + bComponent);
|
|
return;
|
|
}
|
|
EngineUtil.atSteadyState(bComponent);
|
|
SlotCursor slotCursor = bComponent.getProperties();
|
|
while (slotCursor.nextComponent()) {
|
|
this.atSteadyState(slotCursor.get().asComponent());
|
|
}
|
|
}
|
|
|
|
void execute() {
|
|
long l = Clock.ticks();
|
|
this.checkIfSystemClockChanged();
|
|
this.shortTimers.check();
|
|
this.mediumTimers.check();
|
|
this.longTimers.check();
|
|
this.checkAsyncActions();
|
|
long l2 = Clock.ticks();
|
|
long l3 = l2 - l;
|
|
if (l3 > this.peakTicksInsideScan) {
|
|
this.peakTicksInsideScan = l3;
|
|
}
|
|
this.totalTicksInsideScan += l3;
|
|
++this.scanCount;
|
|
if (this.scanCount % 10 == 0) {
|
|
this.deltaTicksInsideScan = this.totalTicksInsideScan - this.lastTotalTicksInsideScan;
|
|
this.lastTotalTicksInsideScan = this.totalTicksInsideScan;
|
|
}
|
|
}
|
|
|
|
private final void checkIfSystemClockChanged() {
|
|
long l = this.getSystemClockWarp();
|
|
if (l != 0L) {
|
|
log.warning("System clock modified: " + l + "ms");
|
|
this.clockChanged(Sys.getStation(), BRelTime.make(l));
|
|
}
|
|
}
|
|
|
|
private final long getMillisVsTicksDelta() {
|
|
long l = Clock.ticks();
|
|
long l2 = Clock.millis();
|
|
long l3 = Clock.ticks();
|
|
if (l3 - l > 1000L) {
|
|
return 0L;
|
|
}
|
|
long l4 = l3 - l2;
|
|
return l4 >= 0L ? l4 : -l4;
|
|
}
|
|
|
|
private final long getSystemClockWarp() {
|
|
long l = this.getMillisVsTicksDelta();
|
|
if (l == 0L) {
|
|
return 0L;
|
|
}
|
|
long l2 = l - this.lastMillisVsTicksDelta;
|
|
if (Math.abs(l2) < 1000L) {
|
|
return 0L;
|
|
}
|
|
this.lastMillisVsTicksDelta = l;
|
|
return l2;
|
|
}
|
|
|
|
public void clockChanged(BComponent bComponent, BRelTime bRelTime) {
|
|
try {
|
|
if (bComponent == null) {
|
|
return;
|
|
}
|
|
EngineUtil.clockChanged(bComponent, bRelTime);
|
|
SlotCursor slotCursor = bComponent.getProperties();
|
|
while (slotCursor.nextComponent()) {
|
|
this.clockChanged(slotCursor.get().asComponent(), bRelTime);
|
|
}
|
|
}
|
|
catch (Throwable throwable) {
|
|
throwable.printStackTrace();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* WARNING - Removed try catching itself - possible behaviour change.
|
|
* Enabled aggressive block sorting
|
|
* Enabled unnecessary exception pruning
|
|
* Enabled aggressive exception aggregation
|
|
*/
|
|
public void enqueueAction(BComponent bComponent, Action action, BValue bValue) {
|
|
ActionQueue actionQueue = this.actionQueue;
|
|
synchronized (actionQueue) {
|
|
if (bComponent == this.currentComponent && action == this.currentAction) {
|
|
return;
|
|
}
|
|
this.actionQueue.enqueue(bComponent, action, bValue);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* WARNING - Removed try catching itself - possible behaviour change.
|
|
* Unable to fully structure code
|
|
* Enabled aggressive block sorting
|
|
* Enabled unnecessary exception pruning
|
|
* Enabled aggressive exception aggregation
|
|
*/
|
|
void checkAsyncActions() {
|
|
var1_1 = null;
|
|
var2_2 = this.actionQueue;
|
|
synchronized (var2_2) {
|
|
var1_1 = this.actionQueue.reset();
|
|
// MONITOREXIT @DISABLED, blocks:[0, 1] lbl6 : MonitorExitStatement: MONITOREXIT : var2_2
|
|
if (true) ** GOTO lbl17
|
|
}
|
|
do {
|
|
this.currentComponent = var1_1.component;
|
|
this.currentAction = var1_1.action;
|
|
EngineUtil.doInvoke(var1_1.component, var1_1.action, var1_1.arg, null);
|
|
var4_3 = var1_1;
|
|
var1_1 = var1_1.next;
|
|
var4_3.next = null;
|
|
lbl17:
|
|
// 2 sources
|
|
|
|
} while (var1_1 != null);
|
|
this.currentComponent = null;
|
|
this.currentAction = null;
|
|
}
|
|
|
|
public NClockTicket schedule(BComponent bComponent, BRelTime bRelTime, Action action, BValue bValue) {
|
|
if (!bComponent.isRunning()) {
|
|
throw new NotRunningException();
|
|
}
|
|
if (action == null) {
|
|
throw new NullPointerException("Null action");
|
|
}
|
|
long l = bRelTime.getMillis();
|
|
if (l <= 0L) {
|
|
throw new IllegalArgumentException("time <= 0");
|
|
}
|
|
NClockTicket nClockTicket = new NClockTicket(bComponent, action, bValue);
|
|
nClockTicket.nextUpdate = -(Clock.ticks() + l);
|
|
nClockTicket.period = 0L;
|
|
this.enqueueTicket(nClockTicket);
|
|
return nClockTicket;
|
|
}
|
|
|
|
public NClockTicket schedule(BComponent bComponent, BAbsTime bAbsTime, Action action, BValue bValue) {
|
|
if (!bComponent.isRunning()) {
|
|
throw new NotRunningException();
|
|
}
|
|
if (action == null) {
|
|
throw new NullPointerException("Null action");
|
|
}
|
|
long l = bAbsTime.getMillis();
|
|
if (l <= 0L) {
|
|
throw new IllegalArgumentException("time <= 0");
|
|
}
|
|
NClockTicket nClockTicket = new NClockTicket(bComponent, action, bValue);
|
|
nClockTicket.nextUpdate = l;
|
|
nClockTicket.period = 0L;
|
|
this.enqueueTicket(nClockTicket);
|
|
return nClockTicket;
|
|
}
|
|
|
|
public NClockTicket schedulePeriodically(BComponent bComponent, BRelTime bRelTime, Action action, BValue bValue) {
|
|
if (!bComponent.isRunning()) {
|
|
throw new NotRunningException();
|
|
}
|
|
if (action == null) {
|
|
throw new NullPointerException("Null action");
|
|
}
|
|
long l = bRelTime.getMillis();
|
|
if (l <= 0L) {
|
|
throw new IllegalArgumentException("period <= 0");
|
|
}
|
|
NClockTicket nClockTicket = new NClockTicket(bComponent, action, bValue);
|
|
nClockTicket.nextUpdate = -(Clock.ticks() + l);
|
|
nClockTicket.period = l;
|
|
this.enqueueTicket(nClockTicket);
|
|
return nClockTicket;
|
|
}
|
|
|
|
public NClockTicket schedulePeriodically(BComponent bComponent, BAbsTime bAbsTime, BRelTime bRelTime, Action action, BValue bValue) {
|
|
if (!bComponent.isRunning()) {
|
|
throw new NotRunningException();
|
|
}
|
|
if (action == null) {
|
|
throw new NullPointerException("Null action");
|
|
}
|
|
long l = bAbsTime.getMillis();
|
|
long l2 = bRelTime.getMillis();
|
|
if (l <= 0L) {
|
|
throw new IllegalArgumentException("start <= 0");
|
|
}
|
|
if (l2 <= 0L) {
|
|
throw new IllegalArgumentException("period <= 0");
|
|
}
|
|
NClockTicket nClockTicket = new NClockTicket(bComponent, action, bValue);
|
|
nClockTicket.nextUpdate = l;
|
|
nClockTicket.period = l2;
|
|
this.enqueueTicket(nClockTicket);
|
|
return nClockTicket;
|
|
}
|
|
|
|
void enqueueTicket(NClockTicket nClockTicket) {
|
|
long l = nClockTicket.period;
|
|
if (l <= 0L) {
|
|
l = nClockTicket.millisLeft();
|
|
}
|
|
if (l < shortTimerThreshold) {
|
|
this.shortTimers.enqueue(nClockTicket);
|
|
} else if (l < mediumTimerThreshold) {
|
|
this.mediumTimers.enqueue(nClockTicket);
|
|
} else {
|
|
this.longTimers.enqueue(nClockTicket);
|
|
}
|
|
}
|
|
|
|
public void reportResources(ResourceReport resourceReport) {
|
|
double d = (double)this.totalTicksInsideScan / (double)this.scanCount;
|
|
double d2 = (double)this.deltaTicksInsideScan / 10.0;
|
|
double d3 = Clock.ticks() - this.startTicks;
|
|
double d4 = (double)this.totalTicksInsideScan / d3 * 100.0;
|
|
resourceReport.put("engine.scan.lifetime", timeFormat.format(d));
|
|
resourceReport.put("engine.scan.peak", timeFormat.format(this.peakTicksInsideScan));
|
|
resourceReport.put("engine.scan.recent", timeFormat.format(d2));
|
|
resourceReport.put("engine.scan.usage", "" + (int)d4 + '%');
|
|
resourceReport.put("engine.queue.shortTimers", this.shortTimers.size + " (Peak " + this.shortTimers.peak + ')');
|
|
resourceReport.put("engine.queue.mediumTimers", this.mediumTimers.size + " (Peak " + this.mediumTimers.peak + ')');
|
|
resourceReport.put("engine.queue.longTimers", this.longTimers.size + " (Peak " + this.longTimers.peak + ')');
|
|
resourceReport.put("engine.queue.actions", this.actionQueue.size() + " (Peak " + this.actionQueue.peak() + ')');
|
|
}
|
|
|
|
public void postInit() {
|
|
SummaryPage summaryPage = new SummaryPage();
|
|
Nre.spySysManagers.add("engineManager", summaryPage);
|
|
summaryPage.add("shortTimers", new TicketQueuePage(this.shortTimers));
|
|
summaryPage.add("mediumTimers", new TicketQueuePage(this.mediumTimers));
|
|
summaryPage.add("longTimers", new TicketQueuePage(this.longTimers));
|
|
summaryPage.add("asyncQueue", new AsyncQueuePage());
|
|
summaryPage.add("hogs", new HogsPage());
|
|
}
|
|
|
|
static String timeStr(long l) {
|
|
return l + "ms [" + BRelTime.toString(l) + ']';
|
|
}
|
|
|
|
public void suspend() {
|
|
this.suspended = true;
|
|
}
|
|
|
|
public void resume() {
|
|
this.suspended = false;
|
|
}
|
|
|
|
public int getCycles() {
|
|
return this.scanCount;
|
|
}
|
|
|
|
public long getTotalTicksInsideCycle() {
|
|
return this.totalTicksInsideScan;
|
|
}
|
|
|
|
public float getAvgerageTicks() {
|
|
double d = (double)this.deltaTicksInsideScan / 10.0;
|
|
return (float)d;
|
|
}
|
|
|
|
private final /* synthetic */ void this() {
|
|
this.lastTotalTicksInsideScan = 0L;
|
|
this.deltaTicksInsideScan = 0L;
|
|
this.peakTicksInsideScan = 0L;
|
|
this.suspended = false;
|
|
this.actionQueue = new ActionQueue();
|
|
this.shortTimers = new TicketQueue(100, 1000);
|
|
this.mediumTimers = new TicketQueue(1000, 10000);
|
|
this.longTimers = new TicketQueue(1000, 30000);
|
|
}
|
|
|
|
public EngineManager() {
|
|
this.this();
|
|
this.startTicks = Clock.ticks();
|
|
this.lastMillisVsTicksDelta = this.getMillisVsTicksDelta();
|
|
new EngineThread().start();
|
|
}
|
|
|
|
/*
|
|
* Illegal identifiers - consider using --renameillegalidents true
|
|
*/
|
|
public class SummaryPage
|
|
extends SpyDir {
|
|
public void write(SpyWriter spyWriter) throws Exception {
|
|
double d = (double)EngineManager.this.totalTicksInsideScan / (double)EngineManager.this.scanCount;
|
|
double d2 = (double)EngineManager.this.deltaTicksInsideScan / 10.0;
|
|
BComponent bComponent = EngineManager.this.currentComponent;
|
|
Action action = EngineManager.this.currentAction;
|
|
spyWriter.startProps();
|
|
spyWriter.prop((Object)"atSteadyState", Sys.atSteadyState());
|
|
spyWriter.prop((Object)"suspended", "" + EngineManager.this.suspended);
|
|
spyWriter.prop((Object)"scanCount", "" + EngineManager.this.scanCount);
|
|
spyWriter.prop((Object)"runtime", EngineManager.timeStr(Clock.ticks() - EngineManager.this.startTicks));
|
|
spyWriter.prop((Object)"totalTicksInsideScan", EngineManager.timeStr(EngineManager.this.totalTicksInsideScan));
|
|
spyWriter.prop((Object)"averageTime/scan", d + "ms");
|
|
spyWriter.prop((Object)"averageTimeLast10Scan", d2 + "ms");
|
|
spyWriter.prop((Object)"peakScanTime", EngineManager.this.peakTicksInsideScan + "ms");
|
|
spyWriter.trTitle("Actions", 2);
|
|
spyWriter.prop((Object)"currentComponent", bComponent == null ? "null" : bComponent.toDebugString());
|
|
spyWriter.prop((Object)"currentAction", action);
|
|
spyWriter.prop((Object)("<a href='" + spyWriter.href("asyncQueue") + "'>Async Action Queue</a>"), EngineManager.this.actionQueue.size() + " (Peak " + EngineManager.this.actionQueue.peak() + ')');
|
|
spyWriter.prop((Object)("<a href='" + spyWriter.href("hogs") + "'>Engine Hogs</a>"), "");
|
|
spyWriter.trTitle("Short Timers (" + shortTimerThreshold + "ms or less)", 2);
|
|
EngineManager.this.shortTimers.writeSummary(spyWriter, "shortTimers");
|
|
spyWriter.trTitle("Medium Timers (" + shortTimerThreshold + "ms to " + mediumTimerThreshold + "ms)", 2);
|
|
EngineManager.this.mediumTimers.writeSummary(spyWriter, "mediumTimers");
|
|
spyWriter.trTitle("Long Timers (" + mediumTimerThreshold + "ms or greater)", 2);
|
|
EngineManager.this.longTimers.writeSummary(spyWriter, "longTimers");
|
|
spyWriter.endProps();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Illegal identifiers - consider using --renameillegalidents true
|
|
*/
|
|
public class TicketQueuePage
|
|
extends Spy {
|
|
TicketQueue q;
|
|
|
|
public void write(SpyWriter spyWriter) throws Exception {
|
|
long l = Clock.millis();
|
|
long l2 = Clock.ticks();
|
|
spyWriter.startTable(true);
|
|
spyWriter.trTitle("Timer Clock.Ticket Queue: " + BAbsTime.make(), 6);
|
|
spyWriter.w("<tr>").th("Mode").th("Next Update").th("Period").th("Component").th("Action").th("ActionArg").w("</tr>\n");
|
|
int n = 0;
|
|
NClockTicket nClockTicket = this.q.head;
|
|
while (nClockTicket != null) {
|
|
long l3 = nClockTicket.millisLeft();
|
|
if (++n > 1000) {
|
|
spyWriter.tr("more...", "", "", "", "", "");
|
|
break;
|
|
}
|
|
spyWriter.tr(nClockTicket.nextUpdate < 0L ? "ticks" : "millis", EngineManager.timeStr(l3), "" + nClockTicket.period, nClockTicket.component.toDebugString(), nClockTicket.action, nClockTicket.arg);
|
|
nClockTicket = nClockTicket.next;
|
|
}
|
|
spyWriter.endTable();
|
|
}
|
|
|
|
TicketQueuePage(TicketQueue ticketQueue) {
|
|
this.q = ticketQueue;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Illegal identifiers - consider using --renameillegalidents true
|
|
*/
|
|
public class AsyncQueuePage
|
|
extends Spy {
|
|
/*
|
|
* WARNING - Removed try catching itself - possible behaviour change.
|
|
* Enabled aggressive block sorting
|
|
* Enabled unnecessary exception pruning
|
|
* Enabled aggressive exception aggregation
|
|
*/
|
|
public void write(SpyWriter spyWriter) throws Exception {
|
|
spyWriter.startTable(true);
|
|
spyWriter.trTitle("Async Action Queue", 2);
|
|
spyWriter.w("<tr>").th("Component").th("Action").w("</tr>\n");
|
|
ActionQueue actionQueue = EngineManager.this.actionQueue;
|
|
synchronized (actionQueue) {
|
|
int n = 0;
|
|
Iterator iterator = EngineManager.this.actionQueue.iterator();
|
|
while (iterator.hasNext()) {
|
|
if (++n > 1000) {
|
|
spyWriter.tr("more...", "");
|
|
break;
|
|
}
|
|
ActionQueue.Entry entry = (ActionQueue.Entry)iterator.next();
|
|
spyWriter.tr(entry.component.toDebugString(), entry.action);
|
|
}
|
|
}
|
|
spyWriter.endTable();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Illegal identifiers - consider using --renameillegalidents true
|
|
*/
|
|
public class HogsPage
|
|
extends Spy {
|
|
public void write(SpyWriter spyWriter) throws Exception {
|
|
BStation bStation = Sys.getStation();
|
|
if (bStation == null) {
|
|
spyWriter.w("Not station VM");
|
|
return;
|
|
}
|
|
Object[] objectArray = bStation.getComponentSpace().getAllComponents();
|
|
Object[] objectArray2 = new Long[objectArray.length];
|
|
Long l = new Long(0L);
|
|
int n = 0;
|
|
while (n < objectArray.length) {
|
|
objectArray2[n] = (Long)((BObject)objectArray[n]).fw(22);
|
|
if (objectArray2[n] == null) {
|
|
objectArray2[n] = l;
|
|
}
|
|
++n;
|
|
}
|
|
SortUtil.sort((Object[])objectArray2, (Object[])objectArray, (boolean)false);
|
|
spyWriter.startTable(true);
|
|
spyWriter.trTitle("Engine Hogs", 4);
|
|
spyWriter.w("<tr>").th("Rank").th("Component").th("Type").th("Total Time").w("</tr>\n");
|
|
n = 0;
|
|
while (n < 100 && n < objectArray.length) {
|
|
Object object = objectArray[n];
|
|
if (objectArray2[n] == l) break;
|
|
long l2 = (Long)objectArray2[n];
|
|
spyWriter.tr("" + n, ((BComponent)object).toPathString(), ((BComponent)object).getType(), EngineManager.timeStr(l2 / 1000000L));
|
|
++n;
|
|
}
|
|
spyWriter.endTable();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Illegal identifiers - consider using --renameillegalidents true
|
|
*/
|
|
class EngineThread
|
|
extends Thread {
|
|
public void run() {
|
|
while (true) {
|
|
try {
|
|
Thread.sleep(engineSleepPeriod);
|
|
if (EngineManager.this.suspended) continue;
|
|
EngineManager.this.execute();
|
|
continue;
|
|
}
|
|
catch (Throwable throwable) {
|
|
log.error("Error in run", throwable);
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
public EngineThread() {
|
|
super(Nre.mainThreadGroup, "Nre:Engine");
|
|
this.setDaemon(true);
|
|
}
|
|
}
|
|
}
|
|
|