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
* 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;
import java.util.ArrayList;
/**
* @author Joakim Eriksson (ported to COOJA by Fredrik Österlind)
*/
@ -40,9 +42,30 @@ public class EventQueue {
private long nextTime;
private int eventCount = 0;
private ArrayList<TimeEvent> pendingEvents = new ArrayList<TimeEvent>();
private boolean hasPendingEvents = false;
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) {
event.time = time;
addEvent(event);
@ -118,6 +141,10 @@ public class EventQueue {
}
public TimeEvent popFirst() {
if (hasPendingEvents) {
handlePendingEvents();
}
TimeEvent tmp = first;
if (tmp == null) {
return null;

View file

@ -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.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;
@ -68,7 +68,7 @@ public class Simulation extends Observable implements Runnable {
private boolean stopSimulation = false;
private Thread thread = null;
private Thread simulationThread = null;
private GUI myGUI = null;
@ -111,6 +111,11 @@ public class Simulation extends Observable implements Runnable {
tickObservable.deleteObserver(observer);
}
protected void scheduleEventUnsafe(TimeEvent e, long time) {
eventQueue.addEvent(e, time);
}
/**
* Schedule event to be handled by event loop.
*
@ -118,7 +123,11 @@ public class Simulation extends Observable implements Runnable {
* @param time Simulated time
*/
public void scheduleEvent(TimeEvent e, long time) {
eventQueue.addEvent(e, time);
if (Thread.currentThread() == simulationThread) {
eventQueue.addEvent(e, time);
} else {
eventQueue.addPendingEvent(e, time);
}
}
private EventQueue eventQueue = new EventQueue();
@ -144,7 +153,7 @@ public class Simulation extends Observable implements Runnable {
}
/* 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 */
scheduleEvent(this, t+1);
scheduleEventUnsafe(this, t+1);
}
};
private TimeEvent delayEvent = new TimeEvent(0) {
public void execute(long t) {
/*logger.info("Delay at: " + t);*/
if (delayTime == 0)
if (delayTime == 0) {
return;
}
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;
/* Schedule tick events */
scheduleEvent(tickMotesEvent, currentSimulationTime);
scheduleEvent(tickMspMotesEvent, currentSimulationTime);
scheduleEvent(delayEvent, currentSimulationTime);
scheduleEventUnsafe(tickMotesEvent, currentSimulationTime);
scheduleEventUnsafe(tickMspMotesEvent, currentSimulationTime);
scheduleEventUnsafe(delayEvent, currentSimulationTime);
/* Simulation starting */
this.setChanged();
@ -212,9 +222,9 @@ public class Simulation extends Observable implements Runnable {
if (rescheduleEvents) {
rescheduleEvents = false;
scheduleEvent(tickMotesEvent, currentSimulationTime);
scheduleEvent(tickMspMotesEvent, currentSimulationTime);
scheduleEvent(delayEvent, currentSimulationTime);
scheduleEventUnsafe(tickMotesEvent, currentSimulationTime);
scheduleEventUnsafe(tickMspMotesEvent, currentSimulationTime);
scheduleEventUnsafe(delayEvent, currentSimulationTime);
}
nextEvent = eventQueue.popFirst();
@ -249,7 +259,7 @@ public class Simulation extends Observable implements Runnable {
}
}
isRunning = false;
thread = null;
simulationThread = null;
stopSimulation = false;
// Notify observers simulation has stopped
@ -275,8 +285,8 @@ public class Simulation extends Observable implements Runnable {
public void startSimulation() {
if (!isRunning()) {
isRunning = true;
thread = new Thread(this);
thread.start();
simulationThread = new Thread(this);
simulationThread.start();
}
}
@ -288,10 +298,10 @@ public class Simulation extends Observable implements Runnable {
stopSimulation = true;
/* Wait until simulation stops */
if (Thread.currentThread() != thread) {
if (Thread.currentThread() != simulationThread) {
try {
if (thread != null) {
thread.join();
if (simulationThread != null) {
simulationThread.join();
}
} catch (InterruptedException e) {
}
@ -783,7 +793,7 @@ public class Simulation extends Observable implements Runnable {
* @return True if simulation is running
*/
public boolean isRunning() {
return isRunning && thread != null;
return isRunning && simulationThread != null;
}
/**