// TESTIT
if (actorToFire == null) {
// If the actorToFire is not set yet,
// find the actor associated with the event just found,
// and update the current tag with the event tag.
Time currentTime;
if (_synchronizeToRealTime) {
// If synchronized to the real time.
synchronized (_eventQueue) {
while (!_stopRequested && !_stopFireRequested) {
lastFoundEvent = _eventQueue.get();
currentTime = lastFoundEvent.timeStamp();
long elapsedTime = System.currentTimeMillis()
- _realStartTime;
// NOTE: We assume that the elapsed time can be
// safely cast to a double. This means that
// the DE domain has an upper limit on running
// time of Double.MAX_VALUE milliseconds.
double elapsedTimeInSeconds = elapsedTime / 1000.0;
ptolemy.actor.util.Time elapsed
= new ptolemy.actor.util.Time(this, elapsedTimeInSeconds);
if (currentTime.compareTo(elapsed) <= 0) {
break;
}
// NOTE: We used to do the following, but it had a limitation.
// In particular, if any user code also calculated the elapsed
// time and then constructed a Time object to post an event
// on the event queue, there was no assurance that the quantization
// would be the same, and hence it was possible for that event
// to be in the past when posted, even if done in the same thread.
// To ensure that the comparison of current time against model time
// always yields the same result, we have to do the comparison using
// the Time class, which is what the event queue does.
/*
if (currentTime.getDoubleValue() <= elapsedTimeInSeconds) {
break;
}*/
long timeToWait = (long) (currentTime.subtract(
elapsed).getDoubleValue() * 1000.0);
if (timeToWait > 0) {
if (_debugging) {
_debug("Waiting for real time to pass: "
+ timeToWait);
}
try {
// NOTE: The built-in Java wait() method
// does not release the
// locks on the workspace, which would block
// UI interactions and may cause deadlocks.
// SOLUTION: workspace.wait(object, long).
_workspace.wait(_eventQueue, timeToWait);
// If we get here and either stop() or stopFire()
// was called, then it is not time to process any event,
// so we should leave it in the event queue.
if (_stopRequested || _stopFireRequested) {
return null;
}
} catch (InterruptedException ex) {
// Continue executing.
}
}
} // while
} // sync
} // if (_synchronizeToRealTime)
// Consume the earliest event from the queue. The event must be
// obtained here, since a new event could have been enqueued
// into the queue while the queue was waiting. For example,
// an IO interrupt event.
// FIXME: The above statement is misleading. How could the
// newly inserted event happen earlier than the previously
// first event in the queue? It may be possible in the
// distributed DE models, but should not happen in DE models.
// Will this cause problems, such as setting time backwards?
// TESTIT How to??
synchronized (_eventQueue) {
lastFoundEvent = _eventQueue.take();
currentTime = lastFoundEvent.timeStamp();
actorToFire = lastFoundEvent.actor();
// NOTE: The _enqueueEvent method discards the events
// for disabled actors.
if ((_disabledActors != null)
&& _disabledActors.contains(actorToFire)) {
// This actor has requested not to be fired again.
if (_debugging) {
_debug("Skipping disabled actor: ",
((Nameable) actorToFire).getFullName());
}
actorToFire = null;
// start a new iteration of the loop:
// LOOPLABEL::GetNextEvent
continue;
}
// Advance the current time to the event time.
// NOTE: This is the only place that the model time changes.
setModelTime(currentTime);
// Advance the current microstep to the event microstep.
_microstep = lastFoundEvent.microstep();
}
// Exceeding stop time means the current time is strictly
// bigger than the model stop time.
if (currentTime.compareTo(getModelStopTime()) > 0) {
if (_debugging) {
_debug("Current time has passed the stop time.");
}
_exceedStopTime = true;