001/* An actor that stops a model executing when it receives a true token. 002 003 Copyright (c) 1997-2014 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.lib; 029 030import ptolemy.data.BooleanToken; 031import ptolemy.data.expr.SingletonParameter; 032import ptolemy.data.type.BaseType; 033import ptolemy.kernel.CompositeEntity; 034import ptolemy.kernel.util.IllegalActionException; 035import ptolemy.kernel.util.NameDuplicationException; 036import ptolemy.kernel.util.Settable; 037 038/////////////////////////////////////////////////////////////////// 039//// Stop 040 041/** 042 043 <p>An actor that stops execution of a model when it receives a true 044 token on any input channel. This is accomplished by calling 045 finish() on the director, which requests that the current iteration 046 be completed and then the execution be halted. This actor will 047 also call stopFire() which requests that any actors that are 048 firing concurrently in separate threads conclude their firings. 049 This is necessary to support threaded domains like PN. If the input 050 is not connected to anything, then this actor requests a stop 051 whenever it fires. 052 053 </p><p> 054 When exactly this stops the execution depends on the domain. For 055 example, in DE, if an event with time stamp <i>T</i> and value 056 <i>true</i> arrives at this actor, then the current iteration will 057 be concluded, and then the model will halt. Concluding the current 058 iteration means processing all events in the event queue with time 059 stamp <i>T</i>. Thus, it is possible for actors to be invoked after 060 this one is invoked with a <i>true</i> input. 061 062 </p><p> 063 In SDF, if this actor receives <i>true</i>, then the current 064 iteration is concluded and then execution is stopped. Similarly in 065 SR. 066 067 </p><p> 068 In PN, where each actor has its own thread, there is no 069 well-defined notion of an iteration. The finish() method of the 070 manager calls stopFire() on all actors, which for threaded actors 071 results in halting them upon their next attempt to read an input or 072 write an output. When all actor threads have stopped, the iteration 073 concludes and the model halts. <b>NOTE</b>: <i>This is not the best 074 way to stop a PN model!</i> This mechanism is nondeterministic in 075 the sense that there is no way to control exactly what data is 076 produced or consumed on the connections before the model stops. To 077 stop a PN model, it is better to design the model so that all 078 actors are starved of data when the model is to stop. The director 079 will detect this starvation, and halt the model. Nonetheless, if 080 the nondeterminism is acceptable, this actor can be used.</p> 081 082 @author Edward A. Lee 083 @version $Id$ 084 @since Ptolemy II 2.1 085 @Pt.ProposedRating Green (eal) 086 @Pt.AcceptedRating Green (neuendor) 087 */ 088public class Stop extends Sink { 089 /** Construct an actor in the specified container with the specified 090 * name. 091 * @param container The container. 092 * @param name The name of this actor within the container. 093 * @exception IllegalActionException If the actor cannot be contained 094 * by the proposed container. 095 * @exception NameDuplicationException If the name coincides with 096 * an actor already in the container. 097 */ 098 public Stop(CompositeEntity container, String name) 099 throws IllegalActionException, NameDuplicationException { 100 super(container, name); 101 102 input.setTypeEquals(BaseType.BOOLEAN); 103 104 // Icon is a stop sign. 105 _attachText("_iconDescription", "<svg>\n" 106 + "<polygon points=\"-8,-19 8,-19 19,-8 19,8 8,19 " 107 + "-8,19 -19,8 -19,-8\" " + "style=\"fill:red\"/>\n" 108 + "<text x=\"-15\" y=\"4\"" 109 + "style=\"font-size:11; fill:white; font-family:SansSerif\">" 110 + "STOP</text>\n" + "</svg>\n"); 111 112 // Hide the name because the name is in the icon. 113 _hideName = new SingletonParameter(this, "_hideName"); 114 _hideName.setToken(BooleanToken.TRUE); 115 _hideName.setVisibility(Settable.EXPERT); 116 } 117 118 /////////////////////////////////////////////////////////////////// 119 //// ports and parameters //// 120 121 /** The parameter that hides the name of the actor. The default 122 * value is true. 123 */ 124 public SingletonParameter _hideName; 125 126 /////////////////////////////////////////////////////////////////// 127 //// public methods //// 128 129 /** Read one token from each input channel that has a token, 130 * and if any token is true, call finish() on the manager. 131 * If nothing at all is connected to the input port, then 132 * call finish() unconditionally. 133 * @exception IllegalActionException If there is no director or 134 * if there is no manager, or if the container is not a 135 * CompositeActor. 136 * @return False if this actor is trying to stop execution if any 137 * token is true or if the input is not connected. If this actor 138 * is not trying to stop execution, then return the value 139 * returned by super.postfire(). 140 */ 141 @Override 142 public boolean postfire() throws IllegalActionException { 143 boolean result = false; 144 145 if (!input.isOutsideConnected()) { 146 result = true; 147 } 148 149 // NOTE: We need to consume data on all channels that have data. 150 // If we don't then DE will go into an infinite loop. 151 for (int i = 0; i < input.getWidth(); i++) { 152 if (input.hasToken(i)) { 153 if (((BooleanToken) input.get(i)).booleanValue()) { 154 result = true; 155 } 156 } 157 } 158 159 if (result) { 160 // NOTE: This used to call stop() on the manager, but that's 161 // not the right thing to do. In particular, this could be 162 // used inside a RunCompositeActor, and it should only 163 // stop the inside execution, not the outside one. 164 // It's also not correct to call stop() on the director, 165 // because stop() requests immediate stopping. To give 166 // determinate stopping, this actor needs to complete 167 // the current iteration. 168 getDirector().finish(); 169 170 // To support multithreaded domains, also have to call 171 // stopFire() to request that all actors conclude ongoing firings. 172 getDirector().stopFire(); 173 174 // Nameable container = getContainer(); 175 176 // if (container instanceof CompositeActor) { 177 // Manager manager = ((CompositeActor) container).getManager(); 178 179 // if (manager != null) { 180 // manager.finish(); 181 // } else { 182 // throw new IllegalActionException(this, 183 // "Cannot stop without a Manager."); 184 // } 185 // } else { 186 // throw new IllegalActionException(this, 187 // "Cannot stop without a container that is a " 188 // + "CompositeActor."); 189 // } 190 191 } 192 193 // If this actor is not trying to stop execution, then return 194 // the value returned by super.postfire(). 195 boolean superResults = super.postfire(); 196 if (!result) { 197 return superResults; 198 } 199 200 return !result; 201 } 202}