001/* An executable entity.
002
003 Copyright (c) 1997-2016 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027 */
028package ptolemy.actor;
029
030import java.util.ArrayList;
031import java.util.Iterator;
032import java.util.LinkedHashSet;
033import java.util.LinkedList;
034import java.util.List;
035import java.util.Set;
036
037import ptolemy.actor.util.BooleanDependency;
038import ptolemy.actor.util.CausalityInterface;
039import ptolemy.actor.util.DefaultCausalityInterface;
040import ptolemy.actor.util.Dependency;
041import ptolemy.kernel.ComponentEntity;
042import ptolemy.kernel.CompositeEntity;
043import ptolemy.kernel.Port;
044import ptolemy.kernel.util.IllegalActionException;
045import ptolemy.kernel.util.InternalErrorException;
046import ptolemy.kernel.util.NameDuplicationException;
047import ptolemy.kernel.util.Nameable;
048import ptolemy.kernel.util.Workspace;
049
050///////////////////////////////////////////////////////////////////
051//// AtomicActor
052
053/**
054 An AtomicActor is an executable entity that cannot itself contain
055 other actors. The Ports of AtomicActors are constrained to be IOPorts.
056 Derived classes may further constrain the ports by overriding the public
057 method newPort() to create a port of the appropriate subclass, and the
058 protected method _addPort() to throw an exception if its argument is a
059 port that is not of the appropriate subclass. In this base class, the
060 actor does nothing in the action methods (prefire, fire, ...).
061
062 @author Mudit Goel, Edward A. Lee, Lukito Muliadi, Steve Neuendorffer, Contributor: Daniel Crawl
063 @version $Id$
064 @since Ptolemy II 0.2
065 @Pt.ProposedRating Green (eal)
066 @Pt.AcceptedRating Green (neuendor)
067 @see ptolemy.actor.CompositeActor
068 @see ptolemy.actor.IOPort
069 */
070public class AtomicActor<T extends IOPort> extends ComponentEntity<T>
071        implements Actor, FiringsRecordable {
072    /** Construct an actor in the default workspace with an empty string
073     *  as its name. Increment the version number of the workspace.
074     *  The object is added to the workspace directory.
075     */
076    public AtomicActor() {
077        super();
078    }
079
080    /** Construct an actor in the specified workspace with an empty
081     *  string as a name. You can then change the name with setName().
082     *  If the workspace argument is null, then use the default workspace.
083     *  The object is added to the workspace directory.
084     *  Increment the version number of the workspace.
085     *  @param workspace The workspace that will list this actor.
086     */
087    public AtomicActor(Workspace workspace) {
088        super(workspace);
089    }
090
091    /** Create a new actor in the specified container with the specified
092     *  name.  The name must be unique within the container or an exception
093     *  is thrown. The container argument must not be null, or a
094     *  NullPointerException will be thrown.
095     *
096     *  @param container The container.
097     *  @param name The name of this actor within the container.
098     *  @exception IllegalActionException If the entity cannot be contained
099     *   by the proposed container (see the setContainer() method).
100     *  @exception NameDuplicationException If the name coincides with
101     *   an entity already in the container.
102     */
103    public AtomicActor(CompositeEntity container, String name)
104            throws IllegalActionException, NameDuplicationException {
105        super(container, name);
106    }
107
108    ///////////////////////////////////////////////////////////////////
109    ////                         public methods                    ////
110
111    /** Add the specified object to the set of objects whose
112     *  preinitialize(), initialize(), and wrapup()
113     *  methods should be invoked upon invocation of the corresponding
114     *  methods of this object.
115     *  @param initializable The object whose methods should be invoked.
116     *  @see #removeInitializable(Initializable)
117     *  @see ptolemy.actor.CompositeActor#addPiggyback(Executable)
118     */
119    @Override
120    public void addInitializable(Initializable initializable) {
121        if (_initializables == null) {
122            _initializables = new LinkedHashSet<Initializable>();
123        }
124        _initializables.add(initializable);
125    }
126
127    /** Append a listener to the current set of actor firing listeners.
128     *  If the listener is already in the set, it will not be added again.
129     *  Note that this method is basically the same as addDebugListener
130     *  in the class NamedObj.
131     *  @param listener The listener to which to send actor firing messages.
132     *  @see #removeActorFiringListener(ActorFiringListener)
133     */
134    @Override
135    public void addActorFiringListener(ActorFiringListener listener) {
136        // NOTE: This method needs to be synchronized to prevent two
137        // threads from each creating a new _actorFiringListeners list.
138        synchronized (this) {
139            if (_actorFiringListeners == null) {
140                _actorFiringListeners = new LinkedList<ActorFiringListener>();
141            }
142        }
143
144        // NOTE: This has to be synchronized to prevent
145        // concurrent modification exceptions.
146        synchronized (_actorFiringListeners) {
147            if (_actorFiringListeners.contains(listener)) {
148                return;
149            } else {
150                _actorFiringListeners.add(listener);
151            }
152
153            _notifyingActorFiring = true;
154        }
155    }
156
157    /** Clone this actor into the specified workspace. The new actor is
158     *  <i>not</i> added to the directory of that workspace (you must do this
159     *  yourself if you want it there).
160     *  The result is a new actor with the same ports as the original, but
161     *  no connections and no container.  A container must be set before
162     *  much can be done with this actor.
163     *
164     *  @param workspace The workspace for the cloned object.
165     *  @exception CloneNotSupportedException If cloned ports cannot have
166     *   as their container the cloned entity (this should not occur), or
167     *   if one of the attributes cannot be cloned.
168     *  @return A new ComponentEntity.
169     */
170    @Override
171    public Object clone(Workspace workspace) throws CloneNotSupportedException {
172
173        // When super.clone() is called below, attributes that are
174        // contained in this actor are also cloned, which includes
175        // calling methods on these attributes such as setContainer().
176        // These methods may add themselves to the firing listeners
177        // or initializables lists in the newObject clone, so we do
178        // not want to clear these lists in newObject after super.clone().
179        // Instead, save this instance's lists here and restore them after
180        // call super.clone().
181        LinkedList<ActorFiringListener> oldActorFiringListeners = _actorFiringListeners;
182        _actorFiringListeners = null;
183        Set<Initializable> oldInitializables = _initializables;
184        _initializables = null;
185
186        @SuppressWarnings("unchecked")
187        AtomicActor<T> newObject = (AtomicActor<T>) super.clone(workspace);
188
189        _initializables = oldInitializables;
190        _actorFiringListeners = oldActorFiringListeners;
191
192        // Reset to force reinitialization of cache.
193        newObject._inputPortsVersion = -1;
194        newObject._outputPortsVersion = -1;
195        newObject._cachedInputPorts = null;
196        newObject._cachedOutputPorts = null;
197        newObject._causalityInterface = null;
198        newObject._causalityInterfaceDirector = null;
199        newObject._receiversVersion = -1L;
200        return newObject;
201    }
202
203    /** Create new receivers if the port is
204     *  an input port and there is a director.
205     *  @param port The port that has connection changes.
206     */
207    @Override
208    public void connectionsChanged(Port port) {
209        if (_debugging) {
210            _debug("Connections changed on port: " + port.getName());
211        }
212
213        if (port instanceof IOPort) {
214            IOPort castPort = (IOPort) port;
215            Manager manager = getManager();
216            if (castPort.isInput() && getDirector() != null && manager != null
217                    && manager.getState() != Manager.IDLE
218                    && manager.getState() != Manager.INFERING_WIDTHS
219                    && manager.getState() != Manager.PREINITIALIZING) {
220                try {
221                    workspace().getWriteAccess();
222                    castPort.createReceivers();
223                } catch (IllegalActionException ex) {
224                    // Should never happen.
225                    throw new InternalErrorException(this, ex,
226                            "Cannot create receivers on Port \""
227                                    + port.getFullName() + "\".");
228                } finally {
229                    // Note that this does not increment the workspace version.
230                    // We have not changed the structure of the model.
231                    _workspace.doneTemporaryWriting();
232                }
233            }
234        }
235    }
236
237    /** Create receivers for each input port.
238     *  @exception IllegalActionException If any port throws it.
239     */
240    @Override
241    public void createReceivers() throws IllegalActionException {
242        if (workspace().getVersion() != _receiversVersion) {
243            // NOTE:  Receivers are also getting created
244            // in connectionChanged(). This to make sure that
245            // the receivers are reset when the model changes while
246            // running the model.
247
248            Iterator<?> inputPorts = inputPortList().iterator();
249            try {
250                workspace().getWriteAccess();
251                while (inputPorts.hasNext()) {
252                    IOPort inputPort = (IOPort) inputPorts.next();
253                    inputPort.createReceivers();
254                }
255                _receiversVersion = workspace().getVersion();
256            } finally {
257                // Note that this does not increment the workspace version.
258                // We have not changed the structure of the model.
259                workspace().doneTemporaryWriting();
260            }
261        }
262    }
263
264    /** Set the dependency between all output ports and all input
265     *  ports of this actor. By default, each
266     *  output port is assumed to have a dependency on all input
267     *  ports. Since this is the assumed behavior, this method
268     *  does nothing by default.
269     *
270     *  However, for subclasses such as {@link ptolemy.actor.lib.TimeDelay},
271     *  where output ports depend on input ports with a time delay,
272     *  this method should be overridden.
273     *  Protected method _declareDelayDependency() should be used
274     *  to declare dependency between input and output ports for
275     *  this actor.
276     *  @exception IllegalActionException Not thrown in this base
277     *  class, derived classes should throw this exception if the
278     *  delay dependency cannot be computed.
279     *  @see #getCausalityInterface()
280     *  @see #_declareDelayDependency(IOPort, IOPort, double)
281     */
282    public void declareDelayDependency() throws IllegalActionException {
283    }
284
285    /** Do nothing.  Derived classes override this method to define their
286     *  primary run-time action.
287     *
288     *  @exception IllegalActionException Not thrown in this base class.
289     */
290    @Override
291    public void fire() throws IllegalActionException {
292        if (_debugging) {
293            _debug("Called fire()");
294        }
295    }
296
297    /** Return a causality interface for this actor. In this base class,
298     *  we return an instance of {@link DefaultCausalityInterface}
299     *  with the dependency type given by the director, or with a BooleanDependency
300     *  if there is no director.
301     *  This declares that all output ports of the actor depend on all input
302     *  ports, unless the actor calls
303     *  {@link #removeDependency(IOPort, IOPort)} or
304     *  {@link #_declareDelayDependency(IOPort, IOPort, double)}.
305     *  If this is called multiple times, the same object is returned each
306     *  time unless the director has changed since the last call, in
307     *  which case a new object is returned.
308     *  @return A representation of the dependencies between input ports
309     *   and output ports.
310     * @exception IllegalActionException Thrown in subclasses if causality
311     * interface cannot be computed.
312     */
313    @Override
314    public CausalityInterface getCausalityInterface()
315            throws IllegalActionException {
316        Director director = getDirector();
317        if (_causalityInterface != null
318                && _causalityInterfaceDirector == director) {
319            return _causalityInterface;
320        }
321        Dependency defaultDependency = BooleanDependency.OTIMES_IDENTITY;
322        if (director != null) {
323            defaultDependency = director.defaultDependency();
324        }
325        _causalityInterface = new DefaultCausalityInterface(this,
326                defaultDependency);
327        _causalityInterfaceDirector = director;
328        return _causalityInterface;
329    }
330
331    /** Return the director responsible for the execution of this actor.
332     *  In this class, this is always the executive director.
333     *  Return null if either there is no container or the container has no
334     *  director.
335     *  @return The director that invokes this actor.
336     */
337    @Override
338    public Director getDirector() {
339        Nameable container = getContainer();
340
341        if (container instanceof Actor) {
342            return ((Actor) container).getDirector();
343        }
344
345        return null;
346    }
347
348    /** Return the executive director (same as getDirector()).
349     *  @return The executive director.
350     */
351    @Override
352    public Director getExecutiveDirector() {
353        return getDirector();
354    }
355
356    /** Return the Manager responsible for execution of this actor,
357     *  if there is one. Otherwise, return null.
358     *  @return The manager.
359     */
360    @Override
361    public Manager getManager() {
362        try {
363            _workspace.getReadAccess();
364
365            Nameable container = getContainer();
366
367            if (container instanceof Actor) {
368                return ((Actor) container).getManager();
369            }
370
371            return null;
372        } finally {
373            _workspace.doneReading();
374        }
375    }
376
377    /** Initialize this actor.  Derived classes override this method
378     *  to perform actions that should occur once at the beginning of
379     *  an execution, but after type resolution.  Derived classes can
380     *  produce output data and schedule events.
381     *
382     *  @exception IllegalActionException If a derived class throws it.
383     */
384    @Override
385    public void initialize() throws IllegalActionException {
386        if (_debugging) {
387            _debug("Called initialize()");
388        }
389        // First invoke initializable methods.
390        if (_initializables != null) {
391            for (Initializable initializable : _initializables) {
392                initializable.initialize();
393            }
394        }
395    }
396
397    /** List all the input ports.
398     *  This method is read-synchronized on the workspace.
399     *  @return A list of input IOPort objects.
400     */
401    @Override
402    public List<T> inputPortList() {
403        if (_inputPortsVersion != _workspace.getVersion()) {
404            try {
405                _workspace.getReadAccess();
406
407                // Update the cache.
408                List<T> inputPorts = new LinkedList<T>();
409                Iterator<T> ports = portList().iterator();
410
411                while (ports.hasNext()) {
412                    T p = ports.next();
413
414                    if (p.isInput()) {
415                        inputPorts.add(p);
416                    }
417                }
418
419                // Create an arrayList, since the cache will not be
420                // modified.  This reduces memory usage.
421                _cachedInputPorts = new ArrayList<T>(inputPorts);
422                _inputPortsVersion = _workspace.getVersion();
423            } finally {
424                _workspace.doneReading();
425            }
426        }
427
428        return _cachedInputPorts;
429    }
430
431    /** Return true. Most actors are written so that the prefire() and
432     *  fire() methods do not change the state of the actor. Hence, for
433     *  convenience, this base class by default returns true. An actor
434     *  that does change state in prefire() or fire() must override
435     *  this method to return false.
436     *
437     *  @return True.
438     */
439    @Override
440    public boolean isFireFunctional() {
441        return true;
442    }
443
444    /** Return true unless all input ports have non-empty default values.
445     *  By default, most actors do not
446     *  check their inputs to see whether they are known.  They assume
447     *  they are known.
448     *  Note that ParameterPort is not treated as having a default value
449     *  because such ports might be used in a context where it is important
450     *  to supply them with an input value.
451     *  @return False if this actor does not need to be provided with
452     *   inputs to fire.
453     *  @exception IllegalActionException If the defaultValue expression
454     *   cannot be evaluated for an input port.
455     */
456    @Override
457    public boolean isStrict() throws IllegalActionException {
458        for (IOPort port : inputPortList()) {
459            if (port.defaultValue.getToken() == null) {
460                // Found an input port with no default value.
461                return true;
462            }
463        }
464        // If all input ports have default values, then report
465        // that this actor is non-strict.
466        // NOTE: If the actor has no input ports at all, this
467        // returns false, indicating the actor is non-strict.
468        return false;
469    }
470
471    /** Invoke a specified number of iterations of the actor. An
472     *  iteration is equivalent to invoking prefire(), fire(), and
473     *  postfire(), in that order. In an iteration, if prefire()
474     *  returns true, then fire() will be called once, followed by
475     *  postfire(). Otherwise, if prefire() returns false, fire()
476     *  and postfire() are not invoked, and this method returns
477     *  NOT_READY. If postfire() returns false, then no more
478     *  iterations are invoked, and this method returns STOP_ITERATING.
479     *  Otherwise, it returns COMPLETED. If stop() is called while
480     *  this is executing, then cease executing and return STOP_ITERATING.
481     *  <p>
482     *  This base class method actually invokes prefire(), fire(),
483     *  and postfire(), as described above, but a derived class
484     *  may override the method to execute more efficient code.
485     *
486     *  @param count The number of iterations to perform.
487     *  @return NOT_READY, STOP_ITERATING, or COMPLETED.
488     *  @exception IllegalActionException If iterating is not
489     *   permitted, or if prefire(), fire(), or postfire() throw it.
490     */
491    @Override
492    public int iterate(int count) throws IllegalActionException {
493        if (_debugging) {
494            _debug("Called iterate(" + count + ")");
495        }
496
497        int n = 0;
498
499        try {
500            while (n++ < count && !_stopRequested) {
501                if (_notifyingActorFiring) {
502                    _actorFiring(FiringEvent.BEFORE_PREFIRE, n);
503                }
504
505                if (prefire()) {
506
507                    if (_notifyingActorFiring) {
508                        _actorFiring(FiringEvent.AFTER_PREFIRE, n);
509                        _actorFiring(FiringEvent.BEFORE_FIRE, n);
510                    }
511
512                    fire();
513                    if (_notifyingActorFiring) {
514                        _actorFiring(FiringEvent.AFTER_FIRE, n);
515                        _actorFiring(FiringEvent.BEFORE_POSTFIRE, n);
516                    }
517
518                    boolean pfire = postfire();
519
520                    if (_notifyingActorFiring) {
521                        _actorFiring(FiringEvent.AFTER_POSTFIRE, n);
522                    }
523
524                    if (!pfire) {
525                        return Executable.STOP_ITERATING;
526                    }
527
528                } else {
529
530                    if (_notifyingActorFiring) {
531                        _actorFiring(FiringEvent.AFTER_PREFIRE, n);
532                    }
533                    return Executable.NOT_READY;
534                }
535            }
536
537            if (_stopRequested) {
538                return Executable.STOP_ITERATING;
539            } else {
540                return Executable.COMPLETED;
541            }
542        } catch (IllegalActionException ex) {
543            // When fire() calls certain Token methods such as
544            // add() or multiply() and the method throws an
545            // exception, the exception will not include the
546            // associated Nameable.  So, we catch exceptions
547            // here and if the associated Nameable is null,
548            // we rethrow with this as the Nameable.
549
550            if (ex.getNameable1() == null) {
551                throw new IllegalActionException(this, ex, ex.getMessage());
552            } else {
553                throw ex;
554            }
555
556        }
557
558    }
559
560    /** Create a new IOPort with the specified name.
561     *  The container of the port is set to this actor.
562     *  This method is write-synchronized on the workspace.
563     *  Normally this method is not called directly by actor code.
564     *  Instead, a change request should be queued with the director.
565     *
566     *  @param name The name for the new port.
567     *  @return The new port.
568     *  @exception NameDuplicationException If this actor already has a port
569     *   with the specified name.
570     *  @see ptolemy.kernel.util.Workspace#getWriteAccess()
571     */
572    @Override
573    public Port newPort(String name) throws NameDuplicationException {
574        try {
575            _workspace.getWriteAccess();
576
577            IOPort port = new IOPort(this, name);
578            return port;
579        } catch (IllegalActionException ex) {
580            // This exception should not occur, so we throw a runtime
581            // exception.
582            throw new InternalErrorException(this, ex, null);
583        } finally {
584            _workspace.doneWriting();
585        }
586    }
587
588    /** Return a new receiver of a type compatible with the director.
589     *  Derived classes may further specialize this to return a receiver
590     *  specialized to the particular actor.
591     *
592     *  @exception IllegalActionException If there is no director.
593     *  @return A new object implementing the Receiver interface.
594     */
595    @Override
596    public Receiver newReceiver() throws IllegalActionException {
597        Director director = getDirector();
598
599        if (director == null) {
600            throw new IllegalActionException(this,
601                    "Cannot create a receiver without a director.");
602        }
603
604        return director.newReceiver();
605    }
606
607    /** List the output ports.
608     *  This method is read-synchronized on the workspace.
609     *  @return A list of output IOPort objects.
610     */
611    @Override
612    public List<T> outputPortList() {
613        if (_outputPortsVersion != _workspace.getVersion()) {
614            try {
615                _workspace.getReadAccess();
616
617                List<T> outputPorts = new LinkedList<T>();
618                Iterator<T> ports = portList().iterator();
619
620                while (ports.hasNext()) {
621                    T p = ports.next();
622
623                    if (p.isOutput()) {
624                        outputPorts.add(p);
625                    }
626                }
627
628                // Create an arrayList, since the cache will not be
629                // modified.  This reduces memory usage.
630                _cachedOutputPorts = new ArrayList<T>(outputPorts);
631                _outputPortsVersion = _workspace.getVersion();
632            } finally {
633                _workspace.doneReading();
634            }
635        }
636
637        return _cachedOutputPorts;
638    }
639
640    /** Return true, unless stop() has been called, in which case,
641     *  return false.  Derived classes override this method to define
642     *  operations to be performed at the end of every iteration of
643     *  its execution, after one invocation of the prefire() method
644     *  and any number of invocations of the fire() method.
645     *  This method typically wraps up an iteration, which may
646     *  involve updating local state.  In derived classes,
647     *  this method returns false to indicate that this actor should not
648     *  be fired again.
649     *
650     *  @return True if execution can continue into the next iteration.
651     *  @exception IllegalActionException Not thrown in this base class.
652     */
653    @Override
654    public boolean postfire() throws IllegalActionException {
655        if (_debugging) {
656            _debug("Called postfire()");
657        }
658
659        return !_stopRequested;
660    }
661
662    /** Return true. Derived classes override this method to define
663     *  operations to be performed at the beginning of every iteration
664     *  of its execution, prior the invocation of the fire() method.
665     *  Derived classes may also use it to check preconditions for an
666     *  iteration, if there are any.
667     *
668     *  @return True if this actor is ready for firing, false otherwise.
669     *  @exception IllegalActionException Not thrown in this base class.
670     */
671    @Override
672    public boolean prefire() throws IllegalActionException {
673        if (_debugging) {
674            _debug("Called prefire()");
675        }
676
677        return true;
678    }
679
680    /** Create receivers and declare delay dependencies. Derived classes
681     *  can override this method to perform additional initialization
682     *  functions, but they should call this base class methods or
683     *  create the receivers themselves.
684     *  This method gets executed exactly once prior to any other
685     *  action methods.  It cannot produce output data since type
686     *  resolution is typically not yet done. It also gets invoked
687     *  prior to any static scheduling that might occur in the domain,
688     *  so it can change scheduling information.
689     *  @exception IllegalActionException Not thrown in this base class.
690     */
691    @Override
692    public void preinitialize() throws IllegalActionException {
693        if (_debugging) {
694            _debug("Called preinitialize()");
695        }
696
697        _stopRequested = false;
698
699        // For backward compatibility, in case there are actors
700        // that override pruneDependencies() to alter their
701        // causality interface, call it here.
702        pruneDependencies();
703
704        // Declare dependency for this actor. For actors such as
705        // TimeDelay, the delay dependency between input and output
706        // ports are declared.
707        declareDelayDependency();
708
709        // First invoke initializable methods.
710        if (_initializables != null) {
711            for (Initializable initializable : _initializables) {
712                initializable.preinitialize();
713            }
714        }
715    }
716
717    /** Prune the dependency declarations, which by default state
718     *  that each output port depends on all input ports in a firing.
719     *  This base class does no pruning, but subclasses that have
720     *  output ports that do not depend on input ports should override
721     *  this method to prune the dependencies.  To declare that an
722     *  output port does not depend on an input port, subclasses
723     *  can call removeDependency(input, output) rather than implementing
724     *  a specialized {@link CausalityInterface}, at least for the simple
725     *  cases where output ports do not depend at all on input ports.
726     *  @exception IllegalActionException Thrown by subclasses if causality interface
727     *  cannot be computed.
728     *  @see #removeDependency(IOPort, IOPort)
729     *  @see #getCausalityInterface()
730     *  @deprecated There is no need to override this method anymore.
731     *   Just call removeDependency() in preinitialize().
732     */
733    @Deprecated
734    public void pruneDependencies() throws IllegalActionException {
735    }
736
737    /** Record a firing event.
738     *  @param type The firing event to be recorded.
739     */
740    @Override
741    public void recordFiring(FiringEvent.FiringEventType type) {
742        _actorFiring(new FiringEvent(null, this, type));
743    }
744
745    /** Unregister an actor firing listener.  If the specified listener has not
746     *  been previously registered, then do nothing.  Note that this method
747     *  is basically the same as removeDebugListener in the class NamedObj.
748     *  @param listener The listener to remove from the list of listeners
749     *   to which actor firing messages are sent.
750     *  @see #addActorFiringListener(ActorFiringListener)
751     */
752    @Override
753    public void removeActorFiringListener(ActorFiringListener listener) {
754        if (_actorFiringListeners == null) {
755            return;
756        }
757
758        // NOTE: This has to be synchronized to prevent
759        // concurrent modification exceptions.
760        synchronized (_actorFiringListeners) {
761            _actorFiringListeners.remove(listener);
762
763            if (_actorFiringListeners.size() == 0) {
764                _notifyingActorFiring = false;
765            }
766
767            return;
768        }
769    }
770
771    /** Remove the dependency that the specified output port has,
772     *  by default, on the specified input port. By default, each
773     *  output port is assumed to have a dependency on all input
774     *  ports. Subclasses can call this method in preinitialize()
775     *  instead of implementing a custom {@link CausalityInterface}
776     *  for the simple cases where output ports do not depend
777     *  at all on certain input ports.
778     *  There should be one such call for each
779     *  input, output pair that does not have a dependency.
780     *  @param input The input port.
781     *  @param output The output port that does not depend on the
782     *   input port.
783     *  @exception IllegalActionException If causality interface
784     *  cannot be computed.
785     *  @see #getCausalityInterface()
786     */
787    public void removeDependency(IOPort input, IOPort output)
788            throws IllegalActionException {
789        CausalityInterface causality = getCausalityInterface();
790        causality.removeDependency(input, output);
791    }
792
793    /** Remove the specified object from the list of objects whose
794     *  preinitialize(), initialize(), and wrapup()
795     *  methods should be invoked upon invocation of the corresponding
796     *  methods of this object. If the specified object is not
797     *  on the list, do nothing.
798     *  @param initializable The object whose methods should no longer be invoked.
799     *  @see #addInitializable(Initializable)
800     *  @see ptolemy.actor.CompositeActor#removePiggyback(Executable)
801     */
802    @Override
803    public void removeInitializable(Initializable initializable) {
804        if (_initializables != null) {
805            _initializables.remove(initializable);
806            if (_initializables.size() == 0) {
807                _initializables = null;
808            }
809        }
810    }
811
812    /** Override the base class to invalidate the schedule and
813     *  resolved types of the director.
814     *  @param container The proposed container.
815     *  @exception IllegalActionException If the action would result in a
816     *   recursive containment structure, or if
817     *   this entity and container are not in the same workspace.
818     *  @exception NameDuplicationException If the container already has
819     *   an entity with the name of this entity.
820     */
821    @Override
822    public void setContainer(CompositeEntity container)
823            throws IllegalActionException, NameDuplicationException {
824        // Invalidate the schedule and type resolution of the old director.
825        Director oldDirector = getDirector();
826
827        if (oldDirector != null) {
828            oldDirector.invalidateSchedule();
829            oldDirector.invalidateResolvedTypes();
830        }
831
832        super.setContainer(container);
833
834        Director director = getDirector();
835
836        // Invalidate the schedule and type resolution of the new director.
837        if (director != null) {
838            director.invalidateSchedule();
839            director.invalidateResolvedTypes();
840        }
841    }
842
843    /** Request that execution of the current iteration stop as soon
844     *  as possible.  In this base class, we set a flag indicating that
845     *  this request has been made (the protected variable _stopRequested).
846     *  Most atomic actors have bounded fire() methods,
847     *  so they can simply ignore this.  Atomic actors with unbounded
848     *  fire() methods should react by saving their state
849     *  and returning from the fire() method at the next convenient
850     *  point.
851     */
852    @Override
853    public void stop() {
854        _stopRequested = true;
855
856        if (_debugging) {
857            _debug("Called stop()");
858        }
859    }
860
861    /** Request that execution of the current iteration complete.
862     *  Most atomic actors have bounded fire() methods, so they
863     *  can simply ignore this.  Atomic actors with unbounded fire()
864     *  methods should override this method to save their state and
865     *  return from the fire() method at the next convenient point.
866     *  In this base class, do nothing.
867     */
868    @Override
869    public void stopFire() {
870        if (_debugging) {
871            _debug("Called stopFire()");
872        }
873    }
874
875    /** Terminate execution immediately.  In this base class, call stop().
876     *  Derived classes may wish to do something more aggressive, such
877     *  as terminating any threads they have started.
878     */
879    @Override
880    public void terminate() {
881        if (_debugging) {
882            _debug("Called terminate()");
883        }
884
885        stop();
886    }
887
888    /** Do nothing except invoke the wrapup() methods of any
889     *  objects that have been registered with addInitializable().
890     *  Derived classes override this method to define
891     *  operations to be performed exactly once at the end of a complete
892     *  execution of an application.  It typically closes
893     *  files, displays final results, etc.
894     *
895     *  @exception IllegalActionException Not thrown in this base class.
896     */
897    @Override
898    public void wrapup() throws IllegalActionException {
899        if (_debugging) {
900            _debug("Called wrapup()");
901        }
902        // Invoke initializable methods.
903        // Collect exceptions during wrapup.
904        LinkedList<Throwable> throwables = new LinkedList<Throwable>();
905
906        if (_initializables != null) {
907            for (Initializable initializable : _initializables) {
908                try {
909                    initializable.wrapup();
910                } catch (Throwable throwable) {
911                    throwables.add(throwable);
912                }
913            }
914            if (throwables.size() == 1) {
915                Throwable exception = throwables.get(0);
916                if (exception instanceof IllegalActionException) {
917                    throw (IllegalActionException)exception;
918                } else {
919                    throw new IllegalActionException(this, exception,
920                            "Exception thrown during wrapup.");
921                }
922            } else if (throwables.size() > 1) {
923                StringBuffer message = new StringBuffer();
924                for (Throwable throwable : throwables) {
925                    message.append(throwable.getMessage());
926                    message.append("\n======\n");
927                }
928                throw new IllegalActionException(this, throwables.get(0),
929                        "Multiple exceptions thrown during wrapup:\n" 
930                        + message.toString());
931            }
932        }
933    }
934
935    ///////////////////////////////////////////////////////////////////
936    ////                         protected methods                 ////
937
938    /** Send an actor firing event to all actor firing listeners that
939     *  have registered with this actor.
940     *  @param event The event.
941     */
942    protected final void _actorFiring(FiringEvent event) {
943        if (_notifyingActorFiring) {
944            Iterator<ActorFiringListener> listeners = _actorFiringListeners
945                    .iterator();
946
947            while (listeners.hasNext()) {
948                listeners.next().firingEvent(event);
949            }
950        }
951    }
952
953    /** Send an actor firing event type to all actor firing listeners that
954     *  have registered with this actor.
955     *  @param type The type.
956     *  @param multiplicity The multiplicity of the firing, that is,
957     *  the number of times the firing will occur or has occurred.
958     */
959    protected final void _actorFiring(FiringEvent.FiringEventType type,
960            int multiplicity) {
961        _actorFiring(new FiringEvent(null, this, type, multiplicity));
962    }
963
964    /** Set the dependency between the input and output port to
965     *  represent a time delay with the specified value.
966     *  Subclasses can call this method
967     *  instead of implementing a custom {@link CausalityInterface}
968     *  for the cases where output ports depend on input ports with
969     *  a time delay.
970     *  If the time delay is 0.0, this method nonetheless
971     *  assumes that the output port does not (immediately) depend on
972     *  the input port (this amounts to a superdense time delay of
973     *  (0.0, 1)). There should be one such call for each
974     *  input, output pair that does not have a dependency.
975     *  @param input The input port.
976     *  @param output The output port with a time delay dependency on the
977     *   input port.
978     *  @param timeDelay The time delay.
979     *  @exception IllegalActionException If causality interface
980     *  cannot be computed.
981     *  @see #getCausalityInterface()
982     */
983    protected void _declareDelayDependency(IOPort input, IOPort output,
984            double timeDelay) throws IllegalActionException {
985        CausalityInterface causality = getCausalityInterface();
986        if (timeDelay == 0.0) {
987            causality.declareDelayDependency(input, output, 0.0, 1);
988        } else {
989            causality.declareDelayDependency(input, output, timeDelay, 0);
990        }
991    }
992
993    ///////////////////////////////////////////////////////////////////
994    ////                         protected variables               ////
995
996    /** The list of ActorFiringListeners registered with this object.
997     *  NOTE: Because of the way we synchronize on this object, it should
998     *  never be reset to null after the first list is created.
999     */
1000    protected LinkedList<ActorFiringListener> _actorFiringListeners = null;
1001
1002    /** List of objects whose (pre)initialize() and wrapup() methods
1003     *  should be slaved to these.
1004     */
1005    protected transient Set<Initializable> _initializables;
1006
1007    /** Flag that is true if there are actor firing listeners. */
1008    protected boolean _notifyingActorFiring = false;
1009
1010    /** Indicator that a stop has been requested by a call to stop(). */
1011    protected boolean _stopRequested = false;
1012
1013    ///////////////////////////////////////////////////////////////////
1014    ////                         private variables                 ////
1015    // Cached lists of input and output ports.
1016    private transient long _inputPortsVersion = -1;
1017
1018    private transient List<T> _cachedInputPorts;
1019
1020    private transient long _outputPortsVersion = -1;
1021
1022    private transient List<T> _cachedOutputPorts;
1023
1024    /** The causality interface, if it has been created. */
1025    private CausalityInterface _causalityInterface;
1026
1027    /** The director for which the causality interface was created. */
1028    private Director _causalityInterfaceDirector;
1029
1030    /** Record of the workspace version the last time receivers were created. */
1031    private long _receiversVersion = -1;
1032}