thread-safe event scheduling

This commit is contained in:
fros4943 2008-12-08 13:07:06 +00:00
parent 34829fe41e
commit c4ba4b7008
2 changed files with 58 additions and 21 deletions

View file

@ -26,11 +26,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: EventQueue.java,v 1.2 2008/12/04 14:03:42 joxe Exp $ * $Id: EventQueue.java,v 1.3 2008/12/08 13:07:32 fros4943 Exp $
*/ */
package se.sics.cooja; package se.sics.cooja;
import java.util.ArrayList;
/** /**
* @author Joakim Eriksson (ported to COOJA by Fredrik Österlind) * @author Joakim Eriksson (ported to COOJA by Fredrik Österlind)
*/ */
@ -40,9 +42,30 @@ public class EventQueue {
private long nextTime; private long nextTime;
private int eventCount = 0; private int eventCount = 0;
private ArrayList<TimeEvent> pendingEvents = new ArrayList<TimeEvent>();
private boolean hasPendingEvents = false;
public EventQueue() { public EventQueue() {
} }
public synchronized void addPendingEvent(TimeEvent event, long time) {
event.time = time;
pendingEvents.add(event);
hasPendingEvents = true;
}
private synchronized void handlePendingEvents() {
if (!hasPendingEvents) {
return;
}
for (TimeEvent e: pendingEvents) {
addEvent(e);
}
pendingEvents.clear();
hasPendingEvents = false;
}
public void addEvent(TimeEvent event, long time) { public void addEvent(TimeEvent event, long time) {
event.time = time; event.time = time;
addEvent(event); addEvent(event);
@ -118,6 +141,10 @@ public class EventQueue {
} }
public TimeEvent popFirst() { public TimeEvent popFirst() {
if (hasPendingEvents) {
handlePendingEvents();
}
TimeEvent tmp = first; TimeEvent tmp = first;
if (tmp == null) { if (tmp == null) {
return null; return null;

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.35 2008/12/04 16:52:03 fros4943 Exp $ * $Id: Simulation.java,v 1.36 2008/12/08 13:07:06 fros4943 Exp $
*/ */
package se.sics.cooja; package se.sics.cooja;
@ -68,7 +68,7 @@ public class Simulation extends Observable implements Runnable {
private boolean stopSimulation = false; private boolean stopSimulation = false;
private Thread thread = null; private Thread simulationThread = null;
private GUI myGUI = null; private GUI myGUI = null;
@ -111,6 +111,11 @@ public class Simulation extends Observable implements Runnable {
tickObservable.deleteObserver(observer); tickObservable.deleteObserver(observer);
} }
protected void scheduleEventUnsafe(TimeEvent e, long time) {
eventQueue.addEvent(e, time);
}
/** /**
* Schedule event to be handled by event loop. * Schedule event to be handled by event loop.
* *
@ -118,7 +123,11 @@ public class Simulation extends Observable implements Runnable {
* @param time Simulated time * @param time Simulated time
*/ */
public void scheduleEvent(TimeEvent e, long time) { public void scheduleEvent(TimeEvent e, long time) {
if (Thread.currentThread() == simulationThread) {
eventQueue.addEvent(e, time); eventQueue.addEvent(e, time);
} else {
eventQueue.addPendingEvent(e, time);
}
} }
private EventQueue eventQueue = new EventQueue(); private EventQueue eventQueue = new EventQueue();
@ -144,7 +153,7 @@ public class Simulation extends Observable implements Runnable {
} }
/* Reschedule MSP motes */ /* Reschedule MSP motes */
scheduleEvent(this, t+1); scheduleEventUnsafe(this, t+1);
} }
}; };
@ -162,18 +171,19 @@ public class Simulation extends Observable implements Runnable {
} }
/* Reschedule Contiki motes */ /* Reschedule Contiki motes */
scheduleEvent(this, t+1); scheduleEventUnsafe(this, t+1);
} }
}; };
private TimeEvent delayEvent = new TimeEvent(0) { private TimeEvent delayEvent = new TimeEvent(0) {
public void execute(long t) { public void execute(long t) {
/*logger.info("Delay at: " + t);*/ /*logger.info("Delay at: " + t);*/
if (delayTime == 0) if (delayTime == 0) {
return; return;
}
try { Thread.sleep(delayTime); } catch (InterruptedException e) { } try { Thread.sleep(delayTime); } catch (InterruptedException e) { }
scheduleEvent(this, t+1); scheduleEventUnsafe(this, t+1);
} }
}; };
@ -184,9 +194,9 @@ public class Simulation extends Observable implements Runnable {
isRunning = true; isRunning = true;
/* Schedule tick events */ /* Schedule tick events */
scheduleEvent(tickMotesEvent, currentSimulationTime); scheduleEventUnsafe(tickMotesEvent, currentSimulationTime);
scheduleEvent(tickMspMotesEvent, currentSimulationTime); scheduleEventUnsafe(tickMspMotesEvent, currentSimulationTime);
scheduleEvent(delayEvent, currentSimulationTime); scheduleEventUnsafe(delayEvent, currentSimulationTime);
/* Simulation starting */ /* Simulation starting */
this.setChanged(); this.setChanged();
@ -212,9 +222,9 @@ public class Simulation extends Observable implements Runnable {
if (rescheduleEvents) { if (rescheduleEvents) {
rescheduleEvents = false; rescheduleEvents = false;
scheduleEvent(tickMotesEvent, currentSimulationTime); scheduleEventUnsafe(tickMotesEvent, currentSimulationTime);
scheduleEvent(tickMspMotesEvent, currentSimulationTime); scheduleEventUnsafe(tickMspMotesEvent, currentSimulationTime);
scheduleEvent(delayEvent, currentSimulationTime); scheduleEventUnsafe(delayEvent, currentSimulationTime);
} }
nextEvent = eventQueue.popFirst(); nextEvent = eventQueue.popFirst();
@ -249,7 +259,7 @@ public class Simulation extends Observable implements Runnable {
} }
} }
isRunning = false; isRunning = false;
thread = null; simulationThread = null;
stopSimulation = false; stopSimulation = false;
// Notify observers simulation has stopped // Notify observers simulation has stopped
@ -275,8 +285,8 @@ public class Simulation extends Observable implements Runnable {
public void startSimulation() { public void startSimulation() {
if (!isRunning()) { if (!isRunning()) {
isRunning = true; isRunning = true;
thread = new Thread(this); simulationThread = new Thread(this);
thread.start(); simulationThread.start();
} }
} }
@ -288,10 +298,10 @@ public class Simulation extends Observable implements Runnable {
stopSimulation = true; stopSimulation = true;
/* Wait until simulation stops */ /* Wait until simulation stops */
if (Thread.currentThread() != thread) { if (Thread.currentThread() != simulationThread) {
try { try {
if (thread != null) { if (simulationThread != null) {
thread.join(); simulationThread.join();
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
} }
@ -783,7 +793,7 @@ public class Simulation extends Observable implements Runnable {
* @return True if simulation is running * @return True if simulation is running
*/ */
public boolean isRunning() { public boolean isRunning() {
return isRunning && thread != null; return isRunning && simulationThread != null;
} }
/** /**