package GCB; import java.util.*; /** StateMachineTimer is a separate thread to allow an FSM to capture missing events * the timer is started by the main thread. As FSMs are created, they * register themselves with the timer thread to receive control periodically. * timerThread does not make any value judgements concerning timeouts. The * thread will activate itself on a regular period (generally every second). * * timerThread is an separate thread that supplies the system timer functions * * @author George C. Blankenship, Jr. */ public class StateMachineTimer extends Thread { // class level data static final String CODE_FILE = "StateMachineTimer"; static final int CODE_REVISION = 3; static final long sleepPeriod = 1000; // desired monitoring period static ListHead FSMs; // FSMs requesting timer service static MainGUI mainGUI; // main GUI static Trace trace; // default (unnamed) trace // object attributes (private) private long clock, // current system time startTime, // start of FSM timeout routine endTime, // end of FSM timeout routine sleepTime; // time to sleep (see calculation below) private Calendar calendar; // public methods // constructors /** FSM is the constructor for a system timer thread * * (no input parameters) * @return (no return value - constructor) */ public StateMachineTimer(MainGUI mainGUI, Trace trace) { this.mainGUI = mainGUI; this.trace = trace; FSMs = new ListHead(); sleepTime = sleepPeriod; clock = 0; trace.write("start "+CODE_FILE+" r."+String.valueOf(CODE_REVISION)); mainGUI.setClock(clock); mainGUI.append("FSM timer ready"); } /** run() is the thread start routing * * (no input parameters) * @return (no return value) */ public void run() { StateMachine FSM; trace.write("FSM timer running"); mainGUI.append("FSM timer running"); while(mainGUI.stop()==false) { try { Thread.sleep(sleepTime); } catch (InterruptedException e) { break; } clock += sleepPeriod; mainGUI.setClock(clock); calendar = Calendar.getInstance(); startTime = calendar.getTimeInMillis(); FSM = (StateMachine) FSMs.getFirst(); while(FSM!=null) { FSM.timer(); FSM = (StateMachine) FSM.getNext(); } calendar = Calendar.getInstance(); // subtract the FSM processing time from sleep period endTime = calendar.getTimeInMillis(); sleepTime = sleepPeriod - (endTime - startTime); if(sleepTime<0) sleepTime = 100; } trace.write("FSM timer stopped"); mainGUI.append("FSM timer stopped"); } /** setFSM() adds an FSM to the monitoring list * * @param fsm a StateMachine that is to receive time calls * @return (no return value - constructor) */ public static void setFSM(StateMachine fsm) { trace.write("add state machine "+fsm.getName()); FSMs.setTail(fsm); } /** clearFSM() removes an FSM from the monitoring list * * @param fsm a StateMachine that is to no longer receive time calls * @return (no return value - constructor) */ public static void clearFSM(StateMachine fsm) { trace.write("remove state machine "+fsm.getName()); FSMs.remove(fsm); } /** isFSMactive() indicates whether there is a state machine active * * @return (true - state machine active) */ public static boolean isFSMactive() { if(FSMs.getCount()==0) return false; return true; } /** summarizeFSMs() display a summary of the active FSMs * * (no input parameters) * @return (no return value) */ static public void summarizeFSMs() { StateMachine fsm; trace.write(String.valueOf(FSMs.getCount())+" active FSMs in timer"); mainGUI.append(String.valueOf(FSMs.getCount())+" active FSMs in timer"); fsm = (StateMachine) FSMs.getFirst(); while(fsm!=null) { trace.write(fsm.getShortSummary()); mainGUI.append(fsm.getShortSummary()); fsm.summarize(); fsm = (StateMachine) fsm.getNext(); } } /** getFSMs() list of all active FSMs * * (no input parameters) * @return array of the active FSMs */ static public StateMachine[] getFSMs() { StateMachine[] activeFSMs = new StateMachine[FSMs.getCount()]; StateMachine fsm; trace.write(String.valueOf(FSMs.getCount())+" active FSMs in timer"); fsm = (StateMachine) FSMs.getFirst(); int i =0; while(fsm!=null) { trace.write(fsm.getShortSummary()); activeFSMs[i++] = fsm; fsm = (StateMachine) fsm.getNext(); } return activeFSMs; } static public StateMachine getFSM(String name) { StateMachine fsm; trace.write("get FSM ("+name+") with "+String.valueOf(FSMs.getCount())+" active FSMs in timer"); fsm = (StateMachine) FSMs.getFirst(); while(fsm!=null) { trace.write(fsm.getShortSummary()); if(name.equals(fsm.getName())) { trace.write("found FSM ("+name+")"); break; } fsm = (StateMachine) fsm.getNext(); } return fsm; } }