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}