001/* A Director governs the execution of a CompositeActor. 002 003 Copyright (c) 1997-2015 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.HashMap; 032import java.util.HashSet; 033import java.util.Iterator; 034import java.util.LinkedHashSet; 035import java.util.LinkedList; 036import java.util.List; 037import java.util.Set; 038 039import ptolemy.actor.util.BooleanDependency; 040import ptolemy.actor.util.CausalityInterface; 041import ptolemy.actor.util.CausalityInterfaceForComposites; 042import ptolemy.actor.util.Dependency; 043import ptolemy.actor.util.Time; 044import ptolemy.data.BooleanToken; 045import ptolemy.data.DoubleToken; 046import ptolemy.data.Token; 047import ptolemy.data.expr.Parameter; 048import ptolemy.data.type.BaseType; 049import ptolemy.kernel.CompositeEntity; 050import ptolemy.kernel.util.Attribute; 051import ptolemy.kernel.util.IllegalActionException; 052import ptolemy.kernel.util.InternalErrorException; 053import ptolemy.kernel.util.LazyComposite; 054import ptolemy.kernel.util.NameDuplicationException; 055import ptolemy.kernel.util.Nameable; 056import ptolemy.kernel.util.NamedObj; 057import ptolemy.kernel.util.Settable; 058import ptolemy.kernel.util.Workspace; 059 060/////////////////////////////////////////////////////////////////// 061//// Director 062 063/** 064 A Director governs the execution within a CompositeActor. A composite actor 065 that contains a director is said to be <i>opaque</i>, and the execution model 066 within the composite actor is determined by the contained director. This 067 director is called the <i>local director</i> of a composite actor. 068 A composite actor is also aware of the director of its container, 069 which is referred to as its <i>executive director</i>. 070 A director may also be contained by a CompositeEntity that is not a 071 CompositeActor, in which case it acts like any other entity within 072 that composite. 073 <p> 074 A top-level composite actor is generally associated with a <i>manager</i> 075 as well as a local director. The Manager has overall responsibility for 076 executing the application, and is often associated with a GUI. Top-level 077 composite actors have no executive director and getExecutiveDirector() will 078 return null. 079 <p> 080 A local director is responsible for invoking the actors contained by the 081 composite. If there is no local director, then the executive director 082 is given the responsibility. The getDirector() method of CompositeActor, 083 therefore, returns the local director, if there is one, and otherwise 084 returns the executive director. Thus, it returns whichever director 085 is responsible for executing the contained actors, or null if there is none. 086 Whatever it returns is called simply the <i>director</i> (vs. local 087 director or executive director). 088 <p> 089 A director implements the action methods (preinitialize(), 090 initialize(), prefire(), fire(), postfire(), iterate(), 091 and wrapup()). In this base class, default implementations 092 are provided that may or may not be useful in specific domains. In general, 093 these methods will perform domain-dependent actions, and then call the 094 respective methods in all contained actors. 095 <p> 096 The director also provides methods to optimize the iteration portion of an 097 execution. This is done by setting the workspace to be read-only during 098 an iteration. In this base class, the default implementation results in 099 a read/write workspace. Derived classes (e.g. domain specific 100 directors) should override the _writeAccessRequired() method to report 101 that write access is not required. If none of the directors in a simulation 102 require write access, then it is safe to set the workspace to be read-only, 103 which will result in faster execution. 104 <p> 105 @author Mudit Goel, Edward A. Lee, Lukito Muliadi, Steve Neuendorffer, John Reekie 106 @version $Id$ 107 @since Ptolemy II 0.2 108 109 @Pt.ProposedRating Green (eal) 110 @Pt.AcceptedRating Yellow (neuendor) 111 */ 112public class Director extends Attribute implements Executable { 113 /** Construct a director in the default workspace with an empty string 114 * as its name. The director is added to the list of objects in 115 * the workspace. Increment the version number of the workspace. 116 * @exception NameDuplicationException If construction of Time objects fails. 117 * @exception IllegalActionException If construction of Time objects fails. 118 */ 119 public Director() throws IllegalActionException, NameDuplicationException { 120 super(); 121 _addIcon(); 122 _initializeParameters(); 123 } 124 125 /** Construct a director in the given container with the given name. 126 * The container argument must not be null, or a 127 * NullPointerException will be thrown. 128 * If the name argument is null, then the name is set to the 129 * empty string. Increment the version number of the workspace. 130 * 131 * @param container The container. 132 * @param name The name of this director. 133 * @exception IllegalActionException If the name has a period in it, or 134 * the director is not compatible with the specified container, or if 135 * the time resolution parameter is malformed. 136 * @exception NameDuplicationException If the container already contains 137 * an entity with the specified name. 138 */ 139 public Director(CompositeEntity container, String name) 140 throws IllegalActionException, NameDuplicationException { 141 super(container, name); 142 _addIcon(); 143 _initializeParameters(); 144 } 145 146 /** Construct a director in the workspace with an empty name. 147 * The director is added to the list of objects in the workspace. 148 * Increment the version number of the workspace. 149 * @param workspace The workspace of this object. 150 * @exception NameDuplicationException If construction of Time objects fails. 151 * @exception IllegalActionException If construction of Time objects fails. 152 */ 153 public Director(Workspace workspace) 154 throws IllegalActionException, NameDuplicationException { 155 super(workspace); 156 _addIcon(); 157 _initializeParameters(); 158 } 159 160 /////////////////////////////////////////////////////////////////// 161 //// public parameters //// 162 163 /** The clock that keeps track of current time of the model. */ 164 public LocalClock localClock; 165 166 /** The local time of model when this director is initialized. 167 * By default, this is blank, which 168 * indicates that the start time is the current time of the enclosing 169 * director when initialize() is invoked, or 0.0 if there is no 170 * enclosing director. This can be set to a double value to explicitly 171 * specify a start time. 172 * Note that if <i>startTime</i> is given a value 173 * that is different from the start time of the enclosing 174 * director, then local time may be ahead of or behind 175 * environment time during execution. 176 * Also note that some directors do not advance time (including 177 * PN and Rendezvous, for example), in which case, local time remains 178 * at the start time value throughout the execution. 179 */ 180 public Parameter startTime; 181 182 /** The stop time of the model. By default, this is blank, which 183 * means that no stop time is specified. If a stop time is specified, 184 * it must be a double, and when local time meets or exceeds the 185 * stop time, then {@link #postfire()} returns false. 186 */ 187 public Parameter stopTime; 188 189 /////////////////////////////////////////////////////////////////// 190 //// public methods //// 191 192 /** Add the specified object to the set of objects whose 193 * preinitialize(), initialize(), and wrapup() 194 * methods should be invoked upon invocation of the corresponding 195 * methods of this object. 196 * @param initializable The object whose methods should be invoked. 197 * @see #removeInitializable(Initializable) 198 * @see ptolemy.actor.CompositeActor#addPiggyback(Executable) 199 */ 200 @Override 201 public void addInitializable(Initializable initializable) { 202 if (_initializables == null) { 203 _initializables = new LinkedHashSet<Initializable>(); 204 } 205 _initializables.add(initializable); 206 } 207 208 /** Override the base class to update local variables. 209 * @param attribute The attribute that changed. 210 * @exception IllegalActionException If timeResolution is 211 * being changed and the model is executing (and not in 212 * preinitialize()). 213 */ 214 @Override 215 public void attributeChanged(Attribute attribute) 216 throws IllegalActionException { 217 if (attribute == startTime) { 218 DoubleToken startTimeValue = (DoubleToken) startTime.getToken(); 219 if (startTimeValue == null) { 220 _startTime = null; 221 } else { 222 _startTime = new Time(this, startTimeValue.doubleValue()); 223 } 224 localClock.resetLocalTime(getModelStartTime()); 225 } else if (attribute == stopTime) { 226 DoubleToken stopTimeValue = (DoubleToken) stopTime.getToken(); 227 if (stopTimeValue != null) { 228 _stopTime = new Time(this, stopTimeValue.doubleValue()); 229 } else { 230 _stopTime = null; 231 } 232 } 233 234 super.attributeChanged(attribute); 235 } 236 237 /** Clone the object into the specified workspace. The new object is 238 * <i>not</i> added to the directory of that workspace (you must do this 239 * yourself if you want it there). 240 * @param workspace The workspace for the cloned object. 241 * @exception CloneNotSupportedException Not thrown in this base class 242 * @return The new Attribute. 243 */ 244 @Override 245 public Object clone(Workspace workspace) throws CloneNotSupportedException { 246 Director newObject = (Director) super.clone(workspace); 247 newObject._actorsFinishedExecution = null; 248 newObject._initializables = null; 249 newObject._startTime = null; 250 newObject._stopTime = null; 251 newObject._zeroTime = new Time(newObject); 252 newObject._executionAspects = null; 253 newObject._aspectForActor = null; 254 newObject._nextScheduleTime = null; 255 return newObject; 256 } 257 258 /** Create the schedule for this director, if necessary. 259 * In this base class nothing is done. 260 * @exception IllegalActionException If the schedule can't be created. 261 */ 262 public void createSchedule() throws IllegalActionException { 263 } 264 265 /** Return a default dependency to use between input 266 * ports and output ports. 267 * Director subclasses may override this if 268 * need specialized dependency. This base class 269 * returns {@link BooleanDependency}.OTIMES_IDENTITY. 270 * @see Dependency 271 * @see CausalityInterface 272 * @see Actor#getCausalityInterface() 273 * @return A default dependency between input ports 274 * and output ports. 275 */ 276 public Dependency defaultDependency() { 277 if (isEmbedded()) { 278 return ((CompositeActor) getContainer()).getExecutiveDirector() 279 .defaultDependency(); 280 } else { 281 return BooleanDependency.OTIMES_IDENTITY; 282 } 283 } 284 285 /** Return a boolean dependency representing a model-time delay 286 * of the specified amount. This base clear returns 287 * BooleanDependency.OTIMES_IDENTITY, which indicates a delay 288 * but does not quantify the delay. 289 * @param delay A non-negative delay. 290 * @return A boolean dependency representing a delay. 291 */ 292 public Dependency delayDependency(double delay) { 293 return BooleanDependency.OTIMES_IDENTITY; 294 } 295 296 /** Return the elapsed time (in milliseconds) since the start of execution 297 * of the model. The start of execution is defined to be the time after 298 * preinitialize() and initialize() has been called for all components, 299 * and before any component has been iterated. This method delegates to 300 * the manager so that the start time is consistent among all directors 301 * in a model. 302 * @return The time in milliseconds since the start of execution of the model. 303 */ 304 public long elapsedTimeSinceStart() { 305 Manager manager = ((CompositeActor) getContainer()).getManager(); 306 return manager.elapsedTimeSinceStart(); 307 } 308 309 /** Request that after the current iteration finishes postfire() returns 310 * false, indicating to the environment that no more iterations should 311 * be invoked. To support domains where actor firings do not necessarily 312 * terminate, such as PN, you may wish to call stopFire() as well to request 313 * that those actors complete their firings. 314 */ 315 public void finish() { 316 _finishRequested = true; 317 } 318 319 /** Iterate all the deeply contained actors of the 320 * container of this director exactly once. This method is not functional, 321 * since an iteration of the deeply contained actors may change 322 * state in their postfire() method. The actors are iterated 323 * in the order that they appear on the list returned by deepEntityList(), 324 * which is normally the order in which they were created. 325 * <p> 326 * This method is <i>not</i> synchronized on the workspace, so the 327 * caller should be. 328 * <p> 329 * In this base class, an attempt is made to fire each actor exactly 330 * once, in the order they were created. Prefire is called once, and 331 * if prefire returns true, then fire is called once, followed by 332 * postfire. The return value from postfire is ignored. If the 333 * container is not an instance of CompositeActor, however, then 334 * this method does nothing. 335 * 336 * @exception IllegalActionException If any called method of one 337 * of the associated actors throws it. 338 */ 339 @Override 340 public void fire() throws IllegalActionException { 341 if (_debugging) { 342 _debug("Director: Called fire()."); 343 } 344 345 Nameable container = getContainer(); 346 347 if (container instanceof CompositeActor) { 348 Iterator<?> actors = ((CompositeActor) container).deepEntityList() 349 .iterator(); 350 int iterationCount = 1; 351 352 while (actors.hasNext() && !_stopRequested) { 353 Actor actor = (Actor) actors.next(); 354 355 if (_debugging) { 356 _debug(new FiringEvent(this, actor, 357 FiringEvent.BEFORE_ITERATE, iterationCount)); 358 } 359 360 if (actor.iterate(1) == Executable.STOP_ITERATING) { 361 if (_debugging) { 362 _debug("Actor requests halt: " 363 + ((Nameable) actor).getFullName()); 364 } 365 366 break; 367 } 368 369 if (_debugging) { 370 _debug(new FiringEvent(this, actor, 371 FiringEvent.AFTER_ITERATE, iterationCount)); 372 } 373 } 374 } 375 } 376 377 /** Request a firing of the given actor at the given absolute 378 * time. This method is only intended to be called from within 379 * main simulation thread. Actors that create their own 380 * asynchronous threads should used the fireAtCurrentTime() 381 * method to schedule firings. 382 * 383 * This method calls {@link #fireAt(Actor, Time)} method. 384 * 385 * @param actor The actor scheduled to be fired. 386 * @param time The scheduled time. 387 * @exception IllegalActionException If the operation is not 388 * permissible (e.g. the given time is in the past). 389 * @deprecated Instead of using double as time argument, use a 390 * time object instead. As of Ptolemy 4.1, replaced by 391 * {@link #fireAt(Actor, Time)} 392 */ 393 @Deprecated 394 public void fireAt(Actor actor, double time) throws IllegalActionException { 395 fireAt(actor, new Time(this, time)); 396 } 397 398 /** Request a firing of the given actor at the given model 399 * time. This base class ignores the request and returns a Time 400 * with value equal to the current time, unless this director 401 * is embedded within a model (and has an executive director), 402 * in which case, this base class requests that the executive 403 * director fire the container of this director at the requested 404 * time, adjusted by the current offset and drift of the local clock. 405 * It does this by delegating to {@link #fireContainerAt(Time, int)} 406 * with the microstep argument set to 1. 407 * <p> 408 * The intent of this method is to request a firing of the actor 409 * at the specified time, but this implementation does not assure 410 * that. In particular, if there is no executive director, it 411 * completely ignores the request. If there is an executive director, 412 * then it is not required to do the firing at the specified time. 413 * In particular, derived classes may override this method 414 * and modify the time of the firing, for example to prevent 415 * attempts to fire an actor in the past. 416 * <p> 417 * Derived classes should override this method to return the time at which 418 * they expect to fire the specified actor. It is up to the actor 419 * to throw an exception if it is not acceptable for the time 420 * to differ from the requested time. 421 * <p> 422 * Note that it is not correct behavior for a director to override 423 * this method to simply fire the specified actor. The actor needs 424 * to be fired as part of the regular execution cycle of that director, 425 * and that needs to occur after this method has returned. 426 * <p> 427 * <b>Note to authors of subclasses:</b> Usually you should not 428 * override this method, but rather override 429 * {@link #fireAt(Actor, Time, int)}. However, we cannot make 430 * this method final because occasionally a domain will change the 431 * default starting microstep. E.g., DE does this. 432 * @param actor The actor scheduled to be fired. 433 * @param time The requested time. 434 * @return An instance of Time with the current time value, or 435 * if there is an executive director, the time at which the 436 * container of this director will next be fired 437 * in response to this request. 438 * @see #fireAtCurrentTime(Actor) 439 * @exception IllegalActionException If there is an executive director 440 * and it throws it. Derived classes may choose to throw this 441 * exception for other reasons. 442 */ 443 public Time fireAt(Actor actor, Time time) throws IllegalActionException { 444 // Unless the actor specifically requests a particular microstep, 445 // we assume it knows nothing about microsteps. We use microstep 1 446 // as the default, since this is the default for discrete events. 447 // The Continuous domain will specifically request a firing at 448 // microstep 0. 449 return fireAt(actor, time, 1); 450 } 451 452 /** Request a firing of the given actor at the given model 453 * time with the given microstep. This method behaves exactly 454 * like {@link #fireAt(Actor, Time)}, except that it also 455 * passes up to the executive director the microstep, if there 456 * is one. 457 * This default implementation just delegates to 458 * {@link #fireContainerAt(Time, int)} 459 * @param actor The actor scheduled to be fired. 460 * @param time The requested time. 461 * @param microstep The requested microstep. 462 * @return An instance of Time with the current time value, or 463 * if there is an executive director, the time at which the 464 * container of this director will next be fired 465 * in response to this request. 466 * @see #fireAtCurrentTime(Actor) 467 * @see #fireContainerAt(Time) 468 * @exception IllegalActionException If there is an executive director 469 * and it throws it. Derived classes may choose to throw this 470 * exception for other reasons. 471 */ 472 public Time fireAt(Actor actor, Time time, int microstep) 473 throws IllegalActionException { 474 return fireContainerAt(time, microstep); 475 } 476 477 /** Request a firing of the given actor at the current model time or later. 478 * This base class simply calls fireAt(actor, getModelTime()) 479 * and returns whatever that returns. Note that fireAt() will modify 480 * the requested time if it happens to be in the past by the time 481 * it is to be posted on the event queue, which is exactly what we 482 * want. Note that the returned time may not match the value 483 * returned by getModelTime() prior to this call. 484 * <p> 485 * Note that it is not correct behavior for a director to override 486 * this method to simply fire the specified actor. The actor needs 487 * to be fired as part of the regular execution cycle of that director, 488 * and that needs to occur after this method has returned. 489 * @param actor The actor to be fired. 490 * @return The time at which the specified actor will be fired, 491 * which in this case is whatever fireAt() returns. 492 * @see #fireAt(Actor, Time) 493 * @exception IllegalActionException If this method is called 494 * before the model is running. 495 */ 496 public Time fireAtCurrentTime(Actor actor) throws IllegalActionException { 497 return fireAt(actor, getModelTime()); 498 } 499 500 /** Request a firing of the container of this director at the specified time 501 * and throw an exception if the executive director does not agree to 502 * do it at the requested time. If there is no executive director (this 503 * director is at the top level), then ignore the request. 504 * This is a convenience method provided because several directors need it. 505 * The requested microstep will be zero. 506 * @param time The requested time. 507 * @return The time that the executive director indicates it will fire this 508 * director, or an instance of Time with value equal to current time 509 * if there is no executive director. 510 * @exception IllegalActionException If the director does not 511 * agree to fire the actor at the specified time, or if there 512 * is no director. 513 */ 514 public Time fireContainerAt(Time time) throws IllegalActionException { 515 return fireContainerAt(time, _defaultMicrostep); 516 } 517 518 /** Request a firing of the container of this director at the specified time, 519 * adjusted by the current offset and drift of the local clock, 520 * and the specified microstep. 521 * Throw an exception if the executive director does not agree to 522 * do it at the requested time. If there is no executive director (this 523 * director is at the top level), then ignore the request and return 524 * a Time with value equal to the current time. 525 * The microstep argument is used by directors that implement 526 * {@link SuperdenseTimeDirector}. 527 * @param time The requested time. 528 * @param microstep The requested microstep. 529 * @return The time that the executive director indicates it will fire this 530 * director, or an instance of Time with value equal to current time 531 * if there is no executive director. 532 * @exception IllegalActionException If the director does not 533 * agree to fire the actor at the specified time, or if there 534 * is no director. 535 */ 536 public Time fireContainerAt(Time time, int microstep) 537 throws IllegalActionException { 538 Actor container = (Actor) getContainer(); 539 // Some composites, such as RunCompositeActor want to be treated 540 // as if they are at the top level even though they have an executive 541 // director, so be sure to check _isTopLevel(). 542 if (container != null && !_isTopLevel()) { 543 Director director = container.getExecutiveDirector(); 544 if (director != null) { 545 if (_debugging) { 546 _debug("**** Requesting that enclosing director refire me at " 547 + time + " with microstep " + microstep); 548 } 549 // Translate the local time into an environment time. 550 Time environmentTime = localClock 551 .getEnvironmentTimeForLocalTime(time); 552 Time result = director.fireAt(container, environmentTime, 553 microstep); 554 if (!result.equals(environmentTime)) { 555 throw new IllegalActionException(this, 556 "Timing incompatibility error: " 557 + director.getName() + " is unable to fire " 558 + container.getName() 559 + " at the requested time: " + time 560 + ". It responds it will fire it at: " 561 + result + "."); 562 } 563 // Translate the response from the environment into a local time. 564 return localClock.getLocalTimeForEnvironmentTime(result); 565 } 566 } 567 return localClock.getLocalTime(); 568 } 569 570 /** Return true if the next actor in the model governed by this director 571 * can be scheduled. The base class always returns true, but derived 572 * classes might override this. 573 * @return True if next actor to be fired can be scheduled. 574 * @exception IllegalActionException not thrown here. 575 */ 576 public boolean scheduleContainedActors() throws IllegalActionException { 577 return true; 578 } 579 580 /** Return a causality interface for the composite actor that 581 * contains this director. This base class returns an 582 * instance of {@link CausalityInterfaceForComposites}, but 583 * subclasses may override this to return a domain-specific 584 * causality interface. 585 * @return A representation of the dependencies between input ports 586 * and output ports of the container. 587 */ 588 public CausalityInterface getCausalityInterface() { 589 return new CausalityInterfaceForComposites((Actor) getContainer(), 590 defaultDependency()); 591 } 592 593 /** Return the current time value of the model being executed by this 594 * director. This time can be set with the setCurrentTime method. 595 * In this base class, time never increases, and there are no restrictions 596 * on valid times. 597 * 598 * @return The current time value. 599 * @deprecated As of Ptolemy II 4.1, replaced by 600 * {@link #getModelTime()} 601 * @see #setCurrentTime(double) 602 */ 603 @Deprecated 604 public double getCurrentTime() { 605 return getModelTime().getDoubleValue(); 606 } 607 608 /** Compute the deadline for an actor firing. In this base class, the deadline 609 * is set to the maximum value. 610 * @param actor The actor. 611 * @param timestamp The timestamp of the event that triggered the firing. 612 * @return The deadline. 613 * @exception IllegalActionException Thrown in subclasses. 614 */ 615 public Time getDeadline(NamedObj actor, Time timestamp) 616 throws IllegalActionException { 617 return Time.POSITIVE_INFINITY; 618 } 619 620 /** Get current environment time. 621 * This is the current time of the enclosing executive 622 * director, if there is one, and null otherwise. 623 * @return Environment time or null if the associated director is the top level director. 624 */ 625 public Time getEnvironmentTime() { 626 if (getContainer() instanceof Actor) { 627 Actor container = (Actor) getContainer(); 628 if (container != null && container.getContainer() != null) { 629 Director executiveDirector = container.getExecutiveDirector(); 630 // Some composites, such as RunCompositeActor want to be treated 631 // as if they are at the top level even though they have an executive 632 // director, so be sure to check _isTopLevel(). 633 if (executiveDirector != null && !_isTopLevel()) { 634 return executiveDirector.getModelTime(); 635 } 636 } 637 } 638 return localClock.getLocalTime(); 639 } 640 641 /** Return the global time for this model. The global time is 642 * defined to be the value returned by the @link{#getModelTime()} 643 * method of the top-level director in the model. 644 * @return The time of the top-level director in the model. 645 * @exception IllegalActionException If the top level is not an Actor. 646 */ 647 public Time getGlobalTime() throws IllegalActionException { 648 NamedObj toplevel = toplevel(); 649 if (!(toplevel instanceof Actor)) { 650 throw new IllegalActionException(this, 651 "Cannot get a global time because the top level is not an actor." 652 + " It is " + toplevel); 653 } 654 return ((Actor) toplevel).getDirector().getModelTime(); 655 } 656 657 /** Return the next time of interest in the model being executed by 658 * this director or the director of any enclosing model up the 659 * hierarchy. If this director is at the top level, then this 660 * default implementation simply returns the current time, since 661 * this director does not advance time. If this director is not 662 * at the top level, then return whatever the enclosing director 663 * returns. 664 * <p> 665 * This method is useful for domains that perform 666 * speculative execution (such as CT). Such a domain in a hierarchical 667 * model (i.e. CT inside DE) uses this method to determine how far 668 * into the future to execute. 669 * <p> 670 * Derived classes should override this method to provide an appropriate 671 * value, if possible. For example, the DEDirector class returns the 672 * time value of the next event in the event queue. 673 * @return The time of the next iteration. 674 * @exception IllegalActionException If time objects cannot be created. 675 * @see #getModelTime() 676 */ 677 public Time getModelNextIterationTime() throws IllegalActionException { 678 NamedObj container = getContainer(); 679 // NOTE: the container may not be a composite actor. 680 // For example, the container may be an entity as a library, 681 // where the director is already at the top level. 682 if (container instanceof CompositeActor) { 683 Director executiveDirector = ((CompositeActor) container) 684 .getExecutiveDirector(); 685 // Some composites, such as RunCompositeActor want to be treated 686 // as if they are at the top level even though they have an executive 687 // director, so be sure to check _isTopLevel(). 688 if (executiveDirector != null && !_isTopLevel()) { 689 return executiveDirector.getModelNextIterationTime(); 690 } 691 } 692 return getModelTime(); 693 } 694 695 /** Return the start time parameter value, if it has been explicitly 696 * set. Otherwise, return the current time of the enclosing director, 697 * if there is one, and return a Time with value 0.0 otherwise. 698 * @return the start time parameter value. 699 * @exception IllegalActionException If the executive director throws it. 700 */ 701 public final Time getModelStartTime() throws IllegalActionException { 702 703 // This method is final for performance reason. 704 if (_startTime == null) { 705 if (isEmbedded() && getContainer() instanceof Actor) { 706 // The previous implementation assumes this method is only called 707 // during initialize. This is not a valid assumption. 708 // It is called when attributeChanged() on startTime, and also 709 // when cloning. 710 Director executiveDirector = ((Actor) getContainer()) 711 .getExecutiveDirector(); 712 // Some composites, such as RunCompositeActor want to be treated 713 // as if they are at the top level even though they have an executive 714 // director, so be sure to check _isTopLevel(). 715 if (executiveDirector != null && !_isTopLevel()) { 716 return executiveDirector.getModelTime(); 717 } else { 718 return _zeroTime; 719 } 720 } else { 721 return _zeroTime; 722 } 723 } 724 return _startTime; 725 } 726 727 /** Return the stop time parameter value, if it has been set, 728 * and otherwise, return a time with value Double.POSITIVE_INFINITY. 729 * @return the stop time parameter value. 730 */ 731 public final Time getModelStopTime() { 732 if (_stopTime != null) { 733 return _stopTime; 734 } 735 return Time.POSITIVE_INFINITY; 736 } 737 738 /** Return the current time object of the model being executed by this 739 * director. 740 * This time can be set with the setModelTime method. In this base 741 * class, time never increases, and there are no restrictions on valid 742 * times. 743 * 744 * @return The current time. 745 * @see #setModelTime(Time) 746 */ 747 public Time getModelTime() { 748 return localClock.getLocalTime(); 749 } 750 751 /** Return the next time of interest in the model being executed by 752 * this director. This method is useful for domains that perform 753 * speculative execution (such as CT). Such a domain in a hierarchical 754 * model (i.e. CT inside DE) uses this method to determine how far 755 * into the future to execute. 756 * <p> 757 * In this base class, we return the current time. 758 * Derived classes should override this method to provide an appropriate 759 * value, if possible. 760 * <p> 761 * Note that this method is not made abstract to facilitate the use 762 * of the test suite. 763 * @return The time of the next iteration. 764 * @exception IllegalActionException If Time objects cannot be created. 765 * @deprecated As of Ptolemy II 4.1, replaced by 766 * {@link #getModelNextIterationTime} 767 */ 768 @Deprecated 769 public double getNextIterationTime() throws IllegalActionException { 770 return getModelNextIterationTime().getDoubleValue(); 771 } 772 773 /** Get the start time of the model. This base class returns 774 * a Time object with 0.0 as the value of the start time. 775 * Subclasses need to override this method to get a different 776 * start time. 777 * For example, CT director and DE director use the value of 778 * the startTime parameter to specify the real start time. 779 * @return The start time of the model. 780 * @deprecated As of Ptolemy II 4.1, replaced by 781 * {@link #getModelStartTime} 782 * @exception IllegalActionException If the specified start time 783 * is invalid. 784 */ 785 @Deprecated 786 public double getStartTime() throws IllegalActionException { 787 return 0.0; 788 } 789 790 /** Get the stop time of the model. This base class returns 791 * a new Time object with Double.MAX_VALUE as the value of the 792 * stop time. 793 * Subclasses need to override this method to get a different 794 * stop time. 795 * For example, CT director and DE director use the value of 796 * the stopTime parameter to specify the real stop time. 797 * @return The stop time of the model. 798 * @deprecated As of Ptolemy II 4.1, replaced by 799 * {@link #getModelStopTime} 800 * @exception IllegalActionException If the specified stop time 801 * is invalid. 802 */ 803 @Deprecated 804 public double getStopTime() throws IllegalActionException { 805 return getModelStopTime().getDoubleValue(); 806 } 807 808 /** Get the time resolution of the model. The time resolution is 809 * the value of the <i>timeResolution</i> parameter. This is the 810 * smallest time unit for the model. 811 * @return The time resolution of the model. 812 * @see #setTimeResolution(double) 813 */ 814 public final double getTimeResolution() { 815 // This method is final for performance reason. 816 return localClock.getTimeResolution(); 817 } 818 819 /** Return true if this director assumes and exports 820 * the strict actor semantics, as described in this paper: 821 * <p> 822 * A. Goderis, C. Brooks, I. Altintas, E. A. Lee, and C. Goble, 823 * "Heterogeneous Composition of Models of Computation," 824 * EECS Department, University of California, Berkeley, 825 * Tech. Rep. UCB/EECS-2007-139, Nov. 2007. 826 * http://www.eecs.berkeley.edu/Pubs/TechRpts/2007/EECS-2007-139.html 827 * <p> 828 * In particular, a director that implements this interface guarantees 829 * that it will not invoke the postfire() method of an actor until all 830 * its inputs are known at the current tag. Moreover, it it will only 831 * do so in its own postfire() method, and in its prefire() and fire() 832 * methods, it does not change its own state. Thus, such a director 833 * can be used within a model of computation that has a fixed-point 834 * semantics, such as SRDirector and ContinuousDirector. 835 * This base class returns false. 836 * @return True if the director assumes and exports strict actor semantics. 837 */ 838 public boolean implementsStrictActorSemantics() { 839 return false; 840 } 841 842 /** Initialize the model controlled by this director. Set the 843 * current time to the start time or the current time of the 844 * executive director, and then invoke the initialize() method 845 * of this director on each actor that is controlled by this director. 846 * If the container is not an instance of CompositeActor, do nothing. 847 * 848 * This method should typically be invoked once per execution, after the 849 * preinitialization phase, but before any iteration. It may be 850 * invoked in the middle of an execution, if reinitialization is 851 * desired. Since type resolution has been completed and the 852 * current time is set, the initialize() method of a contained 853 * actor may produce output or schedule events. If stop() is 854 * called during this methods execution, then stop initializing 855 * actors immediately. 856 * 857 * This method is <i>not</i> synchronized on the workspace, 858 * so the caller should be. 859 * 860 * @exception IllegalActionException If the initialize() method of 861 * one of the associated actors throws it. 862 */ 863 @Override 864 public void initialize() throws IllegalActionException { 865 // Note that the inner director in gt.TransformationRule 866 // does not call super.initialize(), so changes made to this 867 // method may apply there. 868 869 if (_debugging) { 870 _debug("Called initialize()."); 871 } 872 873 // First invoke initializable methods. 874 if (_initializables != null) { 875 for (Initializable initializable : _initializables) { 876 initializable.initialize(); 877 } 878 } 879 880 _actorsFinishedExecution = new HashSet(); 881 882 // Reset the flag that causes postfire() to return false. 883 _finishRequested = false; 884 885 localClock.resetLocalTime(getModelStartTime()); 886 localClock.start(); 887 888 if (_nextScheduleTime != null) { 889 _nextScheduleTime.clear(); 890 } 891 _tokenSentToCommunicationAspect = false; 892 893 // Initialize the contained actors. 894 Nameable container = getContainer(); 895 if (container instanceof CompositeActor) { 896 Iterator<?> actors = ((CompositeActor) container).deepEntityList() 897 .iterator(); 898 899 while (actors.hasNext() && !_stopRequested) { 900 Actor actor = (Actor) actors.next(); 901 902 if (_debugging) { 903 _debug("Invoking initialize(): ", 904 ((NamedObj) actor).getFullName()); 905 } 906 907 initialize(actor); 908 } 909 } 910 } 911 912 /** Initialize the given actor. This method is generally called 913 * by the initialize() method of the director, and by the manager 914 * whenever an actor is added to an executing model as a 915 * mutation. This method will generally perform domain-specific 916 * initialization on the specified actor and call its 917 * initialize() method. In this base class, only the actor's 918 * initialize() method of the actor is called and no 919 * domain-specific initialization is performed. Typical actions 920 * a director might perform include starting threads to execute 921 * the actor or checking to see whether the actor can be managed 922 * by this director. For example, a time-based domain (such as 923 * CT) might reject sequence based actors. 924 * @param actor The actor that is to be initialized. 925 * @exception IllegalActionException If the actor is not 926 * acceptable to the domain. Not thrown in this base class. 927 */ 928 public void initialize(Actor actor) throws IllegalActionException { 929 // FIXME: Note that ProcessDirector does *not* invoke this 930 // method, so changes made here might apply to 931 // ProcessDirector.initialize(Actor). 932 933 if (_debugging) { 934 _debug("Initializing actor: " + ((Nameable) actor).getFullName() 935 + "."); 936 } 937 938 actor.initialize(); 939 if (getExecutionAspect((NamedObj) actor) != null) { 940 _aspectsPresent = true; 941 } 942 } 943 944 /** Resume the execution of an actor that was previously blocked because 945 * it didn't have all the resources it needed for execution. This method 946 * is called by {@link ActorExecutionAspect} actors. 947 * 948 * In this base class, the implementation is empty. Derived directors 949 * should override this method to handle resuming of actor execution. 950 * @param actor The actor that resumes execution. 951 * @exception IllegalActionException Not thrown here but in derived classes. 952 */ 953 public void resumeActor(NamedObj actor) throws IllegalActionException { 954 } 955 956 /** Indicate that resolved types in the model may no longer be valid. 957 * This will force type resolution to be redone on the next iteration. 958 * This method simply defers to the manager, notifying it. If there 959 * is no container, or the container is not an instance of 960 * CompositeActor, or if it has no manager, do nothing. 961 */ 962 public void invalidateResolvedTypes() { 963 Nameable container = getContainer(); 964 965 if (container instanceof CompositeActor) { 966 Manager manager = ((CompositeActor) container).getManager(); 967 968 if (manager != null) { 969 manager.invalidateResolvedTypes(); 970 } 971 } 972 } 973 974 /** Indicate that a schedule for the model may no longer be valid, if 975 * there is a schedule. This method should be called when topology 976 * changes are made, or for that matter when any change that may 977 * invalidate the schedule is made. In this base class, the method 978 * does nothing. In derived classes, it will cause any static 979 * schedule information to be recalculated in the prefire method 980 * of the director. 981 */ 982 public void invalidateSchedule() { 983 } 984 985 /** Return true if this director is embedded inside an opaque composite 986 * actor contained by another composite actor. Note that some classes, 987 * such as RunCompositeActor, may return false even if they are actually 988 * embedded, but they want to be treated as if they were not. 989 * @return True if this directory is embedded inside an opaque composite 990 * actor contained by another composite actor. 991 * @see #setEmbedded(boolean) 992 */ 993 public final boolean isEmbedded() { 994 return !_isTopLevel(); 995 } 996 997 /** Return false. This director iterates actors in its fire() 998 * method, which includes an invocation of their postfire() 999 * methods, so its fire method changes the state of the model. 1000 * 1001 * @return False. 1002 */ 1003 @Override 1004 public boolean isFireFunctional() { 1005 return false; 1006 } 1007 1008 /** Return true. The transferInputs() method does not check whether 1009 * the inputs are known before calling hasToken(), and consequently 1010 * will throw an exception if inputs are not known. Thus, this 1011 * director requires that inputs be known in order to be able to 1012 * iterate. Derived classes that can tolerate unknown inputs 1013 * should override this method to return false. 1014 * 1015 * @return True. 1016 * @exception IllegalActionException Thrown by subclass. 1017 */ 1018 @Override 1019 public boolean isStrict() throws IllegalActionException { 1020 return true; 1021 } 1022 1023 /** Return true if stop has been requested. 1024 * @return True if stop() has been called. 1025 * @see #stop() 1026 */ 1027 public boolean isStopRequested() { 1028 return _stopRequested; 1029 } 1030 1031 /** Invoke a specified number of iterations of this director. An 1032 * iteration is equivalent to invoking prefire(), fire(), and 1033 * postfire(), in that order. In an iteration, if prefire() 1034 * returns true, then fire() will be called once, followed by 1035 * postfire(). Otherwise, if prefire() returns false, fire() 1036 * and postfire() are not invoked, and this method returns 1037 * NOT_READY. If postfire() returns false, then no more 1038 * iterations are invoked, and this method returns STOP_ITERATING. 1039 * Otherwise, it returns COMPLETED. Also, if the stop() is 1040 * called during this execution, then immediately stop iterating 1041 * and return STOP_ITERATING. 1042 * <p> 1043 * This base class method actually invokes prefire(), fire(), 1044 * and postfire(), as described above, but a derived class 1045 * may override the method to execute more efficient code. 1046 * 1047 * @param count The number of iterations to perform. 1048 * @return NOT_READY, STOP_ITERATING, or COMPLETED. 1049 * @exception IllegalActionException If iterating is not 1050 * permitted, or if prefire(), fire(), or postfire() throw it. 1051 */ 1052 @Override 1053 public int iterate(int count) throws IllegalActionException { 1054 int n = 0; 1055 1056 while (n++ < count && !_stopRequested) { 1057 if (prefire()) { 1058 fire(); 1059 1060 if (!postfire()) { 1061 return Executable.STOP_ITERATING; 1062 } 1063 } else { 1064 return Executable.NOT_READY; 1065 } 1066 } 1067 1068 if (_stopRequested) { 1069 return Executable.STOP_ITERATING; 1070 } else { 1071 return Executable.COMPLETED; 1072 } 1073 } 1074 1075 /** Return the object to use to obtain a mutex lock on this director. 1076 * This base class returns this director itself, but subclasses may 1077 * return something else. 1078 * @return An object to use to obtain a lock on this director. 1079 */ 1080 public Object mutexLockObject() { 1081 return this; 1082 } 1083 1084 /** Return a new receiver of a type compatible with this director. 1085 * In this base class, this returns an instance of Mailbox. 1086 * @return A new Mailbox. 1087 */ 1088 public Receiver newReceiver() { 1089 return new Mailbox(); 1090 } 1091 1092 /** Notify this director that a token was sent to a communication 1093 * aspect. Some directors need to perform specific actions but the 1094 * base class just sets a boolean flag. 1095 */ 1096 public void notifyTokenSentToCommunicationAspect() { 1097 _tokenSentToCommunicationAspect = true; 1098 } 1099 1100 /** Return true if the director wishes to be scheduled for another 1101 * iteration. This method is called by the container of 1102 * this director to see whether the director wishes to execute anymore. 1103 * It should <i>not</i>, in general, call postfire() on the contained 1104 * actors. 1105 * <p> 1106 * In this base class, return the false if stop() has been called 1107 * since preinitialize(), and true otherwise. Derived classes that 1108 * override this method need to respect this semantics. The 1109 * protected variable _stopRequested indicates whether stop() 1110 * has been called. 1111 * 1112 * @return True to continue execution, and false otherwise. 1113 * @exception IllegalActionException Not thrown in this base class. 1114 */ 1115 @Override 1116 public boolean postfire() throws IllegalActionException { 1117 if (_debugging) { 1118 _debug("Director: Called postfire()."); 1119 } 1120 return !_stopRequested && !_finishRequested; 1121 } 1122 1123 /** Return true if the director is ready to fire. This method is 1124 * called by the container of this director to determine whether the 1125 * director is ready to execute. It does <i>not</i> 1126 * call prefire() on the contained actors. 1127 * If this director is not at the top level of the hierarchy, 1128 * then this base class synchronizes to environment time, making 1129 * any necessary adjustments for drift or offset of the local clock. 1130 * <p> 1131 * In this base class, assume that the director is always ready to 1132 * be fired, and so return true. Domain directors should probably 1133 * override this method to provide domain-specific behavior. 1134 * However, they should call super.prefire() if they 1135 * wish to propagate time as done here. 1136 * 1137 * @return True. 1138 * @exception IllegalActionException Not thrown in this base class. 1139 */ 1140 @Override 1141 public boolean prefire() throws IllegalActionException { 1142 // FIXME: Note that ProcessDirector does *not* 1143 // invoke this method, so changes made here might 1144 // apply to ProcessDirector.prefire(). 1145 1146 if (_debugging) { 1147 _debug("Director: Called prefire()."); 1148 } 1149 1150 Time modifiedTime = _consultTimeRegulators( 1151 localClock.getLocalTimeForCurrentEnvironmentTime()); 1152 1153 setModelTime(modifiedTime); 1154 boolean noNewActors = true; 1155 List<TimeRegulator> regulators = getContainer() 1156 .attributeList(TimeRegulator.class); 1157 for (TimeRegulator regulator : regulators) { 1158 noNewActors = noNewActors && regulator.noNewActors(); 1159 } 1160 if (_debugging) { 1161 _debug("-- Setting current time to " + getModelTime()); 1162 } 1163 1164 return true && noNewActors; 1165 } 1166 1167 /** Validate the attributes and then invoke the preinitialize() 1168 * methods of all its deeply contained actors. 1169 * This method is invoked once per execution, before any 1170 * iteration, and before the initialize() method. 1171 * Time is not set during this stage. So preinitialize() method 1172 * of actors should not make use of time. They should wait 1173 * until the initialize phase of the execution. 1174 * <p>This method also resets the protected variable _stopRequested 1175 * to false, so if a derived class overrides this method, then it 1176 * should also do that. 1177 * <p>This method is <i>not</i> synchronized on the workspace, so the 1178 * caller should be. 1179 * 1180 * @exception IllegalActionException If the preinitialize() method of 1181 * one of the associated actors throws it. 1182 */ 1183 @Override 1184 public void preinitialize() throws IllegalActionException { 1185 // Note that the inner director in gt.TransformationRule 1186 // does not call super.preinitialize(), so changes made to this 1187 // method may apply there. 1188 1189 if (_debugging) { 1190 _debug(getFullName(), "Preinitializing ..."); 1191 } 1192 1193 // Support old models that set time resolution in director. 1194 Attribute timeResolution = getAttribute("timeResolution"); 1195 if (timeResolution != null) { 1196 double timeResolutionDouble = ((DoubleToken) ((Parameter) timeResolution) 1197 .getToken()).doubleValue(); 1198 try { 1199 timeResolution.setContainer(null); 1200 } catch (NameDuplicationException e) { 1201 // Can't happen. 1202 e.printStackTrace(); 1203 } 1204 localClock.globalTimeResolution.setToken("" + timeResolutionDouble); 1205 } 1206 _zeroTime = new Time(this, 0.0); 1207 localClock.initialize(); 1208 1209 // First invoke initializable methods. 1210 if (_initializables != null) { 1211 for (Initializable initializable : _initializables) { 1212 initializable.preinitialize(); 1213 } 1214 } 1215 1216 // validate all settable attributes. 1217 Iterator<?> attributes = attributeList(Settable.class).iterator(); 1218 while (attributes.hasNext()) { 1219 Settable attribute = (Settable) attributes.next(); 1220 attribute.validate(); 1221 } 1222 // In case the preinitialize() method of any actor 1223 // access current time, set the start time. This is required 1224 // for instance in DDF. 1225 // The following will be repeated in initialize(). 1226 localClock.resetLocalTime(getModelStartTime()); 1227 localClock.start(); 1228 1229 // preinitialize protected variables. 1230 _stopRequested = false; 1231 _finishRequested = false; 1232 1233 Nameable container = getContainer(); 1234 // Preinitialize all the contained actors. 1235 if (container instanceof CompositeActor) { 1236 // Populate any LazyTypedComposites. 1237 // Needed by $PTII/ptolemy/cg/lib/test/auto/ModularCodeGen4.xml 1238 Iterator entities = ((CompositeActor) toplevel()) 1239 .entityList(LazyComposite.class).iterator(); 1240 while (entities.hasNext()) { 1241 // LazyTypedCompositeActor implements ptolemy.kernel.util.LazyComposite, 1242 // which has a populate() method. We refer to the interface so 1243 // as to avoid a dependency between Director and LazyTypedCompositeActor. 1244 LazyComposite lazyComposite = (LazyComposite) entities.next(); 1245 lazyComposite.populate(); 1246 } 1247 1248 // Preinitialize all the contained actors. 1249 Iterator<?> actors = ((CompositeActor) container).deepEntityList() 1250 .iterator(); 1251 while (actors.hasNext()) { 1252 Actor actor = (Actor) actors.next(); 1253 if (_debugging) { 1254 _debug("Invoking preinitialize(): ", 1255 ((NamedObj) actor).getFullName()); 1256 } 1257 preinitialize(actor); 1258 } 1259 1260 // Don't need to create receivers if the workspace hasn't changed since the last run. 1261 // Note that we have to use the version recorded by the Manager on the last 1262 // completion of preinitializeAndResolveTypes() because otherwise, if there 1263 // are multiple directors, then the workspace version will always have changed 1264 // since the last run, since creatingReceivers itself changes it. 1265 Manager manager = ((Actor) container).getManager(); 1266 if (manager == null || manager 1267 .getPreinitializeVersion() != workspace().getVersion()) { 1268 // This increments the workspace version. 1269 _createReceivers(); 1270 } 1271 } 1272 1273 _aspectsPresent = false; 1274 1275 _executionAspects = new ArrayList<ActorExecutionAspect>(); 1276 _aspectForActor = new HashMap<NamedObj, ActorExecutionAspect>(); 1277 if (getContainer() instanceof CompositeActor) { 1278 for (Object entity : ((CompositeActor) getContainer()) 1279 .entityList(ActorExecutionAspect.class)) { 1280 ActorExecutionAspect aspect = (ActorExecutionAspect) entity; 1281 _executionAspects.add(aspect); 1282 } 1283 _aspectsPresent = ((CompositeActor) getContainer()) 1284 .entityList(CommunicationAspect.class).size() > 0; 1285 } 1286 1287 if (_debugging) { 1288 _debug(getFullName(), "Finished preinitialize()."); 1289 } 1290 } 1291 1292 /** 1293 * Preinitialize the actor. 1294 * This method is used by directors that want to instrument calls to 1295 * preinitialize. {@link #preinitialize()} calls this method. 1296 * @param actor The actor to be preinitialized. 1297 * @exception IllegalActionException If thrown while the actor is being 1298 * preinitialized. 1299 * @see #preinitialize() 1300 */ 1301 public void preinitialize(Actor actor) throws IllegalActionException { 1302 actor.preinitialize(); 1303 } 1304 1305 /** Remove the specified object from the list of objects whose 1306 * preinitialize(), initialize(), and wrapup() 1307 * methods should be invoked upon invocation of the corresponding 1308 * methods of this object. If the specified object is not 1309 * on the list, do nothing. 1310 * @param initializable The object whose methods should no longer be invoked. 1311 * @see #addInitializable(Initializable) 1312 * @see ptolemy.actor.CompositeActor#removePiggyback(Executable) 1313 */ 1314 @Override 1315 public void removeInitializable(Initializable initializable) { 1316 if (_initializables != null) { 1317 _initializables.remove(initializable); 1318 if (_initializables.size() == 0) { 1319 _initializables = null; 1320 } 1321 } 1322 } 1323 1324 /** Queue an initialization request with the manager. 1325 * The specified actor will be initialized at an appropriate time, 1326 * between iterations, by calling its preinitialize() and initialize() 1327 * methods. This method is called by CompositeActor when an actor 1328 * sets its container to that composite actor. Typically, that 1329 * will occur when a model is first constructed, and during the 1330 * execute() method of a ChangeRequest. 1331 * In this base class, the request is delegated 1332 * to the manager. If there is no manager, or if the container 1333 * is not an instance of CompositeActor, then do nothing. 1334 * @param actor The actor to initialize. 1335 */ 1336 public void requestInitialization(Actor actor) { 1337 Nameable container = getContainer(); 1338 1339 if (container instanceof CompositeActor) { 1340 Manager manager = ((CompositeActor) container).getManager(); 1341 1342 if (manager != null) { 1343 manager.requestInitialization(actor); 1344 } 1345 } 1346 } 1347 1348 /** Start or resume the actor, which means (re)start the local clock. 1349 * If the clock is not stopped then this has no effect. 1350 * @exception IllegalActionException If the fireAt() request throws it. 1351 */ 1352 public void resume() throws IllegalActionException { 1353 localClock.start(); 1354 } 1355 1356 /** Specify the container. If the specified container is an instance 1357 * of CompositeActor, then this becomes the active director for 1358 * that composite. Otherwise, this is an attribute like any other within 1359 * the container. If the container is not in the same 1360 * workspace as this director, throw an exception. 1361 * If this director is already an attribute of the container, 1362 * then this has the effect only of making it the active director. 1363 * If this director already has a container, remove it 1364 * from that container first. Otherwise, remove it from 1365 * the directory of the workspace, if it is present. 1366 * If the argument is null, then remove it from its container. 1367 * This director is not added to the workspace directory, so calling 1368 * this method with a null argument could result in 1369 * this director being garbage collected. 1370 * <p> 1371 * If this method results in removing this director from a container 1372 * that is a CompositeActor, then this director ceases to be the active 1373 * director for that CompositeActor. Moreover, if the composite actor 1374 * contains any other directors, then the most recently added of those 1375 * directors becomes the active director. 1376 * <p> 1377 * This method is write-synchronized 1378 * to the workspace and increments its version number. 1379 * @param container The proposed container. 1380 * @exception IllegalActionException If the action would result in a 1381 * recursive containment structure, or if 1382 * this director and container are not in the same workspace, or 1383 * if the protected method _checkContainer() throws it. 1384 * @exception NameDuplicationException If the name of this director 1385 * collides with a name already in the container. This will not 1386 * be thrown if the container argument is an instance of 1387 * CompositeActor. 1388 */ 1389 @Override 1390 public void setContainer(NamedObj container) 1391 throws IllegalActionException, NameDuplicationException { 1392 try { 1393 _workspace.getWriteAccess(); 1394 1395 Nameable oldContainer = getContainer(); 1396 1397 if (oldContainer instanceof CompositeActor 1398 && oldContainer != container) { 1399 // Need to remove this director as the active one of the 1400 // old container. Search for another director contained 1401 // by the composite. If it contains more than one, 1402 // use the most recently added one. 1403 Director previous = null; 1404 CompositeActor castContainer = (CompositeActor) oldContainer; 1405 Iterator<?> directors = castContainer 1406 .attributeList(Director.class).iterator(); 1407 1408 while (directors.hasNext()) { 1409 Director altDirector = (Director) directors.next(); 1410 1411 // Since we haven't yet removed this director, we have 1412 // to be sure to not just set it to the active 1413 // director again. 1414 if (altDirector != this) { 1415 previous = altDirector; 1416 } 1417 } 1418 1419 castContainer._setDirector(previous); 1420 } 1421 1422 super.setContainer(container); 1423 1424 if (container instanceof CompositeActor) { 1425 // Set cached value in composite actor. 1426 ((CompositeActor) container)._setDirector(this); 1427 } 1428 } finally { 1429 _workspace.doneWriting(); 1430 } 1431 } 1432 1433 /** Set a new value to the current time of the model, where 1434 * the new time must be no earlier than the current time. 1435 * Derived classes will likely override this method to ensure that 1436 * the time is valid. 1437 * 1438 * @param newTime The new current simulation time. 1439 * @exception IllegalActionException If the new time is less than 1440 * the current time returned by getCurrentTime(). 1441 * @deprecated As of Ptolemy 4.1, replaced by 1442 * {@link #setModelTime} 1443 * @see #getCurrentTime() 1444 */ 1445 @Deprecated 1446 public void setCurrentTime(double newTime) throws IllegalActionException { 1447 setModelTime(new Time(this, newTime)); 1448 } 1449 1450 /** With a false argument, force this director to behave as if it is 1451 * a top-level director even if it is not. This is used by composite 1452 * actors such as RunCompositeActor that need for the inside director 1453 * to behave as if it is running at the top level. 1454 * @param force False to force this director to behave as if it were 1455 * not embedded. 1456 * @see #isEmbedded() 1457 */ 1458 public final void setEmbedded(boolean force) { 1459 if (!force) { 1460 _notEmbeddedForced = true; 1461 } 1462 } 1463 1464 /** Set a new value to the current time of the model. 1465 * @param newTime The new current simulation time. 1466 * @exception IllegalActionException If the new time is less than 1467 * the current time returned by getCurrentTime(). 1468 * @see #getModelTime() 1469 */ 1470 public void setModelTime(Time newTime) throws IllegalActionException { 1471 localClock.setLocalTime(newTime); 1472 } 1473 1474 /** Set time resolution. 1475 * @param timeResolution The new time resolution. 1476 * @see #getTimeResolution() 1477 */ 1478 public void setTimeResolution(double timeResolution) { 1479 localClock.setTimeResolution(timeResolution); 1480 } 1481 1482 /** Request that the director cease execution altogether. 1483 * This causes a call to stop() on all actors contained by 1484 * the container of this director, and sets a flag 1485 * so that the next call to postfire() returns false. 1486 * 1487 * <p> The stop() method requests immediate stopping. To give 1488 * determinate stopping, call finish() so that the 1489 * current iteration is completed.</p> 1490 * 1491 * <p>In multithreaded domains, Director.stopFire() is called 1492 * to request that all actors conclude ongoing firings.</p> 1493 * 1494 */ 1495 @Override 1496 public void stop() { 1497 // Set _stopRequested first before looping through actors below 1498 // so isStopRequested() more useful while we are still looping 1499 // below. Kepler's EML2000DataSource needed this. 1500 _stopRequested = true; 1501 1502 Nameable container = getContainer(); 1503 1504 if (container instanceof CompositeActor) { 1505 Iterator<?> actors = ((CompositeActor) container).deepEntityList() 1506 .iterator(); 1507 1508 while (actors.hasNext()) { 1509 Actor actor = (Actor) actors.next(); 1510 actor.stop(); 1511 } 1512 } 1513 } 1514 1515 /** Request that execution of the current iteration stop. 1516 * In this base class, the request is simply passed on to all actors 1517 * that are deeply contained by the container of this director. 1518 * For most domains, an iteration is a finite computation, so nothing 1519 * further needs to be done here. However, for some process-oriented 1520 * domains, the fire() method of the director is an unbounded computation. 1521 * Those domains should override this method so that when it is called, 1522 * it does whatever it needs to do to get the fire() method to return. 1523 * Typically, it will set flags that will cause all executing threads 1524 * to suspend. These domains should suspend execution in such a way 1525 * that if the fire() method is called again, execution will 1526 * resume at the point where it was suspended. However, they should 1527 * not assume the fire() method will be called again. It is possible 1528 * that the wrapup() method will be called next. 1529 * If the container is not an instance of CompositeActor, then this 1530 * method does nothing. 1531 */ 1532 @Override 1533 public void stopFire() { 1534 Nameable container = getContainer(); 1535 1536 if (container instanceof CompositeActor) { 1537 Iterator<?> actors = ((CompositeActor) container).deepEntityList() 1538 .iterator(); 1539 1540 while (actors.hasNext()) { 1541 Actor actor = (Actor) actors.next(); 1542 actor.stopFire(); 1543 } 1544 } 1545 } 1546 1547 /** Return an array of suggested directors to be used with 1548 * ModalModel. Each director is specified by its full class 1549 * name. The first director in the array will be the default 1550 * director used by a modal model. This base class delegates 1551 * to the executive director, if there is one, and otherwise 1552 * returns an array with only one element, 1553 * "ptolemy.domains.modal.kernel.FSMDirector". 1554 * @return An array of suggested directors to be used with ModalModel. 1555 */ 1556 public String[] suggestedModalModelDirectors() { 1557 NamedObj container = getContainer(); 1558 if (container instanceof Actor) { 1559 Director executiveDirector = ((Actor) container) 1560 .getExecutiveDirector(); 1561 // Some composites, such as RunCompositeActor want to be treated 1562 // as if they are at the top level even though they have an executive 1563 // director, so be sure to check _isTopLevel(). 1564 if (executiveDirector != null && !_isTopLevel()) { 1565 return executiveDirector.suggestedModalModelDirectors(); 1566 } 1567 } 1568 // Default is just one suggestion. 1569 String[] defaultSuggestions = { 1570 "ptolemy.domains.modal.kernel.FSMDirector" }; 1571 return defaultSuggestions; 1572 } 1573 1574 /** Return a boolean to indicate whether a ModalModel under control 1575 * of this director supports multirate firing. In this class, false 1576 * is always returned. Subclasses may override this method to return true. 1577 * @return False indicating a ModalModel under control of this director 1578 * does not support multirate firing. 1579 */ 1580 public boolean supportMultirateFiring() { 1581 return false; 1582 } 1583 1584 /** Suspend the actor at the specified time. This will stop the local 1585 * clock. 1586 */ 1587 public void suspend() { 1588 localClock.stop(); 1589 } 1590 1591 /** Terminate any currently executing model with extreme prejudice. 1592 * This method is not intended to be used as a normal route of 1593 * stopping execution. To normally stop execution, call the finish() 1594 * method instead. This method should be called only 1595 * when execution fails to terminate by normal means due to certain 1596 * kinds of programming errors (infinite loops, threading errors, etc.). 1597 * There is no assurance that the topology will be in a consistent 1598 * state after this method returns. The 1599 * topology should probably be recreated before attempting any 1600 * further operations. 1601 * <p> 1602 * This base class recursively calls terminate() on all actors deeply 1603 * contained by the container of this director. Derived classes should 1604 * override this method to release all resources in use and kill 1605 * any sub-threads. Derived classes should not synchronize this 1606 * method because it should execute as soon as possible. 1607 * If the container is not an instance of CompositeActor, then 1608 * this method does nothing.</p> 1609 */ 1610 @Override 1611 public void terminate() { 1612 Nameable container = getContainer(); 1613 1614 if (container instanceof CompositeActor) { 1615 Iterator<?> actors = ((CompositeActor) container).deepEntityList() 1616 .iterator(); 1617 1618 while (actors.hasNext()) { 1619 Actor actor = (Actor) actors.next(); 1620 actor.terminate(); 1621 } 1622 } 1623 } 1624 1625 /** Transfer data from an input port of the container to the ports 1626 * it is connected to on the inside. The implementation in this 1627 * base class transfers at most one token. Derived classes may override 1628 * this method to transfer a domain-specific number of tokens. 1629 * 1630 * @param port The port to transfer tokens from. 1631 * @return True if at least one data token is transferred. 1632 * @exception IllegalActionException If the port is not an opaque 1633 * input port. 1634 */ 1635 public boolean transferInputs(IOPort port) throws IllegalActionException { 1636 // Use a strategy pattern here so that the code that transfers 1637 // at most one token is available to any derived class. 1638 return _transferInputs(port); 1639 } 1640 1641 /** Transfer data from all output ports of the container to the 1642 * ports they are connected to on the outside. This base class 1643 * iterates over the ports in their natural order and delegates to 1644 * {@link #transferOutputs(IOPort)} to actually do the transfer. 1645 * Override this method if you need to change the order in which 1646 * the transfers occur. 1647 * @exception IllegalActionException Not thrown in this base class. 1648 */ 1649 public void transferOutputs() throws IllegalActionException { 1650 NamedObj container = getContainer(); 1651 if (container instanceof Actor) { 1652 List<IOPort> outports = ((Actor) container).outputPortList(); 1653 for (IOPort port : outports) { 1654 transferOutputs(port); 1655 } 1656 } 1657 } 1658 1659 /** Transfer data from an output port of the container to the 1660 * ports it is connected to on the outside. The implementation 1661 * in this base class transfers at most 1662 * one token, but derived classes may transfer more than one 1663 * token. 1664 * @param port The port to transfer tokens from. 1665 * @return True if at least one data token is transferred. 1666 * @exception IllegalActionException If the port is not an opaque 1667 * output port. 1668 */ 1669 public boolean transferOutputs(IOPort port) throws IllegalActionException { 1670 // Use a strategy pattern here so that the code that transfers 1671 // at most one token is available to any derived class. 1672 return _transferOutputs(port); 1673 } 1674 1675 /** Invoke the wrapup() method of all the actors contained in the 1676 * director's container. In this base class wrapup() is called on the 1677 * associated actors in the order of their creation. If the container 1678 * is not an instance of CompositeActor, then this method does nothing. 1679 * <p> 1680 * This method should be invoked once per execution. None of the other 1681 * action methods should be invoked after it in the execution. 1682 * This method is <i>not</i> synchronized on the workspace, so the 1683 * caller should be. 1684 * 1685 * @exception IllegalActionException If the wrapup() method of 1686 * one of the associated actors throws it. 1687 */ 1688 @Override 1689 public void wrapup() throws IllegalActionException { 1690 // FIXME: Note that ProcessDirector and the inner director in 1691 // gt TransformationRule do not invoke this method, so changes 1692 // made here might apply to ProcessDirector.wrapup(). 1693 1694 if (_debugging) { 1695 _debug("Director: Called wrapup()."); 1696 } 1697 1698 // Collect all the exception messages that occur, but ensure that each 1699 // wrapup method is called. 1700 List<Throwable> exceptions = new LinkedList<Throwable>(); 1701 1702 // First invoke initializable methods. 1703 if (_initializables != null) { 1704 for (Initializable initializable : _initializables) { 1705 try { 1706 initializable.wrapup(); 1707 } catch (Throwable ex) { 1708 exceptions.add(ex); 1709 } 1710 } 1711 } 1712 1713 Nameable container = getContainer(); 1714 1715 if (container instanceof CompositeActor) { 1716 Iterator<?> actors = ((CompositeActor) container).deepEntityList() 1717 .iterator(); 1718 1719 while (actors.hasNext()) { 1720 Actor actor = (Actor) actors.next(); 1721 try { 1722 actor.wrapup(); 1723 } catch (Throwable ex) { 1724 exceptions.add(ex); 1725 } 1726 } 1727 } 1728 if (exceptions.size() > 0) { 1729 StringBuffer message = new StringBuffer( 1730 "Exceptions occurred during wrapup:\n"); 1731 for (Throwable ex : exceptions) { 1732 message.append(ex); 1733 message.append("\n"); 1734 } 1735 throw new IllegalActionException(this, exceptions.get(0), 1736 message.toString()); 1737 } 1738 } 1739 1740 /////////////////////////////////////////////////////////////////// 1741 //// protected methods //// 1742 1743 /** Return true if the actor finished execution. 1744 * @param actor The actor. 1745 * @return True if the actor finished execution. 1746 */ 1747 protected boolean _actorFinished(NamedObj actor) { 1748 return _aspectForActor.get(actor) != null 1749 && _aspectForActor.get(actor).lastScheduledActorFinished(); 1750 } 1751 1752 /** Consult all attributes contained by the container of this director 1753 * that implement the {@link TimeRegulator} interface, if any, and return the 1754 * smallest time returned by those regulators. If there are no such 1755 * attributes, return the proposedTime argument. 1756 * @param proposedTime The time proposed. 1757 * @return The smallest time returned by a TimeRegulator, or the 1758 * proposedTime if none. 1759 * @exception IllegalActionException If a time regulator throws it. 1760 */ 1761 protected Time _consultTimeRegulators(Time proposedTime) 1762 throws IllegalActionException { 1763 Time returnValue = proposedTime; 1764 List<TimeRegulator> regulators = getContainer() 1765 .attributeList(TimeRegulator.class); 1766 for (TimeRegulator regulator : regulators) { 1767 Time modifiedTime = regulator.proposeTime(returnValue); 1768 if (modifiedTime.compareTo(returnValue) < 0) { 1769 returnValue = modifiedTime; 1770 } 1771 } 1772 return returnValue; 1773 } 1774 1775 /** Return a description of the object. The level of detail depends 1776 * on the argument, which is an or-ing of the static final constants 1777 * defined in the NamedObj class. Lines are indented according to 1778 * to the level argument using the protected method _getIndentPrefix(). 1779 * Zero, one or two brackets can be specified to surround the returned 1780 * description. If one is specified it is the the leading bracket. 1781 * This is used by derived classes that will append to the description. 1782 * Those derived classes are responsible for the closing bracket. 1783 * An argument other than 0, 1, or 2 is taken to be equivalent to 0. 1784 * This method is read-synchronized on the workspace. 1785 * @param detail The level of detail. 1786 * @param indent The amount of indenting. 1787 * @param bracket The number of surrounding brackets (0, 1, or 2). 1788 * @return A description of the object. 1789 * @exception IllegalActionException If thrown while getting the 1790 * description of subcomponents. 1791 */ 1792 @Override 1793 protected String _description(int detail, int indent, int bracket) 1794 throws IllegalActionException { 1795 try { 1796 _workspace.getReadAccess(); 1797 1798 String result; 1799 1800 if (bracket == 1 || bracket == 2) { 1801 result = super._description(detail, indent, 1); 1802 } else { 1803 result = super._description(detail, indent, 0); 1804 } 1805 1806 // FIXME: Add director-specific information here, like 1807 // what is the state of the director. 1808 // if ((detail & FIXME) != 0 ) { 1809 // if (result.trim().length() > 0) { 1810 // result += " "; 1811 // } 1812 // result += "FIXME {\n"; 1813 // result += _getIndentPrefix(indent) + "}"; 1814 // } 1815 if (bracket == 2) { 1816 result += "}"; 1817 } 1818 1819 return result; 1820 } finally { 1821 _workspace.doneReading(); 1822 } 1823 } 1824 1825 /** Return true if this director is embedded inside an opaque composite 1826 * actor contained by another composite actor. 1827 * @return True if this directory is embedded inside an opaque composite 1828 * actor contained by another composite actor. 1829 * @deprecated Use {@link #isEmbedded()} instead 1830 */ 1831 @Deprecated 1832 protected boolean _isEmbedded() { 1833 return isEmbedded(); 1834 } 1835 1836 /** Return true if this is a top-level director, or if it should 1837 * always be handled as if it were a top-level director. 1838 * Parts of this method is read synchronized on the workspace. 1839 * @return True if this director is at the top-level. 1840 */ 1841 protected boolean _isTopLevel() { 1842 if (_notEmbeddedForced) { 1843 return true; 1844 } 1845 NamedObj container = getContainer(); 1846 1847 // NOTE: the container may not be a composite actor. 1848 // For example, the container may be an entity as a library, 1849 // where the director is already at the top level. 1850 if (container instanceof CompositeActor) { 1851 if (((CompositeActor) container).getExecutiveDirector() == null) { 1852 return true; 1853 } else { 1854 return false; 1855 } 1856 } 1857 1858 return true; 1859 } 1860 1861 /** Find the ExecutionAspect for the actor. Only one ExecutionAspect 1862 * is returned at this point. 1863 * @param actor The actor to be scheduled. 1864 * @return The aspect. 1865 * @exception IllegalActionException If thrown while getting the 1866 * enable token or the decorator. 1867 */ 1868 public ActorExecutionAspect getExecutionAspect(NamedObj actor) 1869 throws IllegalActionException { 1870 if (_aspectForActor == null) { 1871 _aspectForActor = new HashMap<NamedObj, ActorExecutionAspect>(); 1872 } 1873 ActorExecutionAspect result = _aspectForActor.get(actor); 1874 if (result == null) { 1875 for (ExecutionAttributes executionAttributes : actor 1876 .attributeList(ExecutionAttributes.class)) { 1877 if (((BooleanToken) executionAttributes.enable.getToken()) 1878 .booleanValue()) { 1879 result = (ActorExecutionAspect) executionAttributes 1880 .getDecorator(); 1881 _aspectForActor.put(actor, result); 1882 break; 1883 } 1884 } 1885 } 1886 return result; 1887 } 1888 1889 /** Transfer at most one data token from the given input port of 1890 * the container to the ports it is connected to on the inside. 1891 * This method delegates the operation to the IOPort, so that the 1892 * subclass of IOPort, TypedIOPort, can override this method to 1893 * perform run-time type conversion. 1894 * 1895 * @param port The port to transfer tokens from. 1896 * @return True if at least one data token is transferred. 1897 * @exception IllegalActionException If the port is not an opaque 1898 * input port. 1899 * @see IOPort#transferInputs 1900 */ 1901 protected boolean _transferInputs(IOPort port) 1902 throws IllegalActionException { 1903 if (_debugging) { 1904 _debug("Calling transferInputs on port: " + port.getFullName()); 1905 } 1906 1907 if (!port.isInput() || !port.isOpaque()) { 1908 throw new IllegalActionException(this, port, 1909 "Attempted to transferInputs on a port is not an opaque" 1910 + "input port."); 1911 } 1912 1913 boolean wasTransferred = false; 1914 1915 for (int i = 0; i < port.getWidth(); i++) { 1916 try { 1917 if (i < port.getWidthInside()) { 1918 if (port.hasToken(i)) { 1919 Token t = port.get(i); 1920 1921 if (_debugging) { 1922 _debug("Transferring input " + t + " from " 1923 + port.getName()); 1924 } 1925 1926 port.sendInside(i, t); 1927 wasTransferred = true; 1928 } 1929 } else { 1930 // No inside connection to transfer tokens to. 1931 // In this case, consume one input token if there is one. 1932 if (_debugging) { 1933 _debug(getName(), 1934 "Dropping single input from " + port.getName()); 1935 } 1936 1937 if (port.isKnown() && port.hasToken(i)) { 1938 port.get(i); 1939 } 1940 } 1941 } catch (NoTokenException ex) { 1942 // this shouldn't happen. 1943 throw new InternalErrorException(this, ex, null); 1944 } 1945 } 1946 1947 return wasTransferred; 1948 } 1949 1950 /** Transfer at most one data token from the given output port of 1951 * the container to the ports it is connected to on the outside.. 1952 * @param port The port to transfer tokens from. 1953 * @return True if the port has an inside token that was successfully 1954 * transferred. Otherwise return false (or throw an exception). 1955 * @exception IllegalActionException If the port is not an opaque 1956 * output port 1957 * 1958 */ 1959 protected boolean _transferOutputs(IOPort port) 1960 throws IllegalActionException { 1961 boolean result = false; 1962 if (_debugging) { 1963 _debug("Calling transferOutputs on port: " + port.getFullName()); 1964 } 1965 1966 if (!port.isOutput() || !port.isOpaque()) { 1967 throw new IllegalActionException(this, port, 1968 "Attempted to transferOutputs on a port that " 1969 + "is not an opaque input port."); 1970 } 1971 1972 for (int i = 0; i < port.getWidthInside(); i++) { 1973 try { 1974 if (port.hasTokenInside(i)) { 1975 Token t = port.getInside(i); 1976 1977 if (_debugging) { 1978 _debug(getName(), "transferring output " + t + " from " 1979 + port.getName()); 1980 } 1981 1982 port.send(i, t); 1983 result = true; 1984 } 1985 } catch (NoTokenException ex) { 1986 // this shouldn't happen. 1987 throw new InternalErrorException(this, ex, null); 1988 } 1989 } 1990 return result; 1991 } 1992 1993 /** Schedule an actor for execution on a ExecutionAspect. If the actor can 1994 * execute this method returns true. If resources are not available this 1995 * method returns false. 1996 * @param actor The actor. 1997 * @param timestamp The time the actor requests to be scheduled. 1998 * @return True if actor was scheduled and can be fired. 1999 * @exception IllegalActionException Thrown if parameters cannot be read, actor cannot be 2000 * scheduled or container cannot be fired at future time. 2001 */ 2002 protected boolean _schedule(NamedObj actor, Time timestamp) 2003 throws IllegalActionException { 2004 ActorExecutionAspect aspect = getExecutionAspect(actor); 2005 Time time = null; 2006 Boolean finished = true; 2007 if (timestamp == null) { 2008 timestamp = getModelTime(); 2009 } 2010 if (aspect != null) { 2011 Time environmentTime = ((CompositeActor) aspect.getContainer()) 2012 .getDirector().getEnvironmentTime(); 2013 time = ExecutionAspectHelper.schedule(aspect, actor, 2014 environmentTime, getDeadline(actor, timestamp)); 2015 if (_nextScheduleTime == null) { 2016 _nextScheduleTime = new HashMap<ActorExecutionAspect, Time>(); 2017 } 2018 _nextScheduleTime.put(aspect, time); 2019 finished = _actorFinished(actor); 2020 if (time != null && time.getDoubleValue() > 0.0) { 2021 CompositeActor container = (CompositeActor) aspect 2022 .getContainer(); 2023 Time fireAtTime = environmentTime; 2024 if (!time.equals(Time.POSITIVE_INFINITY)) { 2025 fireAtTime = fireAtTime.add(time); 2026 container.getDirector().fireContainerAt(fireAtTime); 2027 } 2028 } 2029 } 2030 return time == null || finished; 2031 } 2032 2033 /** Set of actors that have returned false from postfire(), 2034 * indicating that they do not wish to be iterated again. 2035 */ 2036 protected Set _actorsFinishedExecution; 2037 2038 /** Contains a map of actors and the ExecutionAspect that is specified for the actor. */ 2039 protected HashMap<NamedObj, ActorExecutionAspect> _aspectForActor; 2040 2041 /** True if any of the directed actors specifies a ExecutionAspect 2042 * in the parameters and this ExecutionAspect exists on this or 2043 * a hierarchy level above (i.e. has not been deleted). 2044 */ 2045 protected boolean _aspectsPresent; 2046 2047 /** The director's default microstep. */ 2048 protected int _defaultMicrostep; 2049 2050 /** ExecutionAspects in the container of this director. 2051 */ 2052 protected List<ActorExecutionAspect> _executionAspects; 2053 2054 /** Indicator that finish() has been called. */ 2055 protected boolean _finishRequested; 2056 2057 /** Set of objects whose (pre)initialize() and wrapup() methods 2058 * should be slaved to these. 2059 */ 2060 protected transient Set<Initializable> _initializables; 2061 2062 /** Next time the aspect wants to be executed. */ 2063 protected HashMap<ActorExecutionAspect, Time> _nextScheduleTime; 2064 2065 /** Flag set to true if a token has been sent to a communication aspect 2066 * by any port/receiver where the aspect is enabled. 2067 */ 2068 protected boolean _tokenSentToCommunicationAspect; 2069 2070 /** Indicator that a stop has been requested by a call to stop(). */ 2071 protected boolean _stopRequested = false; 2072 2073 /** Time with value 0.0. */ 2074 protected Time _zeroTime; 2075 2076 /////////////////////////////////////////////////////////////////// 2077 //// private methods //// 2078 // Add an XML graphic as a hint to UIs for rendering the director. 2079 private void _addIcon() { 2080 _attachText("_iconDescription", 2081 "<svg>\n" + "<rect x=\"-50\" y=\"-15\" " 2082 + "width=\"100\" height=\"30\" " 2083 + "style=\"fill:green\"/>\n" + "</svg>\n"); 2084 } 2085 2086 /** Create receivers for all contained actors. 2087 * @exception IllegalActionException If any port of a contained 2088 * actor throws it when its receivers are created. 2089 * @see Actor#createReceivers 2090 */ 2091 private void _createReceivers() throws IllegalActionException { 2092 Nameable container = getContainer(); 2093 if (container instanceof CompositeActor) { 2094 for (Object actor : ((CompositeActor) container).deepEntityList()) { 2095 ((Actor) actor).createReceivers(); 2096 } 2097 } 2098 } 2099 2100 /** Initialize parameters. This is called by the constructor. 2101 * @exception IllegalActionException 2102 * @exception NameDuplicationException 2103 */ 2104 private void _initializeParameters() 2105 throws IllegalActionException, NameDuplicationException { 2106 localClock = new LocalClock(this, "localClock"); 2107 2108 startTime = new Parameter(this, "startTime"); 2109 startTime.setTypeEquals(BaseType.DOUBLE); 2110 2111 stopTime = new Parameter(this, "stopTime"); 2112 stopTime.setTypeEquals(BaseType.DOUBLE); 2113 2114 _defaultMicrostep = 0; 2115 2116 } 2117 2118 /////////////////////////////////////////////////////////////////// 2119 //// private variables //// 2120 2121 /** Flag indicating that this director has been forced to behave 2122 * as if it were at the top level. 2123 */ 2124 private transient boolean _notEmbeddedForced = false; 2125 2126 /** Start time. */ 2127 private transient Time _startTime; 2128 2129 /** Stop time. */ 2130 private transient Time _stopTime; 2131 2132}