|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES All Classes | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectptolemy.kernel.util.NamedObj
ptolemy.kernel.util.Attribute
ptolemy.actor.Director
ptolemy.domains.de.kernel.DEDirector
public class DEDirector
This director implements the discrete-event (DE) model of computation (MoC). It should be used as the local director of a CompositeActor that is to be executed according to the DE MoC. This director maintains a totally ordered set of events and processes these events in the order defined on their tags and depths.
An event is associated with a tag, which is a tuple of timestamp and
microstep. A timestamp indicates the model time when this event occurs. It
is an object of the Time
class. A microstep is an
integer which represents the index of the sequence of execution phases when
this director processes events with the same timestamp. Two tags are equal
if they have the same timestamp and microstep. If two events have the same
tag, they are called simultaneous events.
Microsteps can only be increased by calling the fireAt() method. For example, when an actor requests to be fired again at the current model time, a new event with the same timestamp but a bigger microstep (incremented by 1) will be generated.
An event is also associated with a depth reflecting its priority, based on which a DE director chooses the execution order for simultaneous events. A depth is an integer and a larger value of depth indicates a lower priority. The depth of an event is determined by topologically sorting all the ports of actors according to their data dependencies over which there is no time delay.
The order of events is defined as follows. An event A is said to be earlier than another event B if A's timestamp is smaller than B's; or if A's timestamp is the same as B's, and A's microstep is smaller than B's; or if A's tag is the same as B's, and A's depth is smaller than B's. By giving events this well-defined order, this director can handle simultaneous events in a deterministic way.
The bottleneck in a typical DE simulator is in the maintenance of the
global event queue. This director uses the calendar queue as the global
event queue. This is an efficient algorithm with O(1) time complexity in
both enqueue and dequeue operations. Sorting in the
CalendarQueue
class is done according to the
order defined above.
The complexity of the calendar algorithm is sensitive to the length of the
event queue. When the size of the event queue becomes too long or changes
very often, the simulation performance suffers from the penalties of queuing
and dequeuing events. A few mechanisms are implemented to reduce such
penalties by keeping the event queue short. The first mechanism is to only
store in the event queue pure events and the trigger events
with the same timestamp and microstep as those of the director. See
DEEvent
for explanation of these two types of events. What is more,
no duplicate trigger events are allowed in the event queue. Another mechanism
is that in a hierarchical model, each level keeps a local event queue.
A lower level only reports the earliest event to its upper level
to schedule a future firing. The last mechanism is to maintain a list which
records all actors that are disabled. Any triggers sent to the actors in
this list are discarded.
In the initialize() method, depths of actors and IO ports are statically
analyzed and calculated. They are not calculated in the preinitialize()
method because hierarchical models may change their structures during their
preinitialize() method. For example, a modal model does not specify its
initial state (and its refinement) until the end of its preinitialize()
method. See FSMActor
. In order to support
mutation, this director recalculates the depths at the beginning of its next
iteration.
There are two types of depths: one is associated with IO ports, which
reflects the order of trigger events; the other one is associated with
actors, which is for pure events. The relationship between the depths of IO
ports and actors is that the depth of an actor is the smallest of the depths
of its IO ports. Pure events can only be produced by calling the fireAt()
method, and trigger events can only be produced by actors that produce
outputs. See DEReceiver.put(Token)
.
Directed loops of IO ports with no delay will trigger an exception.
These are called causality loops. Such loops can be broken with
actors whose output ports do not have an immediate dependence on their
input ports, such as the TimedDelay actor. Notice that the
TimedDelay actor breaks a causality loop even if the time
delay is set to 0.0. This is because DE uses a superdense
notion of time. The output is interpreted as being strictly later
than the input even though its time value is the same.
Whether a causality loop exists is determined by the
CausalityInterface
returned by each actor's
getCausalityInterface() method.
An input port in a DE model contains an instance of DEReceiver. When a token is put into a DEReceiver, that receiver posts a trigger event to the director. This director sorts trigger events in a global event queue.
An iteration, in the DE domain, is defined as processing all the events whose tags are equal to the current tag of the director (also called the model tag). At the beginning of the fire() method, this director dequeues a subset of the earliest events (the ones with smallest timestamp, microstep, and depth) that have the same destination actor from the global event queue. Then, this director fires that actor. This actor must consume tokens from its input port(s), and usually produces new events on its output port(s). These new events will trigger the destination actors to fire. It is important that the actor actually consumes tokens from its inputs, even if the tokens are solely used to trigger reactions, because the actor will be fired repeatedly until there are no more tokens in its input ports with the same tag, or until the actor returns false in its prefire() method. The director then keeps dequeuing and processing the earliest events from the event queue until no more events have the same tag. At that point, and only at that point, it invokes postfire() on all the actors that were fired during the iteration, and concludes the iteration. Note that under this policy, it is possible for an actor to be fired multiple times in an iteration prior to invocation of its postfire() method.
A model starts from the time specified by startTime, which has default value 0.0. The stop time of the execution can be set using the stopTime parameter. The parameter has a default value Infinity, which means the execution runs forever.
Execution of a DE model ends when the timestamp of the earliest event
exceeds the stop time. This stopping condition is checked inside
the postfire() method of this director. By default, execution also ends
when the global event queue becomes empty. Sometimes, the desired
behaviour is for the director to wait on an empty queue until another
thread makes new events available. For example, a DE actor may produce
events when a user hits a button on the screen. To prevent ending the
execution when there are no more events, set the
stopWhenQueueIsEmpty parameter to false
.
Parameters isCQAdaptive, minBinCount, and binCountFactor, are used to configure the calendar queue. Changes to these parameters are ignored when the model is running.
If the parameter synchronizeToRealTime is set to true
,
then the director will not process events until the real time elapsed
since the model started matches the timestamp of the event.
This ensures that the director does not get ahead of real time. However,
of course, this does not ensure that the director keeps up with real time.
This director tolerates changes to the model during execution. The change should be queued with a component in the hierarchy using requestChange(). While invoking those changes, the method invalidateSchedule() is expected to be called, notifying the director that the topology it used to calculate the priorities of the actors is no longer valid. This will result in the priorities (depths of actors) being recalculated the next time prefire() is invoked.
Yellow (hyzheng) |
Green (hyzheng) |
Nested Class Summary |
---|
Nested classes/interfaces inherited from class ptolemy.kernel.util.NamedObj |
---|
NamedObj.ContainedObjectsIterator |
Field Summary | |
---|---|
private boolean |
_delegateFireAt
Indicator that calls to fireAt() should be delegated to the executive director. |
protected java.util.Set<Actor> |
_disabledActors
The set of actors that have returned false in their postfire() methods. |
protected DEEventQueue |
_eventQueue
The queue used for sorting events. |
private boolean |
_exceedStopTime
Set to true when the time stamp of the token to be dequeue has exceeded the stopTime. |
protected boolean |
_isInitializing
A local boolean variable indicating whether this director is in initialization phase execution. |
protected int |
_microstep
The current microstep. |
protected boolean |
_noMoreActorsToFire
Set to true when it is time to end the execution. |
private long |
_realStartTime
The real time at which the model begins executing. |
private Time |
_startTime
Start time. |
protected boolean |
_stopFireRequested
Flag that stopFire() has been called. |
private Time |
_stopTime
Stop time. |
private boolean |
_stopWhenQueueIsEmpty
Decide whether the simulation should be stopped when there's no more events in the global event queue. |
private boolean |
_synchronizeToRealTime
Specify whether the director should wait for elapsed real time to catch up with model time. |
Parameter |
binCountFactor
The factor when adjusting the bin number. |
Parameter |
isCQAdaptive
Specify whether the calendar queue adjusts its bin number at run time. |
Parameter |
minBinCount
The minimum (initial) number of bins in the calendar queue. |
Parameter |
startTime
The start time of model. |
Parameter |
stopTime
The stop time of the model. |
Parameter |
stopWhenQueueIsEmpty
Specify whether the execution stops when the queue is empty. |
Parameter |
synchronizeToRealTime
Specify whether the execution should synchronize to the real time. |
Fields inherited from class ptolemy.actor.Director |
---|
_actorsFinishedExecution, _currentTime, _finishRequested, _initializables, _stopRequested, timeResolution |
Fields inherited from class ptolemy.kernel.util.NamedObj |
---|
_changeListeners, _changeLock, _changeRequests, _debugging, _debugListeners, _elementName, _isPersistent, _verbose, _workspace, ATTRIBUTES, CLASSNAME, COMPLETE, CONTENTS, DEEP, FULLNAME, LINKS |
Fields inherited from interface ptolemy.actor.Executable |
---|
COMPLETED, NOT_READY, STOP_ITERATING |
Constructor Summary | |
---|---|
DEDirector()
Construct a director in the default workspace with an empty string as its name. |
|
DEDirector(CompositeEntity container,
java.lang.String name)
Construct a director in the given container with the given name. |
|
DEDirector(Workspace workspace)
Construct a director in the workspace with an empty name. |
Method Summary | |
---|---|
protected void |
_disableActor(Actor actor)
Disable the specified actor. |
protected void |
_enqueueEvent(Actor actor,
Time time)
Put a pure event into the event queue to schedule the given actor to fire at the specified timestamp. |
protected void |
_enqueueTriggerEvent(IOPort ioPort)
Put a trigger event into the event queue. |
protected int |
_getDepthOfActor(Actor actor)
Return the depth of an actor. |
protected int |
_getDepthOfIOPort(IOPort ioPort)
Return the depth of an ioPort. |
protected Actor |
_getNextActorToFire()
Dequeue the events that have the smallest tag from the event queue. |
private void |
_initParameters()
initialize parameters. |
private void |
_requestFiring()
Request that the container of this director be refired in some future time specified by the first event of the local event queue. |
void |
addDebugListener(DebugListener listener)
Append the specified listener to the current set of debug listeners. |
void |
attributeChanged(Attribute attribute)
Update the director parameters when attributes are changed. |
java.lang.Object |
clone(Workspace workspace)
Clone the object into the specified workspace. |
Dependency |
delayDependency(double delay)
Return a boolean dependency representing a model-time delay of the specified amount. |
java.lang.String |
describePriorities()
Return a string that describes the depths of actors and their ports. |
void |
fire()
Advance the current model tag to that of the earliest event in the event queue, and fire all actors that have requested or are triggered to be fired at the current tag. |
Time |
fireAt(Actor actor,
Time time)
Schedule an actor to be fired at the specified time by posting a pure event to the director, and return the time at which the specified actor will be fired. |
void |
fireAtRelativeTime(Actor actor,
Time time)
Schedule an actor to be fired in the specified time relative to the current model time. |
DEEventQueue |
getEventQueue()
Return the event queue. |
int |
getIndex()
Return a superdense time index for the current time, where the index is equal to the microstep. |
int |
getMicrostep()
Get the current microstep. |
Time |
getModelNextIterationTime()
Return the timestamp of the next event in the queue. |
Time |
getModelStartTime()
Return the start time parameter value. |
Time |
getModelStopTime()
Return the stop time parameter value. |
long |
getRealStartTimeMillis()
Return the system time at which the model begins executing. |
double |
getStartTime()
Deprecated. As Ptolemy II 4.1, use getModelStartTime()
instead. |
double |
getStopTime()
Deprecated. As Ptolemy II 4.1, use getModelStopTime()
instead. |
void |
initialize()
Initialize all the contained actors by invoke the initialize() method of the super class. |
void |
invalidateSchedule()
Indicate that a schedule for the model may no longer be valid. |
Receiver |
newReceiver()
Return a new receiver of the type DEReceiver. |
boolean |
postfire()
Return false if there are no more actors to be fired or the stop() method has been called. |
boolean |
prefire()
Set the model timestamp to the outside timestamp if this director is not at the top level. |
void |
preinitialize()
Set the current timestamp to the model start time, invoke the preinitialize() methods of all actors deeply contained by the container. |
void |
removeDebugListener(DebugListener listener)
Unregister a debug listener. |
void |
setIndex(int index)
Set the superdense time index. |
void |
stop()
Request the execution of the current iteration to stop. |
void |
stopFire()
Request the execution of the current iteration to complete. |
java.lang.String[] |
suggestedModalModelDirectors()
Return an array of suggested directors to use with ModalModel. |
boolean |
transferOutputs(IOPort port)
Override the base class method to transfer all the available tokens at the boundary output port to outside. |
void |
wrapup()
Invoke the wrapup method of the super class. |
Methods inherited from class ptolemy.kernel.util.Attribute |
---|
_checkContainer, _getContainedObject, _propagateExistence, getContainer, moveDown, moveToFirst, moveToIndex, moveToLast, moveUp, setName, updateContent |
Methods inherited from class java.lang.Object |
---|
equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
Methods inherited from interface ptolemy.actor.TimedDirector |
---|
getModelTime, getTimeResolution |
Field Detail |
---|
public Parameter binCountFactor
public Parameter isCQAdaptive
public Parameter minBinCount
public Parameter startTime
public Parameter stopTime
public Parameter stopWhenQueueIsEmpty
public Parameter synchronizeToRealTime
protected java.util.Set<Actor> _disabledActors
protected DEEventQueue _eventQueue
protected boolean _isInitializing
protected int _microstep
protected boolean _noMoreActorsToFire
protected boolean _stopFireRequested
private boolean _delegateFireAt
private boolean _exceedStopTime
private long _realStartTime
private transient Time _startTime
private transient Time _stopTime
private boolean _stopWhenQueueIsEmpty
private boolean _synchronizeToRealTime
Constructor Detail |
---|
public DEDirector()
public DEDirector(Workspace workspace)
workspace
- The workspace of this object.public DEDirector(CompositeEntity container, java.lang.String name) throws IllegalActionException, NameDuplicationException
container
- Container of the director.name
- Name of this director.
IllegalActionException
- If the
director is not compatible with the specified container.
NameDuplicationException
- If the container not a
CompositeActor and the name collides with an entity in the container.Method Detail |
---|
public void addDebugListener(DebugListener listener)
addDebugListener
in interface Debuggable
addDebugListener
in class NamedObj
listener
- The listener to be added to the list of listeners
to which debug messages are sent.removeDebugListener(DebugListener)
public void attributeChanged(Attribute attribute) throws IllegalActionException
attributeChanged
in class Director
attribute
- The changed parameter.
IllegalActionException
- If the parameter set is not valid.
Not thrown in this class.public java.lang.Object clone(Workspace workspace) throws java.lang.CloneNotSupportedException
clone
in class Attribute
workspace
- The workspace for the cloned object.
java.lang.CloneNotSupportedException
- Not thrown in this base classNamedObj.exportMoML(Writer, int, String)
,
NamedObj.setDeferringChangeRequests(boolean)
public Dependency delayDependency(double delay)
delayDependency
in interface TimedDirector
delay
- A non-negative delay.
public java.lang.String describePriorities() throws IllegalActionException
IllegalActionException
- If there is a causality loop.public void fire() throws IllegalActionException
Each actor is fired repeatedly (prefire(), fire()), until either it has no more input tokens, or its prefire() method returns false. Note that if the actor fails to consume its inputs, then this can result in an infinite loop. Each actor that is fired is then postfired once at the conclusion of the iteration.
If there are no events in the event queue, then the behavior depends on the stopWhenQueueIsEmpty parameter. If it is false, then this thread will stall until events become available in the event queue. Otherwise, time will advance to the stop time and the execution will halt.
fire
in interface Executable
fire
in class Director
IllegalActionException
- If the firing actor throws it, or
event queue is not ready, or an event is missed, or time is set
backwards.public Time fireAt(Actor actor, Time time) throws IllegalActionException
If this director is embedded within another model (the container has an executive director), and this method is being called between iterations of this director (which can only occur from a thread different from the one firing this director), then this method also delegates a request to the executive director to fire the container of this director at the requested time. If the executive director returns a value different from the specified time, then this method will use that revised value to schedule the firing of the specified actor, and will return that value.
A subtle corner case can occur in a multithreaded execution that will trigger an exception. In particular, it is possible for this director to delegate a request to its executive director, and for that request to be honored before it has posted the event on its own local event queue. This situation is avoided, for example, by putting this director within a ThreadedComposite actor. If this situation occurs, an exception will be thrown.
fireAt
in class Director
actor
- The scheduled actor to fire.time
- The scheduled time to fire.
IllegalActionException
- If the event queue is not ready,
or if a threading error occurs that would result in returning
a time value that is already in the past.Director.fireAtCurrentTime(Actor)
public void fireAtRelativeTime(Actor actor, Time time) throws IllegalActionException
actor
- The scheduled actor to fire.time
- The scheduled time to fire.
IllegalActionException
- If the specified time contains
a negative time value, or event queue is not ready.public int getMicrostep()
getIndex()
,
setIndex(int)
,
SuperdenseTimeDirector
public DEEventQueue getEventQueue()
public Time getModelNextIterationTime()
getModelNextIterationTime
in class Director
Director.getModelTime()
public final Time getModelStartTime()
getModelStartTime
in class Director
public final Time getModelStopTime()
getModelStopTime
in class Director
public long getRealStartTimeMillis()
public final double getStartTime()
getModelStartTime()
instead.
When the start time is too big, the double representation loses
the specified time resolution. To avoid this loss, use the
getModelStartTime()
instead.
getStartTime
in class Director
public final double getStopTime()
getModelStopTime()
instead.
When the stop time is too big, the double representation loses
the specified time resolution. To avoid this loss, use the
getModelStopTime()
instead.
getStopTime
in class Director
public int getIndex()
getIndex
in interface SuperdenseTimeDirector
setIndex(int)
,
SuperdenseTimeDirector
public void initialize() throws IllegalActionException
The real start time of the model is recorded when this method is called. This method is not synchronized on the workspace, so the caller should be.
initialize
in interface Initializable
initialize
in class Director
IllegalActionException
- If the initialize() method of
the super class throws it.public void invalidateSchedule()
invalidateSchedule
in class Director
public Receiver newReceiver()
newReceiver
in class Director
public boolean postfire() throws IllegalActionException
postfire
in interface Executable
postfire
in class Director
IllegalActionException
- If the postfire method of the super
class throws it, or the stopWhenQueueIsEmpty parameter does not contain
a valid token, or refiring can not be requested.public boolean prefire() throws IllegalActionException
Note that microsteps are not synchronized.
Throw an exception if the current model time is greater than the next event timestamp.
prefire
in interface Executable
prefire
in class Director
IllegalActionException
- If there is a missed event,
or the prefire method of the super class throws it, or can not
query the tokens of the input ports of the container of this
director.public void preinitialize() throws IllegalActionException
This method should be invoked once per execution, before any iteration. Actors cannot produce output data in their preinitialize() methods. If initial events are needed, e.g. pure events for source actor, the actors should do so in their initialize() method.
This method is not synchronized on the workspace, so the caller should be.
preinitialize
in interface Initializable
preinitialize
in class Director
IllegalActionException
- If the preinitialize() method of the
container or one of the deeply contained actors throws it, or the
parameters, minBinCount, binCountFactor, and isCQAdaptive, do not have
valid tokens.public void removeDebugListener(DebugListener listener)
removeDebugListener
in interface Debuggable
removeDebugListener
in class NamedObj
listener
- The listener to remove from the list of listeners
to which debug messages are sent.addDebugListener(DebugListener)
public void setIndex(int index) throws IllegalActionException
setIndex
in interface SuperdenseTimeDirector
index
- The index of the superdense time object.
Events that occur at the same time have different indicies.
IllegalActionException
- Not thrown in this base class.getIndex()
,
SuperdenseTimeDirector
public void stop()
stop
in interface Executable
stop
in class Director
public void stopFire()
stopFire
in interface Executable
stopFire
in class Director
public java.lang.String[] suggestedModalModelDirectors()
suggestedModalModelDirectors
in class Director
Director.suggestedModalModelDirectors()
public boolean transferOutputs(IOPort port) throws IllegalActionException
transferOutputs
in class Director
port
- The port to transfer tokens from.
IllegalActionException
- If the port is not an opaque
output port.public void wrapup() throws IllegalActionException
wrapup
in interface Initializable
wrapup
in class Director
IllegalActionException
- If the wrapup() method of
one of the associated actors throws it.protected void _disableActor(Actor actor)
actor
- The actor to disable.protected void _enqueueEvent(Actor actor, Time time) throws IllegalActionException
The default microstep for the queued event is equal to zero, unless the time is equal to the current time, where the microstep will be the current microstep plus one.
The depth for the queued event is the minimum of the depths of all the ports of the destination actor.
If there is no event queue or the given actor is disabled, then this method does nothing.
actor
- The actor to be fired.time
- The timestamp of the event.
IllegalActionException
- If the time argument is less than
the current model time, or the depth of the actor has not be calculated,
or the new event can not be enqueued.protected void _enqueueTriggerEvent(IOPort ioPort) throws IllegalActionException
The trigger event has the same timestamp as that of the director. The microstep of this event is always equal to the current microstep of this director. The depth for the queued event is the depth of the destination IO port.
If the event queue is not ready or the actor contains the destination port is disabled, do nothing.
ioPort
- The destination IO port.
IllegalActionException
- If the time argument is not the
current time, or the depth of the given IO port has not be calculated,
or the new event can not be enqueued.protected int _getDepthOfActor(Actor actor) throws IllegalActionException
actor
- An actor whose depth is requested.
IllegalActionException
- If the actor depth has
not been computed (this should not occur if the ioPort is under the control
of this director).protected int _getDepthOfIOPort(IOPort ioPort) throws IllegalActionException
ioPort
- A port whose depth is requested.
IllegalActionException
- If the ioPort does not have
a depth (this should not occur if the ioPort is under the control
of this director).protected Actor _getNextActorToFire() throws IllegalActionException
If the stopWhenQueueIsEmpty parameter is false and the queue is empty, then stall the current thread by calling wait() on the _eventQueue until there are new events available. If the synchronizeToRealTime parameter is true, then this method may suspend the calling thread by using Object.wait(long) to let elapsed real time catch up with the current model time.
IllegalActionException
- If event queue is not ready, or
an event is missed, or time is set backwards.private void _initParameters()
private void _requestFiring() throws IllegalActionException
IllegalActionException
- If the queue is empty, or
if the executive director does not respect the fireAt() call.
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES All Classes | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |