001/* A Manager governs the execution of a model.
002
003 Copyright (c) 1997-2017 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 execute catches Exceptions and rethrows them as runtime exceptions. why?
028 requestInitialization is pickier about what actors are initialized.
029 added preinitialization analyses (i.e. constVariableModelAnalysis)
030 Look over exitAfterWrapup().
031 */
032package ptolemy.actor;
033
034import java.lang.ref.WeakReference;
035import java.util.Date;
036import java.util.HashMap;
037import java.util.LinkedList;
038import java.util.List;
039import java.util.ListIterator;
040import java.util.Map;
041import java.util.WeakHashMap;
042
043import ptolemy.kernel.ComponentEntity;
044import ptolemy.kernel.CompositeEntity;
045import ptolemy.kernel.util.ExceptionHandler;
046import ptolemy.kernel.util.IllegalActionException;
047import ptolemy.kernel.util.InternalErrorException;
048import ptolemy.kernel.util.KernelException;
049import ptolemy.kernel.util.Nameable;
050import ptolemy.kernel.util.NamedObj;
051import ptolemy.kernel.util.PtolemyThread;
052import ptolemy.kernel.util.Workspace;
053import ptolemy.util.MessageHandler;
054import ptolemy.util.StringUtilities;
055
056///////////////////////////////////////////////////////////////////
057//// Manager
058
059/**
060 A Manager governs the execution of a model in a domain-independent way.
061 Its methods are designed to be called by a GUI, an applet, a command-line
062 interface, or the top-level code of an application.  The manager can
063 execute the model in the calling thread or in a separate thread.
064 The latter is useful when the caller wishes to remain live during
065 the execution of the model.
066
067 <p> There are three methods that can be used to start execution of a
068 system attached to the manager.  The execute() method is the most
069 basic way to execute a model.  The model will be executed
070 <i>synchronously</i>, meaning that the execute() method will return
071 when execution has completed.  Any exceptions that occur will be
072 thrown by the execute method to the calling thread, and will not be
073 reported to any execution listeners.  The run() method also initiates
074 synchronous execution of a model, but additionally catches all
075 exceptions and passes them to the notifyListenersOfException() method
076 <i>without throwing them to the calling thread</i>.  The startRun()
077 method, unlike the previous two techniques, begins <i>asynchronous</i>
078 execution of a model.  This method starts a new thread for execution
079 of the model and then returns immediately.  Exceptions are reported
080 using the notifyListenersOfException() method.
081
082 <p> In addition, execution can be manually driven, one phase at a
083 time, using the methods initialize(), iterate() and wrapup().  This is
084 most useful for testing purposes.  For example, a type system check
085 only needs to get the resolved types, which are found during
086 initialize, so the test can avoid actually executing the system.
087 Also, when testing mutations, the model can be examined after each
088 toplevel iteration to ensure the proper behavior.
089
090 <p> A manager provides services for cleanly handling changes to the
091 topology.  These include such changes as adding or removing an entity,
092 port, or relation, creating or destroying a link, and changing the
093 value or type of a parameter.  Collectively, such changes are called
094 <i>mutations</i>. Usually, mutations cannot safely occur at arbitrary
095 points in the execution of a model.  Models can queue mutations with
096 any object in the hierarchy or with the manager using the
097 requestChange() method.  An object in the hierarchy simply delegates
098 the request to its container, so the request propagates up the
099 hierarchy until it gets to the top level composite actor, which
100 delegates to the manager, which performs the change at the earliest
101 opportunity.  In this implementation of Manager, the changes are
102 executed between iterations.
103
104 <p> A service is also provided whereby an object can be registered
105 with the composite actor as a change listener.  A change listener is
106 informed when mutations that are requested via requestChange() are
107 executed successfully, or when they fail with an exception.
108
109 <p> Manager can optimize the performance of an execution by making the
110 workspace <i>write protected</i> during an iteration, if all relevant
111 directors permit this.  This removes some of the overhead of obtaining
112 read and write permission on the workspace.  By default, directors do
113 not permit this, but many directors explicitly relinquish write access
114 to allow faster execution.  Such directors are declaring that they
115 will not make changes to the topology during execution.  Instead, any
116 desired mutations are delegated to the manager via the requestChange()
117 method.
118
119 <p> Many domains make use of static analyses for performing, e.g.,
120 static scheduling of actor firings.  In some cases, these analyses
121 must make use of global information.  The class provides a centralized
122 mechanism for managing such global analyses.  During preinitialize,
123 domains can invoke the getAnalysis and addAnalysis methods to create a
124 global analysis.  It is up to the users of this mechanism to ensure
125 that a particular type of analysis is only created once, if that is
126 what is required.  After preinitialize, the manager clears the list of
127 analyses, to avoid unnecessary memory usage, and to ensure that the
128 analyses are performed again on the next invocation of the model.
129 This is somewhat preferable to tying a cache of analysis information
130 to the version of the workspace, since the version number of the
131 workspace itself may change during preinitialize as domains add
132 annotation to the model.
133
134 @author Steve Neuendorffer, Lukito Muliadi, Edward A. Lee, Elaine Cheong, Contributor: Mudit Goel, John S. Davis II, Bert Rodiers, Daniel Crawl
135 @version $Id$
136 @since Ptolemy II 0.2
137 @Pt.ProposedRating Green (neuendor)
138 @Pt.AcceptedRating Yellow (cxh)
139 */
140public class Manager extends NamedObj implements Runnable {
141
142    /** Construct a manager in the default workspace with an empty string
143     *  as its name. The manager is added to the list of objects in
144     *  the workspace. Increment the version number of the workspace.
145     */
146    public Manager() {
147        super();
148    }
149
150    /** Construct a manager in the default workspace with the given name.
151     *  If the name argument is null, then the name is set to the empty
152     *  string. The manager is added to the list of objects in the workspace.
153     *  Increment the version number of the workspace.
154     *  @param name Name of this Manager.
155     *  @exception IllegalActionException If the name has a period.
156     */
157    public Manager(String name) throws IllegalActionException {
158        super(name);
159    }
160
161    /** Construct a manager in the given workspace with the given name.
162     *  If the workspace argument is null, use the default workspace.
163     *  The manager is added to the list of objects in the workspace.
164     *  If the name argument is null, then the name is set to the
165     *  empty string. Increment the version number of the workspace.
166     *
167     *  @param workspace Object for synchronization and version tracking.
168     *  @param name Name of this Manager.
169     *  @exception IllegalActionException If the name has a period.
170     */
171    public Manager(Workspace workspace, String name)
172            throws IllegalActionException {
173        super(workspace, name);
174    }
175
176    ///////////////////////////////////////////////////////////////////
177    ////                         public variables                  ////
178    // NOTE: The following names of states should fit into the sentence:
179    // "The model is ... "
180
181    /** Indicator that the model may be corrupted.
182     */
183    public final static State CORRUPTED = new State("corrupted");
184
185    /** Indicator that there is no currently active execution.
186     */
187    public final static State IDLE = new State("idle");
188
189    /** Indicator that width inference is being done.
190     */
191    public final static State INFERING_WIDTHS = new State("infering widths");
192
193    /** Indicator that the execution is in the initialize phase.
194     */
195    public final static State INITIALIZING = new State("initializing");
196
197    /** Indicator that the execution is in an iteration.
198     */
199    public final static State ITERATING = new State("executing");
200
201    /** Indicator that the execution is paused.
202     */
203    public final static State PAUSED = new State("pausing execution");
204
205    /** Indicator that the execution is paused on a breakpoint.
206     */
207    public final static State PAUSED_ON_BREAKPOINT = new State(
208            "pausing execution on a breakpoint");
209
210    /** Indicator that the execution is in the preinitialize phase.
211     */
212    public final static State PREINITIALIZING = new State("preinitializing");
213
214    /** Indicator that type resolution is being done.
215     */
216    public final static State RESOLVING_TYPES = new State("resolving types");
217
218    /** Indicator that the execution is throwing a throwable.
219     */
220    public final static State THROWING_A_THROWABLE = new State(
221            "throwing a throwable");
222
223    /** Indicator that the execution is in the wrapup phase.
224     */
225    public final static State WRAPPING_UP = new State("wrapping up");
226
227    /** Indicator that the execution is in the wrapup phase and about
228     *  to exit.
229     */
230    public final static State EXITING = new State("exiting");
231
232    ///////////////////////////////////////////////////////////////////
233    ////                         public methods                    ////
234
235    /** Add a static analysis to this manager. A static analysis is
236     *  simply an object that is recorded in a hash table and cleared
237     *  at the end of preinitialize(), with no semantics associated
238     *  with that object.  The intent is for that object to serve as a
239     *  repository for static analysis results, but clearing it and
240     *  the end of preinitialize isn't quite right. The idea is that
241     *  it is cleared at a point when the analysis has to be redone
242     *  after that point. But doing this at the end of preinitialize
243     *  means this won't work with models that mutate either during
244     *  preinitialize() (as in higher- order actors) or during
245     *  execution.
246     *
247     *  @param name The name of the analysis.
248     *  @param analysis The analysis to record.
249     *  @see #getAnalysis(String)
250     */
251    public void addAnalysis(String name, Object analysis) {
252        if (_nameToAnalysis == null) {
253            _nameToAnalysis = new HashMap<String, Object>();
254        }
255
256        _nameToAnalysis.put(name, analysis);
257    }
258
259    /** Add a listener to be notified when the model execution changes state.
260     *  If the specified listener is already a listener, do nothing.
261     *  @param listener The listener.
262     *  @see #removeExecutionListener(ExecutionListener)
263     */
264    public void addExecutionListener(ExecutionListener listener) {
265        if (listener == null) {
266            return;
267        }
268
269        if (_executionListeners == null) {
270            _executionListeners = new LinkedList<WeakReference<ExecutionListener>>();
271        }
272
273        // Do not add the same listener twice, so if it is already in the list,
274        // remove it. See NamedObj.addChangeListener(). -- tfeng
275        removeExecutionListener(listener);
276
277        _executionListeners.add(new WeakReference<ExecutionListener>(listener));
278    }
279
280    /** Return the elapsed time (in milliseconds) since the start of execution
281     *  of the model. The start of execution is defined to be the time after
282     *  initialize() has been called and before any component has been iterated.
283     *  @return The time in milliseconds since the start of execution of the model.
284     */
285    public long elapsedTimeSinceStart() {
286        long currentTime = System.currentTimeMillis();
287        return currentTime - _afterInitTime;
288    }
289
290    /** Enable or disable printing time and memory usage at the end of model
291     *  execution.
292     *
293     *  @param enabled Whether time and memory printing is enabled.
294     */
295    public void enablePrintTimeAndMemory(boolean enabled) {
296        _printTimeAndMemory = enabled;
297    }
298
299    /** Execute the model.  Begin with the initialization phase, followed
300     *  by a sequence of iterations, followed by a wrapup phase.
301     *  The sequence of iterations concludes when the postfire() method
302     *  of the container (the top-level composite actor) returns false,
303     *  or when the finish() method is called.
304     *  <p>
305     *  The execution is performed in the calling thread (the current thread),
306     *  so this method returns only after execution finishes.
307     *  If you wish to perform execution in a new thread, use startRun()
308     *  instead.  Even if an exception occurs during the execution, the
309     *  wrapup() method is called (in a finally clause).
310     *  <p>
311     *  If an exception occurs during the execution, delegate to the
312     *  exception handlers (if there are any) to handle these exceptions.
313     *  If there are no exception handlers, it is up to the
314     *  caller to handle (e.g. report) the exception.
315     *  If you do not wish to handle exceptions, but want to execute
316     *  within the calling thread, use run().
317     *  @see #run()
318     *  @exception KernelException If the model throws it.
319     *  @exception IllegalActionException If the model is already running, or
320     *   if there is no container.
321     */
322    public void execute() throws KernelException, IllegalActionException {
323        // NOTE: This method used to be synchronized, but holding the
324        // lock on the Manager for the duration of an execution creates
325        // endless possibilities for deadlock.  So instead, we put
326        // a small barrier here and throw an exception if the model
327        // is already running.
328        synchronized (this) {
329            if (_state != IDLE) {
330                throw new IllegalActionException(this,
331                        "Model is already running.");
332            }
333        }
334
335        // Make a record of the time execution starts.
336        long startTime = System.currentTimeMillis();
337
338        _debug("-- Manager execute() called.");
339
340        // Reset this in case finish() has been called since the last run.
341        _finishRequested = false;
342
343        boolean completedSuccessfully = false;
344
345        // If we throw an throwable, we save it until after the
346        // finally clauses.
347        Throwable initialThrowable = null;
348
349        try {
350            try {
351                // Register the shutdown hook each time we register as
352                // opposed to each time a Manager is instantiated.
353                // See
354                // https://projects.ecoinformatics.org/ecoinfo/issues/7189
355                _registerShutdownHook();
356                initialize();
357                _afterInitTime = System.currentTimeMillis();
358                if (_afterInitTime - startTime > minimumStatisticsTime) {
359                    setStatusMessage(timeAndMemory(startTime));
360                    System.out.println("Manager.initialize() finished: "
361                            + getStatusMessage());
362                }
363
364                // Call iterate() until finish() is called or postfire()
365                // returns false.
366                _debug("-- Manager beginning to iterate.");
367
368                while (!_finishRequested) {
369                    if (!iterate()) {
370                        break;
371                    }
372
373                    if (_pauseRequested) {
374                        // Have to synchronize on this to be able to wait
375                        // during the pause.
376                        synchronized (this) {
377                            _setState(PAUSED);
378                            try {
379                                // Enable processing of change requests so that editing is live.
380                                setDeferringChangeRequests(false);
381                                while (_pauseRequested && !_finishRequested) {
382                                    try {
383                                        wait();
384                                    } catch (InterruptedException e) {
385                                        // ignore.
386                                    }
387                                }
388                            } finally {
389                                setDeferringChangeRequests(true);
390                            }
391                        }
392                    }
393                }
394
395                completedSuccessfully = true;
396            } catch (Throwable throwable) {
397                // Catch anything that can be throw (Error, Exception etc.)
398                // Catching just KernelException will not work, since
399                // we want to be sure to rethrow things like LinkErrors.
400                // We use THROWING_A_THROWABLE in NonStrictTest.wrapup()
401                // so we be sure the actor fires and reads enough inputs.
402                _setState(THROWING_A_THROWABLE);
403                initialThrowable = throwable;
404            }
405        } finally {
406            try {
407                wrapup();
408            } catch (Exception exception) {
409                // Caught an exception. Discard this exception
410                // if there is an exception thrown during the iteration.
411                // Otherwise, save the exception to be handled later.
412                if (initialThrowable == null) {
413                    initialThrowable = exception;
414                }
415            } finally {
416                // Indicate that it is now safe to execute
417                // change requests when they are requested.
418                setDeferringChangeRequests(false);
419
420                // NOTE: This used to increment the workspace
421                // version, which would require that everything
422                // be re-done on subsequent runs. EAL 9/16/06
423                // _workspace.incrVersion();
424
425                // Reset this for the next run.
426                _finishRequested = false;
427
428                // Wrapup may also throw an exception,
429                // So be sure to reset the state to idle!
430                if (_state != IDLE) {
431                    _setState(IDLE);
432                }
433
434                // Wrapup may throw an exception, so put the following
435                // statement inside the finally block.
436                if (_printTimeAndMemory) {
437                    setStatusMessage(timeAndMemory(startTime));
438                    System.out.println(getStatusMessage());
439                }
440
441                if (completedSuccessfully && initialThrowable == null) {
442                    // The Exit.tcl test needs this because otherwise
443                    // we throw an exception in wrapup(), but
444                    // notifyListenersOfSuccessfulCompletion() was
445                    // called which causes MoMLSimpleApplication to
446                    // exit before MoMLSimpleApplication was notified
447                    // of the exception.
448
449                    _notifyListenersOfSuccessfulCompletion();
450                }
451
452                // Remove the _shutdownThread.
453                // See https://projects.ecoinformatics.org/ecoinfo/issues/7189
454                _disposeOfThreads();
455
456                // Handle throwable with exception handlers,
457                // if there are any.
458                if (initialThrowable != null) {
459                    if (_container == null || _container.get() == null) {
460                        throw new InternalErrorException(this, initialThrowable,
461                                "The container of the manager was null. "
462                                        + "Try calling composite.setManager().");
463                    }
464                    // Look for attributes and entities that implement ExceptionHandler.
465                    CompositeActor container = _container.get();
466                    List<ExceptionHandler> exceptionHandlersList = container
467                            .attributeList(ExceptionHandler.class);
468                    exceptionHandlersList.addAll(
469                            container.entityList(ExceptionHandler.class));
470                    boolean exceptionHandled = false;
471                    for (ExceptionHandler exceptionHandler : exceptionHandlersList) {
472                        // Note that we allow multiple exception handlers
473                        // to handle the same exception. So we iterate all
474                        // of the exception handlers, at least until one
475                        // those throws an exception.
476                        if (exceptionHandler.handleException(container,
477                                initialThrowable)) {
478                            exceptionHandled = true;
479                        }
480                    }
481                    if (exceptionHandled) {
482                        initialThrowable = null;
483                        _notifyListenersOfSuccessfulCompletion();
484                    }
485                }
486
487                // If the throwable has not been handled by exception handlers,
488                // throw it.
489                if (initialThrowable != null) {
490                    if (initialThrowable instanceof RuntimeException) {
491                        // We do not handle runtime exception.
492                        // Throw it.
493                        throw (RuntimeException) initialThrowable;
494                    } else if (initialThrowable instanceof KernelException) {
495                        // Since this class is declared to throw
496                        // KernelException, if we have one, we throw it.
497                        throw (KernelException) initialThrowable;
498                    } else if (initialThrowable instanceof RuntimeException) {
499                        // We do not handle runtime exception.
500                        // Throw it.
501                        throw (RuntimeException) initialThrowable;
502                    } else {
503                        // Ok, it is not a KernelException, so we
504                        // rethrow it as the cause of a KernelException
505                        throw new IllegalActionException(this, initialThrowable,
506                                null);
507                    }
508                }
509            }
510        }
511        /*
512        System.out.println("Manager.execute() finished: "
513                + timeAndMemory(startTime));
514         */
515    }
516
517    /** Cause the system to exit after wrapup().
518     *  If the ptolemy.ptII.exitAfterWrapup property is <b>not</b>
519     *  set, then when wrapup() is almost finished, we call System.exit().
520     *  If the ptolemy.ptII.exitAfterWrapup property is set, then
521     *  we throw an Exception.
522     */
523    public void exitAfterWrapup() {
524        _exitAfterWrapup = true;
525        _setState(EXITING);
526    }
527
528    /** If the state is not IDLE, set a flag to request that execution
529     *  stop and exit in a completely deterministic fashion at the end
530     *  of the next toplevel iteration.  This method may be called
531     *  from within an actor to stop the execution of the model.  This
532     *  will result in stop() being called on the top level
533     *  CompositeActor, although not necessarily immediately.  Note
534     *  that this method is allowed to be called if the model is
535     *  paused and actors that implement the stop() method must
536     *  properly respond to that method even if the model is paused.
537     *  @see Executable#stop
538     */
539    public void finish() {
540        // Set this regardless of whether the model is running to
541        // avoid race conditions.  The model may not have gotten around
542        // to starting when finish is requested.
543        _finishRequested = true;
544
545        if (_debugging) {
546            _debug("finish() has been called.");
547        }
548
549        if (_state == IDLE) {
550            // Don't need to invoke _disposeOfThreads()
551            // here because it is invoked in the finally clause
552            // of execute().
553            // if (_thread != null || _shutdownThread != null) {
554            //     _disposeOfThreads();
555            // }
556            return;
557        }
558
559        Nameable container = getContainer();
560
561        if (!(container instanceof CompositeActor)) {
562            throw new InternalErrorException(
563                    "Attempted to call finish() on an executing manager "
564                            + "with no associated CompositeActor model");
565        }
566
567        // Used to just call stopFire() here, but this does not set
568        // the flag in the director so that isStopRequested() returns
569        // true. We have to set that flag or the actor threads in
570        // threaded domains will not know that a stop has been requested
571        // (vs. a pause).
572        ((CompositeActor) container).stop();
573
574        Thread unpauser = new UnpauserThread();
575        unpauser.start();
576    }
577
578    /** Get the analysis with the given name, or return null if no such
579     *  analysis exists.
580     *  @param name The name of the analysis.
581     *  @return the analysis with the given name, or null.
582     *  @see #addAnalysis(String, Object)
583     */
584    public Object getAnalysis(String name) {
585        if (_nameToAnalysis == null) {
586            return null;
587        } else {
588            return _nameToAnalysis.get(name);
589        }
590    }
591
592    /** Get the real time at which the model began executing.
593     * @return The real time at which the model began executing.
594     */
595    public long getRealStartTime() {
596        return _afterInitTime;
597    }
598
599    /** Return the top-level composite actor for which this manager
600     *  controls execution.
601     *  @return The composite actor that this manager is responsible for.
602     */
603    @Override
604    public NamedObj getContainer() {
605        if (_container == null) {
606            return null;
607        }
608        return _container.get();
609    }
610
611    /** Return the iteration count, which is the number of iterations
612     *  that have been started (but not necessarily completed).
613     *  @return The number of iterations started.
614     */
615    public int getIterationCount() {
616        return _iterationCount;
617    }
618
619    /** Return the workspace version on the last completion of
620     *  preinitializeAndResolveTypes(). This can be used to optimize
621     *  away actions on repeated runs when the workspace hasn't changed
622     *  between runs.
623     *  @return the workspace version on the last completion of
624     *  {@link #preinitializeAndResolveTypes()}.
625     */
626    public long getPreinitializeVersion() {
627        return _preinitializeVersion;
628    }
629
630    /** Return the current state of execution of the manager.
631     *  @return The state of execution.
632     */
633    public State getState() {
634        return _state;
635    }
636
637    /** Return any messages, such as the amount of time consumed.
638     *  This method is called to update the status bar, so the
639     *  output should be short.
640     *  @return the message
641     *  @see #setStatusMessage(String)
642     */
643    public String getStatusMessage() {
644        return _statusMessage;
645    }
646
647    /** Get the execution identifier object for a throwable.
648     *
649     * <p> An execution identifier is an object given to the Manager
650     * via setExecutionIdentifier(), and cleared during preinitialize().
651     * If the Manager notifies a listener of a model error,
652     * getExecutionIdentifier() can be used to map that error back to
653     * the executionIdentifier object.
654     *
655     * @param throwable The throwable.
656     * @return The execution identifier object if one was set, otherwise null.
657     * @see #setExecutionIdentifier(Object)
658     */
659    public Object getExecutionIdentifier(Throwable throwable) {
660        // See http://bugzilla.ecoinformatics.org/show_bug.cgi?id=4230
661
662        // "In SDF provenance records to the error table an exception
663        // thrown after the workflow stops. In PN, multiple exceptions
664        // may be thrown, and this happens during execution. Right now
665        // there's a problem with these errors getting
666        // recorded. Related/in addition: there's also difficulty
667        // knowing which execution errors are correlated with, since
668        // the same workflow may be executing and throwing errors in
669        // multiple windows. As Dan notes: Manager reports exceptions
670        // asynchronously; need a way to tie an exception to
671        // corresponding execution."
672
673        // "The issue is that the Manager notifies listeners of model
674        // errors asynchronously to avoid deadlocks.  However, this
675        // makes it impossible for a listener to associate a specific
676        // execution cycle with a given error."
677        return _throwableToExecutionIdentifier.get(throwable);
678    }
679
680    /** Return a thread that is waiting and can be
681     *  interrupted in the event that a change request is made,
682     *  or null to indicate that there is no thread waiting.
683     *  @return The thread that is waiting, or null to indicate
684     *   that no thread is waiting.
685     *  @see #setWaitingThread(Thread)
686     */
687    public Thread getWaitingThread() {
688        return _waitingThread;
689    }
690
691    /** Initialize the model.  This calls the preinitialize() method of
692     *  the container, followed by the resolveTypes() and initialize() methods.
693     *  Set the Manager's state to PREINITIALIZING and INITIALIZING as
694     *  appropriate.
695     *  This method is read synchronized on the workspace.
696     *  @exception KernelException If the model throws it.
697     *  @exception IllegalActionException If the model is already running, or
698     *   if there is no container.
699     */
700    public synchronized void initialize()
701            throws KernelException, IllegalActionException {
702        try {
703            _workspace.getReadAccess();
704
705            // Make sure that change requests are not executed when requested,
706            // but rather only executed when executeChangeRequests() is called.
707            setDeferringChangeRequests(true);
708
709            long startTime = new Date().getTime();
710            preinitializeAndResolveTypes();
711            if (System.currentTimeMillis()
712                    - startTime > minimumStatisticsTime) {
713                setStatusMessage(timeAndMemory(startTime));
714                System.out.println(
715                        "preinitialize() finished: " + getStatusMessage());
716            }
717
718            _setState(INITIALIZING);
719            if (_container == null || _container.get() == null) {
720                throw new InternalErrorException(this, null,
721                        "The container of the manager was null. "
722                                + "Try calling composite.setManager().");
723            }
724            _container.get().initialize();
725
726            // Since we have just initialized all actors, clear the
727            // list of actors pending initialization.
728            _actorsToInitialize.clear();
729
730            executeChangeRequests();
731        } finally {
732            _workspace.doneReading();
733        }
734    }
735
736    /** Indicate that resolved types in the system may no longer be valid.
737     *  This will force type resolution to be redone on the next iteration.
738     */
739    public void invalidateResolvedTypes() {
740        _typesResolved = false;
741    }
742
743    /** Return true if exitAfterWrapup() was called.
744     *  @return true if exitAfterWrapup was called.
745     */
746    public boolean isExitingAfterWrapup() {
747        return _exitAfterWrapup;
748    }
749
750    /** Invoke one iteration of the model.  An iteration consists of
751     *  first performing changes queued with requestChange()
752     *  and type resolution, if necessary, and then
753     *  invoking prefire(), fire(), and postfire(), in that
754     *  order. If prefire() returns false, then fire() and postfire() are not
755     *  invoked, and true is returned.
756     *  Otherwise, fire() will be called once, followed by
757     *  postfire(). The return value of postfire() is returned.
758     *  Note that this method ignores finish and pause requests
759     *  and thus determines a minimum granularity of the execution.
760     *  Set the state of the manager to ITERATING.
761     *  This method is read synchronized on the workspace.
762     *
763     *  @return True if postfire() is not called, otherwise, return
764     *  the value returned by postfire().
765     *
766     *  @exception KernelException If the model throws it, or if there
767     *   is no container.
768     */
769    public boolean iterate() throws KernelException {
770        if (_container == null || _container.get() == null) {
771            throw new IllegalActionException(this, "No model to execute!  "
772                    + "Try calling composite.setManager()");
773        }
774
775        boolean result = true;
776
777        long startTime = new Date().getTime();
778        // Execute the change requests before acquiring read access on the
779        // workspace. The reason for this is that the change requests are safe
780        // anyway, since they acquire write access on the workspace.
781        // But while copying the change request list in the NamedObj
782        // executeChangeRequest method, this thread will try to acquire a lock
783        // on a local NamedObj object called _changeLock.
784        // If it blocks, it will hold a read lock on the workspace.
785        // Meanwhile, the thread that holds the lock on _changeLock
786        // may attempt to acquire write permission on the workspace (WHY???).
787        executeChangeRequests();
788        try {
789            _workspace.getReadAccess();
790
791            // We should infer the widths before preinitializing the container, since the latter
792            // will create the receivers for which it needs the widths of the relations.
793            if (IORelation._USE_NEW_WIDTH_INFERENCE_ALGO) {
794                _inferWidths();
795            }
796
797            // Pre-initialize actors that have been added.
798            for (Actor actor : _actorsToInitialize) {
799                // Do not attempt to preinitialize transparent composite actors.
800                // Note that the cast is safe, as everything in Ptolemy that
801                // is an actor is also a ComponentEntity.
802                if (((ComponentEntity) actor).isOpaque()) {
803                    actor.getExecutiveDirector().preinitialize(actor);
804                }
805
806                // NOTE: To see why this is no longer needed, see the comment
807                // above for the commented out call to validateSettables().
808                /*
809                 if (actor instanceof NamedObj) {
810                 ((NamedObj) actor).validateSettables();
811                 }
812                 */
813            }
814            if (System.currentTimeMillis()
815                    - startTime > minimumStatisticsTime) {
816                setStatusMessage(timeAndMemory(startTime));
817                System.out
818                        .println("Manager.iterate(): preinitialize() finished: "
819                                + getStatusMessage());
820            }
821
822            if (!_typesResolved) {
823                resolveTypes();
824                _typesResolved = true;
825            }
826
827            _iterationCount++;
828            _setState(ITERATING);
829
830            // Perform domain-specific initialization on the actor.
831            // Do not attempt to initialize transparent composite actors.
832            // Note that the cast is safe, as everything in Ptolemy that
833            // is an actor is also a ComponentEntity.
834            for (Actor actor : _actorsToInitialize) {
835                if (((ComponentEntity) actor).isOpaque()) {
836                    actor.getExecutiveDirector().initialize(actor);
837                }
838            }
839
840            _actorsToInitialize.clear();
841
842            // Note that if prefire() returns false, then postfire()
843            // is *not* called and this method will return true, which
844            // indicate to a caller of this method that iterate()
845            // could be called again. This is because if prefire
846            // returns false, it means "I don't want to be fired now."
847            // If postfire returns false, it means "I don't want to
848            // ever be fired again."
849            CompositeActor container = _container.get();
850            if (container.prefire()) {
851                container.fire();
852                result = container.postfire();
853            }
854        } finally {
855            _workspace.doneReading();
856        }
857
858        return result;
859    }
860
861    /** Notify all the execution listeners of an exception.
862     *  If there are no listeners, then print the exception information
863     *  to the standard error stream. This is intended to be used by threads
864     *  that are involved in an execution as a mechanism for reporting
865     *  errors.  As an example, in a threaded domain, each thread
866     *  should catch all exceptions and report them using this method.
867     *  This method is merely calls
868     *  {@link #notifyListenersOfThrowable(Throwable)}.
869     *  @param exception The exception.
870     */
871    public void notifyListenersOfException(Exception exception) {
872        notifyListenersOfThrowable(exception);
873    }
874
875    /** Notify all the execution listeners of a Throwable.
876     *  If there are no listeners, then print the throwable information
877     *  to the standard error stream. This is intended to be used by threads
878     *  that are involved in an execution as a mechanism for reporting
879     *  errors.  As an example, in a threaded domain, each thread
880     *  should catch all exceptions and report them using this method.
881     *  This method defers the actual reporting to a new thread
882     *  because it requires obtaining a lock on this manager, and that
883     *  could cause deadlock.
884     *  @param throwable The throwable
885     */
886    public void notifyListenersOfThrowable(final Throwable throwable) {
887        Thread thread = new ErrorReportingThread("Error reporting thread",
888                throwable);
889        thread.start();
890    }
891
892    /** Set a flag requesting that execution pause at the next opportunity
893     *  (between iterations).  This method calls stopFire() on the
894     *  toplevel composite actor to ensure that the manager's execution
895     *  thread becomes active again. Actors are expected to react to
896     *  stopFire() by returning as soon as possible from their fire()
897     *  methods, thus completing an iteration.  For example, in the case
898     *  of PN, an iteration only ends if deadlock occurs, which may
899     *  never happen.  Calling stopFire() truncates the iteration.
900     *  The thread controlling the execution (the one that calls execute())
901     *  will be suspended the next time through the iteration loop.
902     *  To resume execution, call resume().
903     *  @see Executable#stopFire
904     */
905    public void pause() {
906        _pauseRequested = true;
907
908        Nameable container = getContainer();
909
910        if (!(container instanceof CompositeActor)) {
911            throw new InternalErrorException(
912                    "Attempted to call pause() on an executing manager "
913                            + "with no associated CompositeActor model");
914        }
915
916        ((CompositeActor) container).stopFire();
917    }
918
919    /** The thread that calls this method will wait until resume() has
920     *  been called.
921     *
922     *  <p>Note: This method will block.  It should only be called
923     *  from the executing thread (the thread that is executing the
924     *  model).  Do not call this method from the same thread that
925     *  will call resume().
926     *  @param breakpointMessage The message to print when paused on a
927     *  breakpoint.
928     */
929    public void pauseOnBreakpoint(String breakpointMessage) {
930        //  FIXME: Added by celaine.  Review this.  Works with
931        //  DebugController to resume execution after a breakpoint.
932        //  FIXME: in PN this could be called multiple times.  make sure
933        //  this still works with multiple threads.
934        try {
935            if (_state == ITERATING) {
936                // This will deadlock if called from, say, the UI
937                // thread, because execute() holds the lock.
938                synchronized (this) {
939                    if (_state == ITERATING) {
940                        // Set the new state to show that execution is paused
941                        // on a breakpoint.
942                        PAUSED_ON_BREAKPOINT.setDescription(
943                                "pausing on breakpoint: " + breakpointMessage
944                                        + ".  Click Resume to continue.");
945                        _setState(PAUSED_ON_BREAKPOINT);
946
947                        _resumeNotifyWaiting = true;
948
949                        // Wait until resume() is called.
950                        while (_resumeNotifyWaiting) {
951                            wait();
952                        }
953
954                        // resume() has been called, so reset the state of the
955                        // execution.
956                        _setState(ITERATING);
957                    } else { //if (_state == ITERATING) {
958                        throw new InternalErrorException("State was changed "
959                                + "while pauseOnBreakpoint was called.");
960                    }
961                } //synchronized(this) {
962            } else { //if (_state == ITERATING) {
963                throw new InternalErrorException("pauseOnBreakpoint occurred "
964                        + "while not iterating the model.");
965            }
966        } catch (InterruptedException error) {
967            throw new InternalErrorException("Interrupted while trying to "
968                    + "wait for resume() method to be called.");
969        }
970    }
971
972    /** Preinitialize the model.  This calls the preinitialize()
973     *  method of the container, followed by the resolveTypes()
974     *  methods.  Set the Manager's state to PREINITIALIZING.  Note
975     *  that this method may be invoked without actually running the
976     *  method, but the calling code must make sure that the Manager's
977     *  state is reset to IDLE.  This method is read synchronized on
978     *  the workspace.
979     *  @exception KernelException If the model throws it.
980     *  @exception IllegalActionException If the model is already running, or
981     *   if there is no container.
982     */
983    public synchronized void preinitializeAndResolveTypes()
984            throws KernelException {
985        try {
986            _workspace.getReadAccess();
987
988            if (_state != IDLE) {
989                throw new IllegalActionException(this,
990                        "The model is not idle, it is "
991                                + _state.getDescription());
992            }
993
994            if (_container == null || _container.get() == null) {
995                throw new IllegalActionException(this, "No model to run!  "
996                        + "Try calling composite.setManager().");
997            }
998
999            _setState(PREINITIALIZING);
1000
1001            _exitAfterWrapup = false;
1002            _pauseRequested = false;
1003            _typesResolved = false;
1004            _iterationCount = 0;
1005            _executionIdentifier = null;
1006
1007            _resumeNotifyWaiting = false;
1008
1009            // NOTE: Used to call validateSettables() here with the following
1010            // note.  However, this call is very expensive and means that
1011            // second runs are no faster than first runs.
1012            // NOTE: This is needed because setExpression() on parameters
1013            // does not necessarily trigger their evaluation. Thus,
1014            // if one calls setExpression() without calling validate(),
1015            // then the new value will never be seen.  Note that the
1016            // MoML parser and Vergil's parameter editor both validate
1017            // variables.  But if a model is created some other way,
1018            // for example in a test suite using Tcl or in Java,
1019            // then the user might not think to call validate(), and
1020            // it would seem counterintuitive to have to do so.
1021            // _container.validateSettables();
1022
1023            // Clear the preinitialization analyses... Ensure that
1024            // We get current analysis.
1025            if (_nameToAnalysis != null) {
1026                _nameToAnalysis.clear();
1027                _nameToAnalysis = null;
1028            }
1029
1030            // Initialize the topology.
1031            // NOTE: Some actors require that parameters be set prior
1032            // to preinitialize().  Hence, this occurs after the call
1033            // above to validateSettables(). This makes sense, since the
1034            // preinitialize() method may depend on these parameters.
1035            // E.g., in CT higher-order components, such as
1036            // ContinuousTransferFunction, during preinitialize(),
1037            // the inside of the higher-order components is constructed
1038            // based on the parameter values.
1039            // EAL 5/31/02.
1040            _container.get().preinitialize();
1041            //_container.createReceivers(); // Undid this change temporarily since the move of createReceivers breaks HDF
1042            //_container.createSchedule(); // Undid this change temporarily since the move of createReceivers breaks HDF
1043            executeChangeRequests();
1044
1045            // Infer widths (if not already done)
1046            // NOTE: This has most likely already been done, since it is done
1047            // when receivers are created, which occurs earlier in preinitialize().
1048            if (IORelation._USE_NEW_WIDTH_INFERENCE_ALGO) {
1049                _inferWidths();
1050            }
1051
1052            resolveTypes();
1053            _typesResolved = true;
1054            _preinitializeVersion = _workspace.getVersion();
1055        } finally {
1056            // Clear the preinitialization analyses.
1057            if (_nameToAnalysis != null) {
1058                _nameToAnalysis.clear();
1059                _nameToAnalysis = null;
1060            }
1061
1062            _workspace.doneReading();
1063        }
1064    }
1065
1066    /** If the workspace version has changed since the last invocation
1067     *  of preinitializeAndResolveTypes(), then invoke it now and set
1068     *  the state of the Manager to IDLE upon completion. This can be used
1069     *  during editing a model to check types, to expand higher-order
1070     *  components, or to establish connections between Publisher and
1071     *  Subscriber actors.
1072     *  @exception KernelException If thrown while preinitializing
1073     *  and resolving types.
1074     */
1075    public void preinitializeIfNecessary() throws KernelException {
1076        try {
1077            if (_preinitializeVersion != _workspace.getVersion()) {
1078                preinitializeAndResolveTypes();
1079            }
1080        } finally {
1081            _setState(IDLE);
1082        }
1083    }
1084
1085    /** Invoke preinitialize() and wrapup().
1086     *
1087     *  <p>If the model has not been preinitialized since the last
1088     *  change to its structure, that must be done now for the result
1089     *  to be accurate. This is because higher-order components
1090     *  and Publisher and Subscriber connections may not have yet
1091     *   been created.</p>
1092     *
1093     *  @param actor The actor upon which to call preinitialize() on
1094     *  its toplevel.
1095     *  @exception KernelException If thrown when a Manager is added to
1096     *  the top level or if preinitialize() fails.
1097     */
1098    public static void preinitializeThenWrapup(Actor actor)
1099            throws KernelException {
1100        // If preinitialize() has not yet been called, then we don't
1101        // yet know what Subscribers are using connected to the
1102        // Publisher.
1103        Manager manager = actor.getManager();
1104        if (manager == null) {
1105            CompositeActor toplevel = (CompositeActor) ((NamedObj) actor)
1106                    .toplevel();
1107            manager = new Manager(toplevel.workspace(), "PubManager");
1108            toplevel.setManager(manager);
1109        }
1110        try {
1111            // Create connections between Publishers and Subscribers.
1112            manager.preinitializeIfNecessary();
1113        } finally {
1114            try {
1115                // FIXME: should this be synchronized on this?
1116                if (manager.getState() != IDLE
1117                        && manager.getState() != WRAPPING_UP) {
1118                    manager.wrapup();
1119                }
1120            } catch (Throwable throwable) {
1121                // The Exit actor causes Manager.wrapup() to throw this.
1122                if (!manager.isExitingAfterWrapup()) {
1123                    throw new IllegalActionException(actor, throwable,
1124                            "Manager.wrapup() failed.");
1125                }
1126            }
1127        }
1128    }
1129
1130    /** Remove a listener from the list of listeners that are notified
1131     *  of execution events.  If the specified listener is not on the list,
1132     *  do nothing.
1133     *  @param listener The listener to remove.
1134     *  @see #addExecutionListener(ExecutionListener)
1135     */
1136    public void removeExecutionListener(ExecutionListener listener) {
1137        if (listener == null || _executionListeners == null) {
1138            return;
1139        }
1140        List<WeakReference<ExecutionListener>> toRemove = new LinkedList<WeakReference<ExecutionListener>>();
1141        for (WeakReference<ExecutionListener> reference : _executionListeners) {
1142            if (reference.get() == listener) {
1143                toRemove.add(reference);
1144            }
1145        }
1146        _executionListeners.removeAll(toRemove);
1147    }
1148
1149    /** Queue an initialization request.
1150     *  The specified actor will be initialized at an appropriate time,
1151     *  in the iterate() method, by calling its preinitialize()
1152     *  and initialize() methods.  This method should be called when an
1153     *  actor is added to a model through a mutation in order to properly
1154     *  initialize the actor.
1155     *  @param actor The actor to initialize.
1156     */
1157    public void requestInitialization(Actor actor) {
1158        // Only initialize once.
1159        if (_actorsToInitialize.contains(actor)) {
1160            return;
1161        }
1162        // Only initialize containers.  This avoids initializing an
1163        // actor twice when it is added as part of a container that is
1164        // being added.
1165        {
1166            NamedObj container = actor.getContainer();
1167
1168            while (container != null) {
1169                if (_actorsToInitialize.contains(container)) {
1170                    return;
1171                }
1172
1173                container = container.getContainer();
1174            }
1175        }
1176
1177        // OK, then we need to initialize this actor.  However, we
1178        // don't need to initialize any actors contained by this
1179        // actor.
1180        if (actor instanceof CompositeEntity) {
1181            List<Actor> list = new LinkedList<Actor>(_actorsToInitialize);
1182            for (Actor otherActor : list) {
1183                if (((CompositeEntity) actor)
1184                        .deepContains((NamedObj) otherActor)) {
1185                    _actorsToInitialize.remove(otherActor);
1186                }
1187            }
1188        }
1189
1190        // Lastly, add this actor to the actors to initialize.
1191        _actorsToInitialize.add(actor);
1192    }
1193
1194    /** Check types on all the connections and resolve undeclared types.
1195     *  If the container is not an instance of TypedCompositeActor,
1196     *  do nothing.
1197     *  Set the Manager's state to RESOLVING_TYPES.
1198     *  This method is write-synchronized on the workspace.
1199     *  @exception TypeConflictException If a type conflict is detected.
1200     */
1201    public void resolveTypes() throws TypeConflictException {
1202        if (!(_container.get() instanceof TypedCompositeActor)) {
1203            return;
1204        }
1205
1206        try {
1207            _workspace.getReadAccess();
1208            _setState(RESOLVING_TYPES);
1209
1210            TypedCompositeActor
1211                    .resolveTypes((TypedCompositeActor) _container.get());
1212        } finally {
1213            _workspace.doneReading();
1214        }
1215    }
1216
1217    /** If the model is paused, resume execution.  This method must
1218     *  be called from a different thread than that controlling the
1219     *  execution, since the thread controlling the execution is
1220     *  suspended.
1221     */
1222    public void resume() {
1223        // Avoid the case when the director is not actually paused causing the
1224        // swing thread to block.
1225        if (_state == PAUSED) {
1226            synchronized (this) {
1227                if (_state == PAUSED) {
1228                    _pauseRequested = false;
1229                    notifyAll();
1230                } else {
1231                    throw new InternalErrorException("resume() should be the "
1232                            + "only method that goes from "
1233                            + "PAUSED to not paused");
1234                }
1235            }
1236        } else if (_state == PAUSED_ON_BREAKPOINT) {
1237            synchronized (this) {
1238                if (_state == PAUSED_ON_BREAKPOINT) {
1239                    // Notify all threads waiting to know whether resume() has
1240                    // been called (threads that called waitForResume()).
1241                    //
1242                    // Works with DebugController to resume execution after a
1243                    // breakpoint.
1244                    if (_resumeNotifyWaiting) {
1245                        _resumeNotifyWaiting = false;
1246                        notifyAll();
1247                    }
1248                }
1249            }
1250        }
1251    }
1252
1253    /** Execute the model, catching all exceptions. Use this method to
1254     *  execute the model within the calling thread, but to not throw
1255     *  exceptions.  Instead, the exception is handled using the
1256     *  notifyListenersOfException() method.  Except for its
1257     *  exception handling, this method has exactly the same behavior
1258     *  as execute().
1259     */
1260    @Override
1261    public void run() {
1262        try {
1263            execute();
1264        } catch (Throwable throwable) {
1265            // If running tried to load in some native code using JNI
1266            // then we may get an Error here
1267            notifyListenersOfThrowable(throwable);
1268
1269            // Used to call _disposeOfThreads() here, but now exeucte()
1270            // calls it in its finally block.
1271            // } finally {
1272            //  _disposeOfThreads();
1273
1274        }
1275    }
1276
1277    /** Set the execution identifier object. Any throwables that occur
1278     * in current execution cycle are associated with this
1279     * identifier. The execution identifier is reset in
1280     * preinitialize().
1281     *
1282     * @param executionIdentifier The execution identifier object
1283     * @see #getExecutionIdentifier(Throwable)
1284     */
1285    public void setExecutionIdentifier(Object executionIdentifier) {
1286        _executionIdentifier = executionIdentifier;
1287    }
1288
1289    /** Set the status message, such as the amount of time consumed.
1290     *  This method is called to update the status bar, so the
1291     *  output should be short.
1292     *  @param message The message to be displayed.
1293     *  @see #getStatusMessage()
1294     */
1295    public void setStatusMessage(String message) {
1296        _statusMessage = message;
1297    }
1298
1299    /** Indicate that the specified thread is waiting and can be
1300     *  interrupted in the event that a change request is made.
1301     *  @param thread The thread that is waiting, or null to indicate
1302     *   that no thread is waiting.
1303     *  @see #getWaitingThread()
1304     */
1305    public void setWaitingThread(Thread thread) {
1306        _waitingThread = thread;
1307    }
1308
1309    /** Return a short description of the throwable.
1310     *  @param throwable The throwable
1311     *  @return If the throwable is an Exception, return "Exception",
1312     *  if it is an Error, return "Error", if it is a Throwable, return
1313     *  "Throwable".
1314     *  @deprecated Instead ptolemy.util.MessageHandler.shortDescription()
1315     */
1316    @Deprecated
1317    public static String shortDescription(Throwable throwable) {
1318        return MessageHandler.shortDescription(throwable);
1319    }
1320
1321    /** Start an execution in another thread and return.  Any exceptions
1322     *  that occur during the execution of the model are handled by
1323     *  the notifyListenersOfException() method.
1324     *  @exception IllegalActionException If the model is already running,
1325     *  e.g. the state is not IDLE.
1326     */
1327    public void startRun() throws IllegalActionException {
1328        if (_state != IDLE) {
1329            throw new IllegalActionException(this,
1330                    "Model is " + _state.getDescription());
1331        }
1332
1333        // Set this within the calling thread to avoid race conditions
1334        // where finish() might be called before the spawned thread
1335        // actually starts up.
1336        _finishRequested = false;
1337        _thread = new PtolemyRunThread(this, _container.get().getName());
1338        // Priority set to the minimum to get responsive UI during execution.
1339        _thread.setPriority(Thread.MIN_PRIORITY);
1340        _thread.start();
1341    }
1342
1343    /** If the state is not IDLE, set a flag to request that
1344     *  execution stop and exit in a completely deterministic fashion
1345     *  at the end of the next toplevel iteration.  This method may
1346     *  be called from within an actor to stop the execution of the model.
1347     *  This will result in stop() being called on the top level
1348     *  CompositeActor, although not necessarily immediately.
1349     *  This is basically an alias for finish().
1350     *
1351     *  <p> Note that in general, it is best to get that director
1352     *  and call finish() and stopFire() on the director than
1353     *  it is to call Manager.stop().</p>
1354     *
1355     *  <p> The reason that it is better to call Director.finish()
1356     *  is that if Manager.stop() is called inside a RunCompositeActor
1357     *  then only the inside execution will be stopped, not
1358     *  the outside one.  It is also not correct to call stop()
1359     *  on the directory because Director.stop() requests immediate
1360     *  stopping.  To give determinate stopping, call Director.finish()
1361     *  so that the current iteration is completed.</p>
1362     *
1363     *  <p>In multithreaded domains, Director.stopFire is called
1364     *  to request that all actors conclude ongoing firings.</p>
1365     */
1366    public void stop() {
1367        finish();
1368    }
1369
1370    /** Terminate the currently executing model with extreme prejudice.
1371     *  This leaves the state of the manager in CORRUPTED, which means
1372     *  that the model cannot be executed again.  A new model must be
1373     *  created, with a new manager, to execute again.
1374     *  This method is not intended to be used as a normal route of
1375     *  stopping execution. To normally stop execution, call the finish()
1376     *  method instead. This method should be called only
1377     *  when execution fails to terminate by normal means due to certain
1378     *  kinds of programming errors (infinite loops, threading errors, etc.).
1379     *  <p>
1380     *  If the model execution was started in a separate thread (using
1381     *  startRun()), then that thread is killed unceremoniously (using
1382     *  a method that is now deprecated in Java, for obvious reasons).
1383     *  This method also calls terminate on the toplevel composite actor.
1384     *  <p>
1385     *  This method is not synchronized because we want it to
1386     *  execute as soon as possible.
1387     *  @deprecated
1388     */
1389    @Deprecated
1390    public void terminate() {
1391        // If the execution was started in a separate thread, kill that thread.
1392        // NOTE: This uses the stop() method, which is now deprecated in Java.
1393        // Indeed it should be, since it terminates a thread
1394        // nondeterministically, and can leave any objects that the thread
1395        // operating on in an inconsistent state.
1396        if (_thread != null) {
1397            // NOTE:  stop() in java.lang.Thread has been deprecated
1398            _thread.stop();
1399
1400            try {
1401                _thread.join();
1402            } catch (InterruptedException e) {
1403                // This will usually get thrown, since we are
1404                // forcibly terminating
1405                // the thread.   We just ignore it.
1406            }
1407
1408            _disposeOfThreads();
1409        }
1410
1411        // Terminate the entire hierarchy as best we can.
1412        if (_container != null && _container.get() != null) {
1413            _container.get().terminate();
1414        }
1415        _setState(CORRUPTED);
1416    }
1417
1418    /** Return a string with the elapsed time since startTime, and
1419     *  the amount of memory used.
1420     *  @param startTime The start time in milliseconds.  For example,
1421     *  the value returned by <code>(new Date()).getTime()</code>.
1422     *  @return A string with the elapsed time since startTime, and
1423     *  the amount of memory used.
1424     */
1425    public static String timeAndMemory(long startTime) {
1426        Runtime runtime = Runtime.getRuntime();
1427        long totalMemory = runtime.totalMemory() / 1024;
1428        long freeMemory = runtime.freeMemory() / 1024;
1429        return timeAndMemory(startTime, totalMemory, freeMemory);
1430    }
1431
1432    /** Return a string with the elapsed time since startTime, and
1433     *  the amount of memory used.
1434     *  This method takes a java.lang.Long object so that ptjacl
1435     *  can properly pass a long number:
1436     *  <pre>
1437     *  set currentTime  [java::call -noconvert java.lang.System currentTimeMillis]
1438     *  java::call ptolemy.actor.Manager timeAndMemoryLong $x
1439     *  </pre>
1440     *  @param startTime The start time in milliseconds.  For example,
1441     *  the value returned by <code>(new Date()).getTime()</code>.
1442     *  @return A string with the elapsed time since startTime, and
1443     *  the amount of memory used.
1444     */
1445    public static String timeAndMemoryLong(Long startTime) {
1446
1447        return timeAndMemory(startTime.longValue());
1448    }
1449
1450    /** Return a string with the elapsed time since startTime,
1451     *  and the amount of memory used.
1452     *  the value returned by <code>(new Date()).getTime()</code>.
1453     *  @param startTime The start time in milliseconds.  For example,
1454     *  the value returned by <code>(new Date()).getTime()</code>.
1455     *  @param totalMemory The total amount of memory used in kilobytes.
1456     *  @param freeMemory The total amount of memory free in kilobytes.
1457     *  @return A string with the elapsed time since startTime, and
1458     *  the amount of memory used.
1459     */
1460    public static String timeAndMemory(long startTime, long totalMemory,
1461            long freeMemory) {
1462        return System.currentTimeMillis() - startTime + " ms. Memory: "
1463                + totalMemory + "K Free: " + freeMemory + "K ("
1464                + Math.round((double) freeMemory / (double) totalMemory * 100.0)
1465                + "%)";
1466    }
1467
1468    /** If there is an active thread created by startRun(), then wait
1469     *  for it to complete and return. The wait is accomplished by
1470     *  calling the join() method on the thread.  If there is no
1471     *  active thread, then wait until the manager state is idle
1472     *  by calling wait().
1473     *  @see #startRun()
1474     */
1475    public void waitForCompletion() {
1476        if (_thread != null) {
1477            try {
1478                _thread.join();
1479            } catch (InterruptedException ex) {
1480                // Ignore this and return.
1481            }
1482        } else {
1483            // NOTE: Previously, execute() was a synchronized method.
1484            // Result: This would almost certainly deadlock if called
1485            // from a thread apart from the executing thread because execute()
1486            // is synchronized, so the running thread holds the lock!
1487            // NOTE: Synchronizing here is not correct.
1488            // See Workspace.wait(Object)
1489            // synchronized (this) {
1490            while (getState() != IDLE && getState() != CORRUPTED) {
1491                try {
1492                    workspace().wait(this);
1493                } catch (InterruptedException ex) {
1494                    break;
1495                }
1496            }
1497            _disposeOfThreads();
1498            // }
1499        }
1500    }
1501
1502    /** Wrap up the model by invoking the wrapup method of the toplevel
1503     *  composite actor.
1504     *  At the end of this model, the state is set to idle.
1505     *  @exception KernelException If the model throws it.
1506     *  @exception IllegalActionException If the model is idle or already
1507     *   wrapping up, or if there is no container.
1508     */
1509    public void wrapup() throws KernelException, IllegalActionException {
1510        try {
1511            // NOTE: This method used to be synchronized, but we cannot
1512            // hold the lock on the director during wrapup because it
1513            // will cause deadlock. Instead, we use a small barrier
1514            // here to check and set the state.
1515            synchronized (this) {
1516                if (_state == IDLE || _state == WRAPPING_UP) {
1517                    throw new IllegalActionException(this,
1518                            "Cannot wrap up. The current state is: "
1519                                    + _state.getDescription());
1520                }
1521
1522                if (_container == null || _container.get() == null) {
1523                    throw new IllegalActionException(this, "No model to run!");
1524                }
1525
1526                _setState(WRAPPING_UP);
1527            }
1528
1529            // Wrap up the topology
1530            _container.get().wrapup();
1531
1532            // Process all change requests. If the model reaches this wrap up
1533            // state due to the occurrence of an exception during execution,
1534            // some change requests may be pending. If these requests
1535            // are not processed, they will be left to the next execution.
1536            // Also, wrapping up execution may cause change requests to be queued.
1537            // Also, at the same time, re-enable immediate execution of
1538            // change requests.
1539            setDeferringChangeRequests(false);
1540
1541            // NOTE: This used to increment the workspace
1542            // version, which would require that everything
1543            // be re-done on subsequent runs. EAL 9/16/06
1544            // _workspace.incrVersion();
1545
1546            if (_exitAfterWrapup) {
1547                // If the ptolemy.ptII.exitAfterWrapup property is set,
1548                // then we don't actually exit.
1549                StringUtilities.exit(0);
1550            }
1551        } finally {
1552            // We must set the state to IDLE here even if
1553            // we entered wrapup() and the state was IDLE or WRAPPING_UP.
1554            // If we don't set the state to IDLE, then if an accessor
1555            // has an error in wrapup, the model will always be
1556            // stuck in WRAPPING_UP.
1557            _setState(IDLE);
1558        }
1559    }
1560
1561    ///////////////////////////////////////////////////////////////////
1562    ////                         public variables                  ////
1563
1564    /** The minimum amount of time that may elapse during certain
1565     *  operations before statistics are generated.  The Manager and
1566     *  other classes in Ptolemy will print out statistics if the
1567     *  amount of time (in milliseconds) named by this variable
1568     *  elapses during certain steps such as preinitialize().
1569     *  The initial default value is 10000, meaning that certain
1570     *  operations can take up to 10 seconds before statistics
1571     *  are printed.
1572     *  @see ptolemy.kernel.CompositeEntity#statistics(String)
1573     */
1574    public static int minimumStatisticsTime = 10000;
1575
1576    /** The amount of time to allow for the model to terminate
1577     *  gracefully before shutting it down when the JVM is shut down
1578     *  due to control-C, user logging out, etc.
1579     */
1580    public static long SHUTDOWN_TIME = 30000L;
1581
1582    ///////////////////////////////////////////////////////////////////
1583    ////                         protected methods                 ////
1584
1585    /** Make this manager the manager of the specified composite
1586     *  actor. If the composite actor is not null, then the manager is
1587     *  removed from the directory of the workspace.  If the composite
1588     *  actor is null, then the manager is <b>not</b> returned to the
1589     *  directory of the workspace, which may result in it being
1590     *  garbage collected.  This method should not be called directly.
1591     *  Instead, call setManager in the CompositeActor class (or a
1592     *  derived class).
1593     *  @param compositeActor The composite actor that this manager will
1594     *  manage.
1595     */
1596    protected void _makeManagerOf(CompositeActor compositeActor) {
1597        if (compositeActor != null) {
1598            _workspace.remove(this);
1599        } else {
1600            _disposeOfThreads();
1601        }
1602
1603        _container = new WeakReference<CompositeActor>(compositeActor);
1604    }
1605
1606    /** Notify listeners that execution has completed.
1607     *  @deprecated Incomplete name, use
1608     *  {@link #_notifyListenersOfSuccessfulCompletion()}
1609     */
1610    @Deprecated
1611    protected synchronized void _notifyListenersOfCompletion() {
1612        _notifyListenersOfSuccessfulCompletion();
1613    }
1614
1615    /** Notify listeners that execution has completed successfully.
1616     */
1617    protected synchronized void _notifyListenersOfSuccessfulCompletion() {
1618        if (_debugging) {
1619            _debug("-- Manager completed execution with " + _iterationCount
1620                    + " iterations");
1621        }
1622
1623        if (_executionListeners != null) {
1624            ListIterator<WeakReference<ExecutionListener>> listeners = _executionListeners
1625                    .listIterator();
1626
1627            while (listeners.hasNext()) {
1628                WeakReference<ExecutionListener> reference = listeners.next();
1629                ExecutionListener listener = reference.get();
1630
1631                if (listener != null) {
1632                    listener.executionFinished(this);
1633                } else {
1634                    listeners.remove();
1635                }
1636            }
1637        }
1638    }
1639
1640    /** Propagate the state change event to all the execution listeners.
1641     */
1642    protected void _notifyListenersOfStateChange() {
1643        if (_debugging) {
1644            _debug("-- Manager state is now: " + _state.getDescription());
1645        }
1646
1647        if (_executionListeners != null) {
1648            ListIterator<WeakReference<ExecutionListener>> listeners = _executionListeners
1649                    .listIterator();
1650
1651            while (listeners.hasNext()) {
1652                WeakReference<ExecutionListener> reference = listeners.next();
1653                ExecutionListener listener = reference.get();
1654
1655                if (listener != null) {
1656                    listener.managerStateChanged(this);
1657                } else {
1658                    listeners.remove();
1659                }
1660            }
1661        }
1662    }
1663
1664    /** Register a shutdown hook to gracefully stop the execution of a model
1665     *  if the JVM is shut down (by control-C, the user logging out, etc.).
1666     */
1667    protected void _registerShutdownHook() {
1668        _shutdownThread = new Thread() {
1669            @Override
1670            public void run() {
1671                if (_state != IDLE) {
1672                    System.out.println(
1673                            "# Manager._registerShutdownHook(): State is "
1674                                    + _state
1675                                    + ", which is not IDLE.  Waiting for model to stop.");
1676                }
1677                finish();
1678                if (_thread != null && _thread.isAlive()) {
1679                    try {
1680                        // This seems dangerous. Could prevent the process
1681                        // from dying. We use a timeout here of 30 seconds.
1682                        _thread.join(SHUTDOWN_TIME);
1683                    } catch (InterruptedException e) {
1684                        // Failed to stop the thread.
1685                        e.printStackTrace();
1686                    }
1687                }
1688            }
1689        };
1690        try {
1691            Runtime.getRuntime().addShutdownHook(_shutdownThread);
1692        } catch (java.security.AccessControlException ex) {
1693            // This exception gets triggered by
1694            // http://ptolemy.eecs.berkeley.edu/ptolemyII/ptII10.0/ptII10.0.devel/ptolemy/vergil/Vergil.htm
1695            System.out.println("Warning: failed to add a shutdown hook."
1696                    + "(Running a model in an applet always causes this)");
1697        }
1698    }
1699
1700    /** Set the state of execution and notify listeners if the state
1701     *  actually changes.
1702     *  @param newState The new state.
1703     */
1704    protected synchronized void _setState(State newState) {
1705        if (_state != newState) {
1706            _state = newState;
1707            _notifyListenersOfStateChange();
1708            notifyAll();
1709        }
1710    }
1711
1712    ///////////////////////////////////////////////////////////////////
1713    ////                         private methods                   ////
1714
1715    /** Dispose of the thread by removing it from the workspace and
1716     *  setting it to null.  Also, remove the shutdown thread.
1717     */
1718    private void _disposeOfThreads() {
1719        // FIXME: Should we acquire the read lock on the Workspace and
1720        // then have a version of doneReading that cleans up?
1721        // FIXME: Should we check to see if the Manager is idle here?
1722        _thread = null;
1723
1724        // FIXME: Should this be synchronized?
1725        if (_shutdownThread != null) {
1726            Runtime.getRuntime().removeShutdownHook(_shutdownThread);
1727            _shutdownThread = null;
1728        }
1729    }
1730
1731    /**
1732     *  Infer the width of the relations for which no width has been
1733     *  specified yet.
1734     *  This method will set the state to INFERING_WIDTHS and change
1735     *  it back afterwards.
1736     *  @exception IllegalActionException If the widths of the relations at
1737     *          port are not consistent or if the width cannot be inferred
1738     *          for a relation.
1739     */
1740    private void _inferWidths() throws IllegalActionException {
1741        if (_container == null || _container.get() == null) {
1742            throw new NullPointerException("The container of the manager "
1743                    + getFullName() + " was null. "
1744                    + "Try calling composite.setManager().");
1745        }
1746        if (_container.get().needsWidthInference()) {
1747            State previousState = _state;
1748            try {
1749                _setState(INFERING_WIDTHS);
1750                _container.get().inferWidths();
1751            } finally {
1752                _setState(previousState);
1753            }
1754        }
1755    }
1756
1757    ///////////////////////////////////////////////////////////////////
1758    ////                         private variables                 ////
1759    // A list of actors with pending initialization.
1760    private List<Actor> _actorsToInitialize = new LinkedList<Actor>();
1761
1762    /** The real time at which the model begins executing. */
1763    private long _afterInitTime = 0;
1764
1765    // The top-level CompositeActor that contains this Manager
1766    private WeakReference<CompositeActor> _container = null;
1767
1768    /** An execution identifier.  See
1769     * #getExecutionIdentifier(Throwable throwable)
1770     */
1771    private Object _executionIdentifier;
1772
1773    // Listeners for execution events. This list has weak references.
1774    private List<WeakReference<ExecutionListener>> _executionListeners;
1775
1776    // Set to true if we should exit after wrapup().
1777    private boolean _exitAfterWrapup = false;
1778
1779    // Flag indicating that finish() has been called.
1780    private boolean _finishRequested = false;
1781
1782    // Count the number of iterations completed.
1783    private int _iterationCount;
1784
1785    // The map that keeps track of analyses.
1786    private HashMap<String, Object> _nameToAnalysis;
1787
1788    // Flag indicating that pause() has been called.
1789    private boolean _pauseRequested = false;
1790
1791    // Version at which preinitialize last successfully executed.
1792    private long _preinitializeVersion = -1;
1793
1794    // Whether time and memory usage are printed at the end of model execution.
1795    private boolean _printTimeAndMemory = true;
1796
1797    // Flag for waiting on resume();
1798    private boolean _resumeNotifyWaiting = false;
1799
1800    // The thread that is passed to Runtime.addShutdowHook().
1801    private Thread _shutdownThread = null;
1802
1803    // The state of the execution.
1804    private volatile State _state = IDLE;
1805
1806    // A short status message.
1807    private String _statusMessage = "";
1808
1809    // If startRun() is used, then this points to the thread that was
1810    // created.
1811    private PtolemyThread _thread;
1812
1813    // A map that associates throwables with execution identifiers. The map is
1814    // a WeakHashMap so that execution identifiers can be garbage collected.
1815    private Map<Throwable, Object> _throwableToExecutionIdentifier = new WeakHashMap<Throwable, Object>();
1816
1817    // An indicator of whether type resolution needs to be done.
1818    private boolean _typesResolved = false;
1819
1820    /** A thread that is waiting, e.g. synchronized to real time, or null if there is none. */
1821    private Thread _waitingThread;
1822
1823    ///////////////////////////////////////////////////////////////////
1824    ////                         inner class                       ////
1825
1826    /** Instances of this class represent phases of execution, or the
1827     *  state of the manager.
1828     */
1829    public static class State {
1830        // Constructor is private because only Manager instantiates this class.
1831        private State(String description) {
1832            _description = description;
1833        }
1834
1835        /** Get a description of the state.
1836         *  @return A description of the state.
1837         */
1838        public String getDescription() {
1839            return _description;
1840        }
1841
1842        //  An utter hack...
1843        private void setDescription(String description) {
1844            _description = description;
1845        }
1846
1847        /** Print out the current state.
1848         */
1849        @Override
1850        public String toString() {
1851            return "The model is " + getDescription();
1852        }
1853
1854        private String _description;
1855    }
1856
1857    /** Notify listeners of an exception.
1858     */
1859    private class ErrorReportingThread extends Thread {
1860        // This thread is a named inner class so that we can find it
1861        // by name when looking for memory leaks.
1862
1863        /** Construct an thread that reports errors.
1864         *  @param name The name of the thread.
1865         */
1866        public ErrorReportingThread(String name, Throwable throwable) {
1867            super(name);
1868            _throwable = throwable;
1869        }
1870
1871        /** Run the thread.
1872         */
1873        @Override
1874        public void run() {
1875            synchronized (Manager.this) {
1876                // We use Throwables instead of Exceptions so that
1877                // we can catch Errors like
1878                // java.lang.UnsatisfiedLink.
1879                String errorMessage = MessageHandler.shortDescription(
1880                        _throwable) + " occurred: " + _throwable.getClass()
1881                        + "(" + _throwable.getMessage() + ")";
1882                _debug("-- Manager notifying listeners of exception: "
1883                        + _throwable);
1884
1885                if (_executionListeners == null) {
1886                    System.err.println(
1887                            "No executionListeners? Error message was: "
1888                                    + errorMessage);
1889                    _throwable.printStackTrace();
1890                } else {
1891
1892                    // If the execution id is not null, map the
1893                    // throwable to the id.
1894                    if (_executionIdentifier != null) {
1895                        _throwableToExecutionIdentifier.put(_throwable,
1896                                _executionIdentifier);
1897                    }
1898
1899                    ListIterator<WeakReference<ExecutionListener>> listeners = _executionListeners
1900                            .listIterator();
1901
1902                    while (listeners.hasNext()) {
1903                        WeakReference<ExecutionListener> reference = listeners
1904                                .next();
1905                        ExecutionListener listener = reference.get();
1906
1907                        if (listener != null) {
1908                            listener.executionError(Manager.this, _throwable);
1909                        } else {
1910                            listeners.remove();
1911                        }
1912                    }
1913                }
1914            }
1915        }
1916
1917        /** The throwable that is to be passed to the listeners. */
1918        private Throwable _throwable;
1919    }
1920
1921    private class PtolemyRunThread extends PtolemyThread {
1922        // This thread is a named inner class so that we can find it
1923        // by name when looking for memory leaks.
1924
1925        public PtolemyRunThread(Runnable target, String name) {
1926            super(target, name);
1927        }
1928
1929        @Override
1930        public void run() {
1931            // The run() method will set _thread to null
1932            // upon completion of the run.
1933            Manager.this.run();
1934        }
1935    }
1936
1937    private class UnpauserThread extends Thread {
1938        // This thread is a named inner class so that we can find it
1939        // by name when looking for memory leaks.
1940
1941        @Override
1942        public void run() {
1943            // NOTE: The execute() method used to be synchronized,
1944            // which would cause deadlock with this.
1945            // During wrapup, if the Manager is locked
1946            // and the ProcessDirector is waiting for threads
1947            // to end, then these unpausers
1948            // can't run, and the processes can't end.
1949            synchronized (Manager.this) {
1950                Manager.this.notifyAll();
1951            }
1952        }
1953    }
1954}