From 456ef03dc19965bac434a8b0f01ca9d524ef694b Mon Sep 17 00:00:00 2001 From: fros4943 Date: Tue, 28 Oct 2008 13:35:59 +0000 Subject: [PATCH] removed tick lists and variable tick times handling tick events in simulation loop: moving towards fully event based (as opposed to tick based) --- .../cooja/java/se/sics/cooja/Simulation.java | 196 ++++++++---------- 1 file changed, 90 insertions(+), 106 deletions(-) diff --git a/tools/cooja/java/se/sics/cooja/Simulation.java b/tools/cooja/java/se/sics/cooja/Simulation.java index 5bd817157..a29ec0128 100644 --- a/tools/cooja/java/se/sics/cooja/Simulation.java +++ b/tools/cooja/java/se/sics/cooja/Simulation.java @@ -24,7 +24,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: Simulation.java,v 1.26 2008/10/03 13:18:29 fros4943 Exp $ + * $Id: Simulation.java,v 1.27 2008/10/28 13:35:59 fros4943 Exp $ */ package se.sics.cooja; @@ -38,17 +38,13 @@ import se.sics.cooja.dialogs.*; /** * A simulation consists of a number of motes and mote types. * - * The motes in the simulation are ticked one by one in a simulation loop. When - * all motes have been ticked once, the simulation time is updated and then the - * simulation sleeps for some specified delay time. Any tick observers are also - * notified at this time. + * The motes in the simulation are ticked every millisecond. * - * When observing the simulation itself, the simulation state, added or deleted - * motes etc. are observed, as opposed to individual mote changes. Changes of - * individual motes should instead be observed via corresponding mote - * interfaces. + * A simulation is observable: + * changed simulation state, added or deleted motes etc are observed. + * To track mote changes, observe the mote (interfaces) itself. * - * @author Fredrik Osterlind + * @author Fredrik Österlind */ public class Simulation extends Observable implements Runnable { @@ -78,14 +74,8 @@ public class Simulation extends Observable implements Runnable { private long randomSeed = 123456; - private int currentTickListIndex = 0; - - private int nrTickLists = 1; - private int maxMoteStartupDelay = 1000; - private Random tickListRandom = new Random(); - private Random delayMotesRandom = new Random(); // Tick observable @@ -121,97 +111,106 @@ public class Simulation extends Observable implements Runnable { tickObservable.deleteObserver(observer); } + /** + * Schedule event to be handled by event loop. + * + * @param e Event + * @param time Simulated time + */ + public void scheduleEvent(TimeEvent e, int time) { + eventQueue.addEvent(e, time); + } + + private EventQueue eventQueue = new EventQueue(); + + private Mote[] mspMoteArray; + private TimeEvent tickMspMotesEvent = new TimeEvent(0) { + public void execute(int t) { + /*logger.info("MSP motes tick at: " + t);*/ + + /* Tick MSP motes */ + boolean wantMoreTicks = true; + while (wantMoreTicks) { + /* Tick all MSP motes until none need more ticks */ + wantMoreTicks = false; + for (Mote element : mspMoteArray) { + if (element.tick(currentSimulationTime)) { + wantMoreTicks = true; + } + } + } + + /* Reschedule MSP motes */ + scheduleEvent(this, t+1); + } + }; + + private Mote[] moteArray; + private TimeEvent tickMotesEvent = new TimeEvent(0) { + public void execute(int t) { + /*logger.info("Contiki motes tick at: " + t);*/ + + /* Tick Contiki motes */ + for (Mote mote : moteArray) { + mote.tick(t); + } + + /* Reschedule Contiki motes */ + scheduleEvent(this, t+1); + } + }; + + private TimeEvent delayEvent = new TimeEvent(0) { + public void execute(int t) { + /*logger.info("Delay at: " + t);*/ + + if (delayTime > 0) { + try { Thread.sleep(delayTime); } catch (InterruptedException e) { } + scheduleEvent(this, t+1); + } + } + }; + public void run() { long lastStartTime = System.currentTimeMillis(); logger.info("Simulation main loop started, system time: " + lastStartTime); isRunning = true; - // Notify observers simulation is starting + /* Simulation starting */ this.setChanged(); this.notifyObservers(this); - /* Experimental: Tick MSP motes separately */ + /* Tick MSP motes separately */ ArrayList mspMotes = new ArrayList(); + ArrayList contikiMotes = new ArrayList(); for (Mote mote: motes) { if (mote.getType().getClass().toString().contains(".mspmote.")) { mspMotes.add(mote); + } else { + contikiMotes.add(mote); } } + mspMoteArray = mspMotes.toArray(new Mote[mspMotes.size()]); + moteArray = contikiMotes.toArray(new Mote[mspMotes.size()]); - // Distribute motes in tick lists according to random seed - // TODO Timeconsuming approach (but only performed once) - int motesToDistribute = motes.size() - mspMotes.size(); - Mote[][] allLists = new Mote[nrTickLists][]; - for (int i=0; i < nrTickLists; i++) { - allLists[i] = new Mote[(int) Math.ceil((double)motesToDistribute/(double)(nrTickLists - i))]; - motesToDistribute -= allLists[i].length; - } - - // Distribute motes according to seed - tickListRandom.setSeed(randomSeed); - Vector motesClone = new Vector(); - for (Mote mote: motes) { - if (!mote.getType().getClass().toString().contains(".mspmote.")) { - motesClone.add(mote); - } - } - for (int i=0; i < allLists.length; i++) { - for (int j=0; j < allLists[i].length; j++) { - int moteNr = tickListRandom.nextInt(motesClone.size()); - allLists[i][j] = motesClone.remove(moteNr); - } - } - - Mote[] mspArray = mspMotes.toArray(new Mote[mspMotes.size()]); try { - while (isRunning) { + while (isRunning) { - /* Tick MSP motes */ -// try { - boolean wantMoreTicks = true; - while (wantMoreTicks) { - /* Tick all MSP motes until none need more ticks */ - wantMoreTicks = false; - for (int i = 0, n = mspArray.length; i < n; i++) { - if (mspArray[i].tick(currentSimulationTime)) { - wantMoreTicks = true; - } - } - } -// } catch (RuntimeException e) { -// isRunning = false; -// thread = null; -// break; -// } - - // Tick current mote subset - for (Mote moteToTick : allLists[currentTickListIndex]) { - moteToTick.tick(currentSimulationTime); + TimeEvent nextEvent = eventQueue.popFirst(); + if (nextEvent == null) { + throw new RuntimeException("No more events"); } - // Select next mote subset (persistent) - currentTickListIndex++; - if (currentTickListIndex >= nrTickLists) { - currentTickListIndex = 0; - } + currentSimulationTime = nextEvent.time; + nextEvent.execute(currentSimulationTime); - // Increase simulation time - currentSimulationTime += tickTime; - - // Notify tick observers + /* Notify tick observers */ tickObservable.allTicksPerformed(); - // Sleep - if (delayTime > 0) { - Thread.sleep(delayTime); - } - if (stopSimulation) { isRunning = false; } - - } - } catch (InterruptedException e) { + } } catch (IllegalArgumentException e) { logger.warn("llegalArgumentException:" + e); } catch (IllegalMonitorStateException e) { @@ -238,6 +237,13 @@ public class Simulation extends Observable implements Runnable { public Simulation(GUI gui) { myGUI = gui; delayMotesRandom.setSeed(randomSeed); + + /* XXX Remove me */ + scheduleEvent(tickMotesEvent, currentSimulationTime); + /* XXX Remove me */ + scheduleEvent(tickMspMotesEvent, currentSimulationTime); + /* XXX Remove me? */ + scheduleEvent(delayEvent, currentSimulationTime); } /** @@ -314,20 +320,6 @@ public class Simulation extends Observable implements Runnable { this.randomSeed = randomSeed; } - /** - * @return Number of tick lists - */ - public int getNrTickLists() { - return nrTickLists; - } - - /** - * @param nrTickLists Number of tick lists - */ - public void setNrTickLists(int nrTickLists) { - this.nrTickLists = Math.max(1, nrTickLists); - } - /** * @return Maximum mote startup delay */ @@ -373,11 +365,6 @@ public class Simulation extends Observable implements Runnable { element.setText(Long.toString(randomSeed)); config.add(element); - // Number of tick lists - element = new Element("nrticklists"); - element.setText(Integer.toString(nrTickLists)); - config.add(element); - // Max mote startup delay element = new Element("motedelay"); element.setText(Integer.toString(maxMoteStartupDelay)); @@ -460,11 +447,6 @@ public class Simulation extends Observable implements Runnable { delayMotesRandom.setSeed(randomSeed); } - // Number of tick lists - if (element.getName().equals("nrticklists")) { - nrTickLists = Integer.parseInt(element.getText()); - } - // Max mote startup delay if (element.getName().equals("motedelay")) { maxMoteStartupDelay = Integer.parseInt(element.getText()); @@ -671,6 +653,8 @@ public class Simulation extends Observable implements Runnable { public void setDelayTime(int delayTime) { this.delayTime = delayTime; + scheduleEvent(delayEvent, currentSimulationTime); + this.setChanged(); this.notifyObservers(this); }