super.fire();
if (_throwable != null) {
Throwable throwable = _throwable;
_throwable = null;
throw new IllegalActionException(this, throwable,
"Run in a new thread threw an exception "
+ "on the previous firing.");
}
// Read the inputs. This should be done even if there is
// no model.
// Derived classes may need to read inputs earlier in their
// fire() method, before calling this class, in which case
// they are expected to set this flag to true.
if (!_alreadyReadInputs) {
// Iterate over input ports and read any available values
// into the referenced model parameters and validate
// settable attributes.
_readInputsAndValidateSettables();
}
// Set the flag to false for the next firing.
_alreadyReadInputs = false;
if (_model instanceof CompositeActor) {
CompositeActor executable = (CompositeActor) _model;
_manager = executable.getManager();
if (_manager == null) {
throw new InternalErrorException("No manager!");
}
if (_debugging) {
_manager.addDebugListener(this);
Director director = executable.getDirector();
if (director != null) {
director.addDebugListener(this);
}
} else {
_manager.removeDebugListener(this);
Director director = executable.getDirector();
if (director != null) {
director.removeDebugListener(this);
}
}
// If there is a previous execution, then wait for it to finish.
// Avoid the synchronize block if possible.
if (_executing) {
synchronized (this) {
while (_executing) {
try {
if (_debugging) {
_debug("** Waiting for previous execution to finish.");
}
// Use workspace version of wait to release
// read permission on the workspace.
workspace().wait(this);
} catch (InterruptedException ex) {
// Cancel subsequent execution.
getManager().finish();
return;
}
}
if (_debugging) {
_debug("** Previous execution has finished.");
}
}
}
if (_executionOnFiringValue == _RUN_IN_CALLING_THREAD) {
if (_debugging) {
_debug("** Executing referenced model in the calling thread.");
}
try {
_manager.execute();
} catch (KernelException ex) {
throw new IllegalActionException(this, ex,
"Execution failed.");
}
_writeOutputs();
} else if (_executionOnFiringValue == _RUN_IN_A_NEW_THREAD) {
// Listen for exceptions. The listener is
// removed in the listener methods, executionError()
// and executionFinished().
if (_debugging) {
_debug("** Creating a new thread to execute the model.");
}
_manager.addExecutionListener(this);
// Create a thread. Can't directly use _manager.startRun()
// because we need to write outputs upon completion.
if (_manager.getState() != Manager.IDLE) {
throw new IllegalActionException(this,
"Cannot start an execution. "
+ "Referenced model is "
+ _manager.getState().getDescription());
}