package ecologylab.concurrent; import ecologylab.appframework.TraceSlots; /** * Extensions to thread provide the service of raising embellishments, * and also functionality for starting & stopping this thang. */ public abstract class RaiseMonitor extends Thread { protected boolean running; /** * A montior object used to control access to the wait() call that happens * when a waitThenShow() request is received. */ protected final Object waitingLock = new Object(); /** * */ protected boolean waitingToDoRun; private int raiseDelay; public RaiseMonitor(String name, int raiseDelay, boolean startNow) { super(name); this.raiseDelay = raiseDelay; if (startNow) start(); } @Override public void start() { if (!running) { running = true; super.start(); } } public synchronized void stopRunning() { if (running) { running = false; synchronized (waitingLock) { notify(); } } } /** * Raise after a suitable delay, unless a cancel comes * in first(). */ public synchronized void waitThenShow() { //println("RolloverFrame.delayThenShow()"); notify(); } @Override public synchronized void run() { while (running) { try { //TraceSlots.rolloverRaiseStatus = 3000; // wait for the next request //Debug.println("RaiseMonitor.run() wait()"); wait(); if (!running) break; TraceSlots.rolloverRaiseStatus = 3001; //Debug.println("RaiseMonitor.run() take waitingLock"); synchronized (waitingLock) { waitingToDoRun = true; // println("RolloverFrame.run() waitingLock.wait(RAISE_ABOUT_DELAY)"); TraceSlots.rolloverRaiseStatus = 3002; // wait for a little delay before raising waitingLock.wait(raiseDelay); if (running == false) break; //println("run() waitingToDoRun="+waitingToDoRun); if (waitingToDoRun) { waitingToDoRun = false; TraceSlots.rolloverRaiseStatus = 3003; doRaise(); TraceSlots.rolloverRaiseStatus = 3004; } else // waitingToDoRun changed asychronously by cancel() { TraceSlots.rolloverRaiseStatus = 3005; //cancelRaise(); //oneAndOnly.showEmbellishments = false; } } //Debug.println("RaiseMonitor.run() released waitingLock"); } catch (Exception e) { if (running) e.printStackTrace(); } } } protected abstract void doRaise(); protected abstract void cancelRaise(); public void setRaiseDelay(int raiseDelay) { this.raiseDelay = raiseDelay; } /** * If a request to raise the object is pending, cancel it. */ public boolean cancel() { synchronized (waitingLock) { boolean result = waitingToDoRun; if (waitingToDoRun) { cancelRaise(); waitingToDoRun = false; waitingLock.notify(); } return result; } } /** * Checks if RaiseMonitor is currently waiting to execute doRaise() * @return true if it is waiting. false if it is not. */ public boolean waitingToDoRun() { return waitingToDoRun; } public Object waitingLock() { return waitingLock; } public boolean isRunning() { return running; } }