removed tick lists and variable tick times

handling tick events in simulation loop: moving towards fully event based (as opposed to tick based)
This commit is contained in:
fros4943 2008-10-28 13:35:59 +00:00
parent 5c2d5940ed
commit 456ef03dc1

View file

@ -24,7 +24,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * 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; package se.sics.cooja;
@ -38,17 +38,13 @@ import se.sics.cooja.dialogs.*;
/** /**
* A simulation consists of a number of motes and mote types. * 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 * The motes in the simulation are ticked every millisecond.
* 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.
* *
* When observing the simulation itself, the simulation state, added or deleted * A simulation is observable:
* motes etc. are observed, as opposed to individual mote changes. Changes of * changed simulation state, added or deleted motes etc are observed.
* individual motes should instead be observed via corresponding mote * To track mote changes, observe the mote (interfaces) itself.
* interfaces.
* *
* @author Fredrik Osterlind * @author Fredrik Österlind
*/ */
public class Simulation extends Observable implements Runnable { public class Simulation extends Observable implements Runnable {
@ -78,14 +74,8 @@ public class Simulation extends Observable implements Runnable {
private long randomSeed = 123456; private long randomSeed = 123456;
private int currentTickListIndex = 0;
private int nrTickLists = 1;
private int maxMoteStartupDelay = 1000; private int maxMoteStartupDelay = 1000;
private Random tickListRandom = new Random();
private Random delayMotesRandom = new Random(); private Random delayMotesRandom = new Random();
// Tick observable // Tick observable
@ -121,97 +111,106 @@ public class Simulation extends Observable implements Runnable {
tickObservable.deleteObserver(observer); 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() { public void run() {
long lastStartTime = System.currentTimeMillis(); long lastStartTime = System.currentTimeMillis();
logger.info("Simulation main loop started, system time: " + lastStartTime); logger.info("Simulation main loop started, system time: " + lastStartTime);
isRunning = true; isRunning = true;
// Notify observers simulation is starting /* Simulation starting */
this.setChanged(); this.setChanged();
this.notifyObservers(this); this.notifyObservers(this);
/* Experimental: Tick MSP motes separately */ /* Tick MSP motes separately */
ArrayList<Mote> mspMotes = new ArrayList<Mote>(); ArrayList<Mote> mspMotes = new ArrayList<Mote>();
ArrayList<Mote> contikiMotes = new ArrayList<Mote>();
for (Mote mote: motes) { for (Mote mote: motes) {
if (mote.getType().getClass().toString().contains(".mspmote.")) { if (mote.getType().getClass().toString().contains(".mspmote.")) {
mspMotes.add(mote); 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<Mote> motesClone = new Vector<Mote>();
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 { try {
while (isRunning) { while (isRunning) {
/* Tick MSP motes */ TimeEvent nextEvent = eventQueue.popFirst();
// try { if (nextEvent == null) {
boolean wantMoreTicks = true; throw new RuntimeException("No more events");
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);
} }
// Select next mote subset (persistent) currentSimulationTime = nextEvent.time;
currentTickListIndex++; nextEvent.execute(currentSimulationTime);
if (currentTickListIndex >= nrTickLists) {
currentTickListIndex = 0;
}
// Increase simulation time /* Notify tick observers */
currentSimulationTime += tickTime;
// Notify tick observers
tickObservable.allTicksPerformed(); tickObservable.allTicksPerformed();
// Sleep
if (delayTime > 0) {
Thread.sleep(delayTime);
}
if (stopSimulation) { if (stopSimulation) {
isRunning = false; isRunning = false;
} }
} }
} catch (InterruptedException e) {
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
logger.warn("llegalArgumentException:" + e); logger.warn("llegalArgumentException:" + e);
} catch (IllegalMonitorStateException e) { } catch (IllegalMonitorStateException e) {
@ -238,6 +237,13 @@ public class Simulation extends Observable implements Runnable {
public Simulation(GUI gui) { public Simulation(GUI gui) {
myGUI = gui; myGUI = gui;
delayMotesRandom.setSeed(randomSeed); 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; 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 * @return Maximum mote startup delay
*/ */
@ -373,11 +365,6 @@ public class Simulation extends Observable implements Runnable {
element.setText(Long.toString(randomSeed)); element.setText(Long.toString(randomSeed));
config.add(element); config.add(element);
// Number of tick lists
element = new Element("nrticklists");
element.setText(Integer.toString(nrTickLists));
config.add(element);
// Max mote startup delay // Max mote startup delay
element = new Element("motedelay"); element = new Element("motedelay");
element.setText(Integer.toString(maxMoteStartupDelay)); element.setText(Integer.toString(maxMoteStartupDelay));
@ -460,11 +447,6 @@ public class Simulation extends Observable implements Runnable {
delayMotesRandom.setSeed(randomSeed); delayMotesRandom.setSeed(randomSeed);
} }
// Number of tick lists
if (element.getName().equals("nrticklists")) {
nrTickLists = Integer.parseInt(element.getText());
}
// Max mote startup delay // Max mote startup delay
if (element.getName().equals("motedelay")) { if (element.getName().equals("motedelay")) {
maxMoteStartupDelay = Integer.parseInt(element.getText()); maxMoteStartupDelay = Integer.parseInt(element.getText());
@ -671,6 +653,8 @@ public class Simulation extends Observable implements Runnable {
public void setDelayTime(int delayTime) { public void setDelayTime(int delayTime) {
this.delayTime = delayTime; this.delayTime = delayTime;
scheduleEvent(delayEvent, currentSimulationTime);
this.setChanged(); this.setChanged();
this.notifyObservers(this); this.notifyObservers(this);
} }