|
From: Nick C. <nic...@ve...> - 2003-02-21 18:26:44
|
Thanks for this. I read it quickly, and it seems like a good unification. I'll have to check whether it is possible to unify begin(), display() etc. under this one method. Last time you asked it wasn't. After the refactoring of the controller hierarchy this should now, hopefully, be feasible, so thanks for bringing it up. As for exit(). This is a bug, I think. There used to be a flag for really exiting or just shutting down repast on exit. I think I moved this too far up up the hierarchy during the refactoring and so its no longer available to thin controller. I'll push it back down. This does raise the question though of what should supplied by repast and what should be overridden by a user in a child class. exit() is not an example of this however. Nick On Fri, 2003-02-21 at 13:03, Mark R. Diggory wrote: > Nick, > > I've added an extra method to the version of ThinController I am using > currently, I think it would be a nice addition to the class itself. > Specifically, I am providing an "initSim()" method, analogous to > "begin()" in the BatchController. This method provides just enought > rudimentary threading control to get the simulation launched in a new > Thread and wait for it to complete. I did this so I would not need to do > "thread management" in my taglibrary wrapper for the controller and I > can just rely on the threading available in the ThinController to get > the simulation started and wait until its finished before returning from > the initSim method. This should allow my taglibrary to support any > controller. (as you can see by my examples: models/cagn and models/simple). > > However, I still find myself having to call different methods to get the > controller "initialized". Consolidating > Controller.display(),BatchController.begin() and > ThinController.initSim() into one standard method in the IController > interface would provide for a consistent way to initialize the > controller across all controllers. It could be backward compatable for > the time being by just creating an initSim method in the IController and > BaseController, then overriding it in Controller and BatchController > with calls to display or begin. Eventually, > uchicago.src.sim.engine.SimInit could be modified to use the new initSim > method and there would no longer be the need to determine what type the > controller was just to get it initialized/running. I think we had > discussed this before, though I can't recall your response. > > If ThinController.initSim() seems like the "wrong" name for this method, > I'm not attached to it. > > One other thing, in this situation I find the System.exit() call in the > ThinController.exitSim() results in the shutdown of the entire JVM, if > I'm using it in the Jelly env. where I might want to do post processing > after the exitSim occurs I loose the JVM instance before I can do those > things. I've been commenting it out in my version. Since it is a method > available from "System" I'm concerned about it being in the Controller, > specifically because, if the user of ThinController is either doing > thier own Thread Management or relying on initSim() for this, they can > decide if they want to do a System.exit() after exitSim occures in thier > code. Having it in the exitSim method, they loose that flexibility. > > Thanks > -Mark > ---- > > /** > * Provides minimal (thin) controller support for running a simulation. > * ThinController is intended to provide batch-like non-gui programmatic control over > * a simulation for those who want to do batch type runs without using > * RePast's batch run mechansim. Thin controller thus provides methods to > * start, stop, pause and exit a simulation, but virtually nothing else. In > * particular loading parameters into a model is not done here. Loading > * parameters using some sort of custom parameter file or mechanism will have > * to be done elsewhere.<p> > * > * ThinController can be used in conjuntion with a tool like Drone (drone.sf.net) > * where an instance of the model and a controller are created for each run > * of the model. The main method of a model might then look like: > * <pre><code> > * public static void main( String[] args ) { > * MyModel model = new MyModel(); > * ThinController controller = new ThinController(); > * model.setController(controller); > * controller.setExitOnExit(true); > * controller.setModel(model); > * model.addSimEventListener(controller); > * // custom parameter loading here ... > * ... > * control.startSimulation(); > * } > * </code></pre> > * > * @version $Revision: 1.7 $ $Date: 2003/01/03 16:41:04 $ > * > */ > package uchicago.src.sim.engine; > > public class ThinController extends BaseController { > > protected volatile boolean finished = false; > > private Object appMonitor = new Object(); > > protected boolean isGui; > > /** > * Creates a ThinController, specifying whether this is a graphical controller > * or not. The isGui parameter only determines what value is returned by the > * isGUI method, nothing more. > * > * @param isGui whether or not this ThinController will identify itself as > * a gui controller or not > */ > public ThinController(boolean isGui) { > super(); > this.isGui = isGui; > } > > /* Gives just enough rudimentary threading control to launch the sim in a > * new thread > */ > public void initSim() { > Runnable control = new Runnable() { > public void run() { > startSim(); > while (!finished) { > synchronized (monitor) { > while (!runFinished) { > try { > monitor.wait(); > } catch (InterruptedException ex) { > } > } > } > > stopSim(); > finished = true; > > } > synchronized (appMonitor) { > appMonitor.notify(); > } > } > }; > > Thread t = new Thread(control); > t.start(); > synchronized (appMonitor) { > while (!finished) { > try { > appMonitor.wait(); > } catch (InterruptedException ex) { > } > } > } > exitSim(); > } > > /** > * Exits a simulation. > */ > public void exitSim() { > stopSim(); > if (runThread != null) { > runThread.interrupt(); > try { > runThread.join(); > } catch (InterruptedException ex) { > System.out.println("Interrupted"); > } > } > > fireSimEvent(new SimEvent(this, SimEvent.END_EVENT)); > /* not so good a decision when the controller exists in the root thread of > * JVM, users may want to exit the sim without shutting down the JVM > */ > //System.exit(0); > } > > protected void onTickCountUpdate() {} > > /** > * Listens for SimEvents and responds accordingly. > * @param evt > */ > public void simEventPerformed(SimEvent evt) { > if (evt.getId() == SimEvent.STOP_EVENT) { > stopSim(); > } else if (evt.getId() == SimEvent.END_EVENT) { > exitSim(); > } else if (evt.getId() == SimEvent.PAUSE_EVENT) { > pauseSim(); > } > } > > /** > * Returns true if this ThinController is a gui controller. The actual > * value returned depends the value passed to the contructor. > */ > public boolean isGUI() { > return isGui; > } > > /** > * Returns true if this ThinController is a batch controller. The actual > * value returned depends the value passed to the contructor. > */ > public boolean isBatch() { > return !isGui; > } > > /** > * Always returns 1. > */ > public long getRunCount() { > return 1; > } > } > -- Nick Collier Social Science Research Computing University of Chicago http://repast.sourceforge.net |