A container for another actor that executes that other actor
in a separate thread called the <i>inside thread</i>.
This actor starts that thread in its initialize()
method, which is invoked by its executive director (the director
in charge of firing this actor). The thread that invokes the
action methods of this actor
(initialize(), prefire(), fire(), postfire(), and wrapup())
is called the <i>director thread</i>.
<p>
A paper describing the use of this actor is found at
<a href="http://www.eecs.berkeley.edu/Pubs/TechRpts/2008/EECS-2008-151.html">
http://www.eecs.berkeley.edu/Pubs/TechRpts/2008/EECS-2008-151.html</a>.
<p>
This actor automatically creates input and output ports to
match those of the inside actor. Input events provided at those
input ports are provided as input events to the contained actor.
Outputs provided by the contained actor become output events
of this actor. The time stamp of the input events is provided
by the container of this actor. The time stamp of the output events
depends on the <i>delay</i> parameter, as explained below.
<p>
The inside thread blocks waiting for inputs or pure events.
Inputs are provided to that thread when the fire() method of
this actor is invoked by the director thread.
Pure events are provided after fireAt(),
fireAtCurrentTime(), or fireAtFirstValidTimeAfter() are called
by either the inside thread or the director thread.
When the time of those firing requests becomes current time,
the container will (presumably) fire this actor, and
this actor will provide a pure event to the inside thread,
causing it to fire the contained actor.
<p>
If the <i>synchronizeToRealTime</i> parameter is true, then
when the inside thread encounters an input or pure event
with time stamp <i>t</i>, it stalls until real time matches
or exceeds <i>t</i> (measured in seconds since the start of
execution of the inside thread). In contrast for example
to the <i>synchronizeToRealTime</i> parameter of the DEDirector,
this enables construction of models where only a portion of the
model synchronizes to real time.
<p>
When the wrapup() method of this actor is called, the inside thread is
provided with signal to terminate rather than to process additional
inputs. The inside thread will also exit if stop() is called on this
actor; however, in this case, which iterations are completed
is nondeterminate (there may be inputs left unprocessed).
<p>
The parameters of this actor include all the parameters of the
contained actor, and setting those parameters automatically
sets the parameters of the contained actor.
<p>
In addition to the parameters of the contained actor, this actor
has a <i>delay</i> parameter. This parameter is a double that
be any nonnegative value or the special value <i>UNDEFINED</i>.
If it is given a nonnegative value, then the value specifies
the model-time delay between input events and the output
events that result from reacting to those input events.
That is, if this actor is given an input event with time
stamp <i>t</i>, then if the contained actor produces any output
events in reaction to that event, those output events will be
produced by this actor with time stamp <i>t</i> + <i>delay</i>.
<p>
If <i>delay</i> has value <i>UNDEFINED</i>, then
outputs are produced at the current model time of the executive
director when the inside thread happens to produce those events,
or if <i>synchronizeToRealTime</i>, at the greater of current
model time and current real time (measured in seconds since
the start of execution).
This is accomplished by the inside thread calling
fireAtFirstValidTimeAfter() of the enclosing director, and
then producing the outputs when the requested firing occurs
in the director thread. Note that with this value of the
<i>delay</i>, it is possible for the inside thread to
continue to execute and respond to input events after
the wrapup phase of the director thread has been entered.
The wrapup phase will stall until the inside thread has
completed its processing of its inputs, but any outputs
it produces after the wrapup phase has started will be
discarded.
<p>
The most common use of this actor is in the DE domain,
although it can also be used in CT, SR, SDF, and other domains,
with some care. See the above referenced memo.
Regardless of the value of <i>delay</i>, this actor is treated
by DE as introducing a delay, much like the TimedDelay actor.
In fact, if <i>delay</i> is 0.0, there will be a one tick delay
in superdense time, just as with the TimedDelay actor.
If the inside model also has a time delay (e.g. if you
put a TimedDelay actor inside a ThreadedComposite), then
the total delay is the sum of the two delays.
<p>
<b>Discussion:</b>
<p>
There are several useful things you can do with this model.
We describe some use cases here:
<p>
<i>Background execution.</i> When <i>delay</i> is greater than
or equal to 0.0,
then when this actor is fired in response to input events
with time stamp <i>t</i>, the actual
processing of those events occurs later in a separate thread. The
director thread is not blocked, and can continue to process events
with time stamps less than or equal to <i>t</i> + <i>delay</i>.
The director thread is blocked from processing events with larger
time stamps than that because this is necessary to preserve DE
semantics. To implement this, this actor uses fireAt() to
request a firing at time <i>t</i> + <i>delay</i>, and when that
firing occurs, it blocks the director thread until the reaction
is complete.
<p>
<i>Parallel firing.</i> Note that if <i>delay</i> is set to 0.0,
it may seem that there is no point in using this actor, since
model time will not be allowed to increase past <i>t</i> until
the contained actor has reacted to events with time stamp <i>t</i>.
However, there is actually exploitable concurrency if there
are other actors in the model that also have pending input
events with time stamp <i>t</i>. Those event can be processed
concurrently with this actor reacting to its input event.
A typical use case will broadcast an event to several instances
of ThreadedComposite, in which case each of those several
inside threads can execute concurrently in reaction to those
input events.
<p>
<i>Real-time source.</i> If the contained actor (and hence this
actor) has no inputs and <i>synchronizeToRealTime</i> is true, then
the contained actor must call fireAt() or one of its variants so that
the inside thread will be provided with pure events.
The behavior depends on which variant of the fireAt() methods is used
by the inside actor. There are three cases:
FIXME: Described these. In particular, delay needs to specify the
minimum increment between these or fireAt() could result in an
exception. Do we want a parameter to relax that?
<p>
On subtlety of this actor is that it cannot expose instances of ParameterPort
without introducing nondeterminacy in the execution. A ParameterPort
is an input port that sets the value of a parameter with the same name. Upon receiving
a token at such a port, if this actor were to set a parameter visible by the
inside thread, there is no assurance that the inside thread is not still
executing an earlier iteration. Thus, it could appear to be sending a message
backward in time, which would be truly bizarre. To prevent this error,
this actor does not mirror such ports, and hence they appear on the outside
only as parameters.
Edward A. Lee
$Id: ThreadedComposite.java 70402 2014-10-23 00:52:20Z cxh $
Ptolemy II 8.0
Yellow (eal)
Red (eal)
The model-time delay between the input events and the
output events. This is a double that defaults to 0.0,
indicating that outputs should have the same time stamps
as the inputs that trigger them. If it has a value greater
than zero, then the outputs will have large time stamps
by that amount. If it has the value <i>UNDEFINED</i>
(or any negative number), then the output time stamp
will be nondeterminate, and will depend on the current
model time of the outside director when the output is
produced or on current real time.
If set to true, the inside thread stalls until real time matches
the time stamps of input events or pure events for each firing.
In addition, if <i>delay</i> is set to undefined and this is set
to true, then output events are assigned a time stamp that is the
greater of current model time and real time.
Time is measured since the start of the execution of the inside
thread. This is a boolean that defaults to false. Changing
the value of this parameter has no effect until the next
execution of the model.