updated thread handling:

- threads are no longer pooled (this makes naming threads difficult)
- threads are now named by their causing event, which improves logging

updated calls to thread.sleep: those are now provided by new class Delayed Execution
This commit is contained in:
Stephan Richter
2021-02-28 13:03:21 +01:00
parent cabab80b5c
commit b951b948e5
47 changed files with 293 additions and 260 deletions

View File

@@ -94,7 +94,7 @@ public abstract class Action extends BaseClass {
return this.toString().equals(other.toString());
}
public abstract boolean fire(Context context);
public abstract boolean fire(Context context,Object cause);
public static Action get(Id actionId) {
return actions.get(actionId);

View File

@@ -80,15 +80,15 @@ public class ActionList extends Action implements Iterable<Action>{
return actions.remove(action);
}
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
if (context.invalidated()) {
LOG.debug("Context has been invalidated, aborting {}",this);
return false;
}
if (!isEmpty()) LOG.debug("{}.fire({})",this,context);
for (Action action : actions) {
if (!action.fire(context)) return false;
LOG.debug("firing \"{}\"",action);
if (!action.fire(context,cause)) return false;
}
return true;
}

View File

@@ -8,8 +8,8 @@ import java.util.Map;
import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.moving.Train;
import de.srsoftware.web4rail.tags.Checkbox;
import de.srsoftware.web4rail.tags.Fieldset;
@@ -30,7 +30,7 @@ public class AddDestination extends Action {
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
Train train = context.train();
if (isNull(train)) return false;
if (isNull(destination)) { // clear destinations!
@@ -73,17 +73,13 @@ public class AddDestination extends Action {
Id blockId = new Id(json.getString(Train.DESTINATION));
destination = BaseClass.get(blockId);
if (isNull(destination)) {
Application.threadPool.execute(new Thread() {
new DelayedExecution(this) {
@Override
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
public void execute() {
destination = BaseClass.get(blockId);
}
});
};
}
}
return super.load(json);

View File

@@ -24,7 +24,7 @@ public class AddRemoveTag extends Action{
private boolean remove = false;
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
if (isNull(context.train())) return false;
if (remove) {
context.train().removeTag(tag);

View File

@@ -28,7 +28,7 @@ public class AlterDirection extends Action{
@SuppressWarnings("incomplete-switch")
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
Train train = context.train();
if (isNull(train)) return false;

View File

@@ -9,7 +9,7 @@ public class BrakeStart extends Action {
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
if (isNull(context.route())) return false;
context.route().brakeStart();
LOG.debug("Started brake process...");

View File

@@ -27,11 +27,11 @@ public class ConditionalAction extends ActionList {
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
for (Condition condition : conditions) {
if (!condition.fulfilledBy(context)) return true; // wenn die Bedingung nicht erfüllt ist, ist das kein Fehler!
}
return super.fire(context.clone()); // actions, that happen within the conditional action list must not modify the global context.
return super.fire(context.clone(),cause); // actions, that happen within the conditional action list must not modify the global context.
}
@Override

View File

@@ -24,7 +24,7 @@ public class CoupleTrain extends Action {
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
Train train = context.train();
if (isNull(train)) return false;
Block block = train.currentBlock();

View File

@@ -6,8 +6,8 @@ import java.util.List;
import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Input;
import de.srsoftware.web4rail.tags.Window;
@@ -30,19 +30,17 @@ public class DelayedAction extends ActionList {
}
@Override
public boolean fire(Context context) {
Application.threadPool.execute(new Thread() {
public void run() {
try {
int delay = min_delay + (min_delay < max_delay ? random.nextInt(max_delay - min_delay) : 0);
Thread.sleep(delay);
LOG.debug("{} ms passed by, firing actions:",delay);
} catch (InterruptedException e) {
LOG.warn("Interrupted Exception thrown while waiting:",e);
}
DelayedAction.super.fire(context);
};
});
public boolean fire(Context context,Object cause) {
int delay = min_delay + (min_delay < max_delay ? random.nextInt(max_delay - min_delay) : 0);
new DelayedExecution(delay,cause) {
@Override
public void execute() {
LOG.debug("{} ms passed by, firing actions:",delay);
DelayedAction.super.fire(context,cause);
}
};
return true;
}

View File

@@ -6,8 +6,8 @@ import java.util.Map;
import org.json.JSONObject;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.tiles.Block;
@@ -22,7 +22,7 @@ public class DetermineTrainInBlock extends Action {
private Block block = null;
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
context.block(block);
context.train(block.train());
return true;
@@ -42,16 +42,13 @@ public class DetermineTrainInBlock extends Action {
if (isSet(blockId)) {
block = Block.get(blockId);
if (isNull(block)) {
Application.threadPool.execute(new Thread() {
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new DelayedExecution(this) {
@Override
public void execute() {
block = Block.get(blockId);
};
});
}
};
}
}
return this;

View File

@@ -7,8 +7,8 @@ import java.util.Map;
import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Radio;
import de.srsoftware.web4rail.tags.Window;
@@ -26,7 +26,7 @@ public class DisableEnableBlock extends Action {
private boolean disable = true;
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
if (isNull(block)) block = context.block();
if (isNull(block)) return false;
block.setEnabled(!disable);
@@ -48,16 +48,13 @@ public class DisableEnableBlock extends Action {
if (isSet(blockId)) {
block = Block.get(blockId);
if (isNull(block)) {
Application.threadPool.execute(new Thread() {
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new DelayedExecution(this) {
@Override
public void execute() {
block = Block.get(blockId);
};
});
}
};
}
}
if (json.has(STATE)) {

View File

@@ -6,8 +6,8 @@ import java.util.Map;
import org.json.JSONObject;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.tiles.Decoupler;
@@ -24,7 +24,7 @@ public class EngageDecoupler extends Action {
private Decoupler decoupler = null;
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
if (isNull(decoupler)) return false;
decoupler.engage();
return true;
@@ -45,14 +45,13 @@ public class EngageDecoupler extends Action {
if (json.has(DECOUPLER)) {
String decouplerId = json.getString(DECOUPLER);
decoupler = BaseClass.get(new Id(decouplerId));
if (isNull(decoupler)) Application.threadPool.execute(new Thread() { // if relay not loaded, yet: wait one sec and try again
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {}
if (isNull(decoupler)) new DelayedExecution(this) {
@Override
public void execute() {
decoupler = BaseClass.get(new Id(decouplerId));
};
});
}
};
}
return this;
}

View File

@@ -10,7 +10,7 @@ public class FinishRoute extends Action {
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
Route route = context.route();
if (isSet(route)) route.finish();
return true;

View File

@@ -29,7 +29,7 @@ public class Loop extends ActionList {
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
if (isNull(object)) return false;
List<? extends BaseClass> elements = null;
switch (object) {
@@ -53,7 +53,7 @@ public class Loop extends ActionList {
break;
}
if (elements == null) return false;
for (BaseClass element : elements) super.fire(context.setMain(element));
for (BaseClass element : elements) super.fire(context.setMain(element),cause);
return true;
}

View File

@@ -13,7 +13,7 @@ public class PreserveRoute extends Action {
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
Train train = context.train();
Route route = context.route();
// These are errors:

View File

@@ -9,7 +9,7 @@ public class ReactivateContact extends Action{
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
if (isNull(context.contact())) return false;
if (isNull(context.route())) return false;
return context.route().reactivate(context.contact());

View File

@@ -11,7 +11,7 @@ public class SavePlan extends Action{
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
try {
plan.stream(plan.save());
} catch (IOException e) {

View File

@@ -30,7 +30,7 @@ public class SendCommand extends Action{
private Target target = Target.SRCP;
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
switch (target) {
case SRCP:
plan.queue(new Command(command) {

View File

@@ -5,8 +5,8 @@ import java.util.List;
import org.json.JSONObject;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.moving.Train;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window;
@@ -20,7 +20,7 @@ public class SetContextTrain extends Action {
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
context.train(train);
return true;
}
@@ -39,14 +39,13 @@ public class SetContextTrain extends Action {
Id trainId = Id.from(json,REALM_TRAIN);
if (isSet(trainId)) {
train = Train.get(trainId);
if (isNull(train)) Application.threadPool.execute(new Thread() { // load asynchronously, as referred tile may not be available,yet
public void run() {
try {
sleep(1000);
train = Train.get(trainId);
} catch (InterruptedException e) {}
};
});
if (isNull(train)) new DelayedExecution(this) {
@Override
public void execute() {
train = Train.get(trainId);
}
};
}
}
return this;

View File

@@ -6,8 +6,8 @@ import java.util.Map;
import org.json.JSONObject;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Label;
import de.srsoftware.web4rail.tags.Window;
@@ -24,7 +24,7 @@ public class SetDisplayText extends TextAction{
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
plan.place(display.text(fill(text, context)));
return true;
}
@@ -44,14 +44,13 @@ public class SetDisplayText extends TextAction{
@Override
public Action load(JSONObject json) {
if (json.has(DISPLAY)) {
Application.threadPool.execute(new Thread() { // load asynchronously, as referred tile may not be available,yet
public void run() {
try {
sleep(1000);
display = (TextDisplay) plan.get(Id.from(json,DISPLAY), false);
} catch (InterruptedException e) {}
new DelayedExecution(this) {
@Override
public void execute() {
display = (TextDisplay) plan.get(Id.from(json,DISPLAY), false);
};
});
};
}
return super.load(json);
}

View File

@@ -26,7 +26,7 @@ public class SetPower extends Action{
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
ControlUnit cu = plan.controlUnit();
switch (pc) {
case ON:
@@ -85,6 +85,6 @@ public class SetPower extends Action{
LOG.debug("update: {}",params);
String newState = params.get(STATE);
if (isSet(newState)) pc = POWERCHANGE.valueOf(newState);
return properties();
return parent().properties();
}
}

View File

@@ -7,8 +7,8 @@ import java.util.Map;
import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Select;
import de.srsoftware.web4rail.tags.Window;
@@ -28,7 +28,7 @@ public class SetRelayOrSwitch extends Action {
private boolean state = false;
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
if (isNull(relayOrSwitch)) return false;
if (relayOrSwitch instanceof Relay) ((Relay)relayOrSwitch).state(state);
if (relayOrSwitch instanceof Switch) ((Switch)relayOrSwitch).state(state);
@@ -55,26 +55,24 @@ public class SetRelayOrSwitch extends Action {
if (json.has(RELAY)) {
String relayId = json.getString(RELAY);
relayOrSwitch = BaseClass.get(new Id(relayId));
if (isNull(relayOrSwitch)) Application.threadPool.execute(new Thread() { // if relay not loaded, yet: wait one sec and try again
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {}
if (isNull(relayOrSwitch)) new DelayedExecution(this) {
@Override
public void execute() {
relayOrSwitch = BaseClass.get(new Id(relayId));
};
});
};
}
if (json.has(SWITCH)) {
String relayId = json.getString(SWITCH);
relayOrSwitch = BaseClass.get(new Id(relayId));
if (isNull(relayOrSwitch)) Application.threadPool.execute(new Thread() { // if relay not loaded, yet: wait one sec and try again
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {}
if (isNull(relayOrSwitch)) new DelayedExecution(this) {
@Override
public void execute() {
relayOrSwitch = BaseClass.get(new Id(relayId));
};
});
}
};
}
if (json.has(STATE)) state = json.getBoolean(STATE);
return this;

View File

@@ -34,7 +34,7 @@ public class SetSignal extends Action {
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
if (isNull(signal)) return false;
return signal.state(state);
}

View File

@@ -25,7 +25,7 @@ public class SetSpeed extends Action{
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
if (isNull(context.train())) return false;
context.train().setSpeed(speed);
return true;

View File

@@ -7,8 +7,8 @@ import java.util.Map;
import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Select;
import de.srsoftware.web4rail.tags.Window;
@@ -25,7 +25,7 @@ public class SetTurnout extends Action {
private Turnout.State state = State.STRAIGHT;
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
if (isNull(turnout)) return false;
if (!turnout.state(state).succeeded()) return false;
if (turnout.address() == 0) return true;
@@ -53,19 +53,13 @@ public class SetTurnout extends Action {
Id turnoutId = json.has(TURNOUT) ? new Id(json.getString(TURNOUT)) : null;
if (isSet(turnoutId)) {
turnout = BaseClass.get(turnoutId);
if (isNull(turnout)) {
Application.threadPool.execute(new Thread() {
@Override
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
turnout = BaseClass.get(turnoutId);
}
});
}
if (isNull(turnout)) new DelayedExecution(this) {
@Override
public void execute() {
turnout = BaseClass.get(turnoutId);
}
};
}
if (json.has(Turnout.STATE)) state = Turnout.State.valueOf(json.getString(Turnout.STATE));
return this;

View File

@@ -11,7 +11,7 @@ public class ShowText extends TextAction{
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
plan.stream(fill(text,context));
return true;
}

View File

@@ -22,7 +22,7 @@ public class SplitTrain extends Action {
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
Train train = context.train();
if (isNull(train)) return false;
return train.splitAfter(position);

View File

@@ -20,7 +20,7 @@ public class StartStopAuto extends Action {
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
if (isNull(context.train())) return false;
if (inverted) {
context.train().automatic();

View File

@@ -9,7 +9,7 @@ public class StopTrain extends Action{
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
if (isNull(context.train())) return false;
LOG.debug("{}.fire() called, context = {}",this,context);
context.train().stopNow();

View File

@@ -27,7 +27,7 @@ public class SwitchFunction extends Action {
}
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
if (isNull(context) || isNull(context.train())) return false;
switch (effect) {
case TOGGLE:

View File

@@ -20,7 +20,7 @@ public class TriggerContact extends Action {
private Contact contact = null;
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
if (isSet(contact)) return contact.trigger(200);
return false;
}

View File

@@ -7,8 +7,8 @@ import java.util.Map;
import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Input;
import de.srsoftware.web4rail.tags.Window;
@@ -30,34 +30,29 @@ public class WaitForContact extends ActionList {
private int timeout = 10000;
@Override
public boolean fire(Context context) {
public boolean fire(Context context,Object cause) {
LOG.debug("{}.fire(...) called, waiting for {}.",this,contact);
if (isNull(contact)) return false;
fired = false;
Listener listener = new Listener() {
@Override
public void fired() {
public void fired(Object cause) {
LOG.debug("{} triggered, firing {}",contact,actions);
fired = true;
contact.removeListener(this);
WaitForContact.super.fire(context);
WaitForContact.super.fire(context,cause);
}
};
contact.addListener(listener);
Application.threadPool.execute(new Thread() { // remove listener after timout
new DelayedExecution(timeout,cause) {
@Override
public void run() {
try {
sleep(timeout);
} catch (InterruptedException e) {
e.printStackTrace();
}
public void execute() {
contact.removeListener(listener);
LOG.debug("{} timed out, firing {}",this,timeoutActions);
if (!fired) timeoutActions.fire(context);
if (!fired) timeoutActions.fire(context,cause);
}
});
};
return true;
}
@@ -90,19 +85,13 @@ public class WaitForContact extends ActionList {
if (json.has(CONTACT)) {
String cid = json.getString(CONTACT);
contact = BaseClass.get(new Id(cid));
if (isNull(contact)) {
Application.threadPool.execute(new Thread() {
@Override
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
contact = BaseClass.get(new Id(cid));
}
});
}
if (isNull(contact)) new DelayedExecution(this) {
@Override
public void execute() {
contact = BaseClass.get(new Id(cid));
}
};
}
if (json.has(TIMEOUT)) timeout = json.getInt(TIMEOUT);
if (json.has(TIMEOUT_ACTIONS)) timeoutActions.load(json.getJSONObject(TIMEOUT_ACTIONS));