001/* A type polymorphic boolean select used in the DDF domain. 002 003 Copyright (c) 1998-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.domains.ddf.lib; 029 030import ptolemy.actor.TypedAtomicActor; 031import ptolemy.actor.TypedIOPort; 032import ptolemy.data.BooleanToken; 033import ptolemy.data.IntToken; 034import ptolemy.data.expr.Parameter; 035import ptolemy.data.type.BaseType; 036import ptolemy.kernel.CompositeEntity; 037import ptolemy.kernel.util.IllegalActionException; 038import ptolemy.kernel.util.NameDuplicationException; 039import ptolemy.kernel.util.Settable; 040import ptolemy.kernel.util.StringAttribute; 041import ptolemy.kernel.util.Workspace; 042 043/** 044 A type polymorphic select with boolean valued control for use in 045 the DDF domain. In the first iteration, an input token at the 046 <i>control</i> port is read and its value is noted. In the second 047 iteration, if the <i>control</i> input read from the previous 048 iteration is true, then an input token at the <i>trueInput</i> port 049 is read and sent to the output. Likewise with a false <i>control</i> 050 input and the <i>falseInput</i> port. It alternates between these 051 two kinds of iterations until stopped. The <i>control</i> port must 052 receive Boolean Tokens. The <i>trueInput</i> and <i>falseInput</i> 053 ports may receive Tokens of any type. Because tokens are immutable, 054 the same Token is sent to the output, rather than a copy. 055 <p> 056 Note this actor sends an output token every two iterations. Contrast 057 this with BooleanSelect which sends an output token every iteration. 058 059 @author Gang Zhou 060 @version $Id$ 061 @since Ptolemy II 4.1 062 @Pt.ProposedRating Yellow (zgang) 063 @Pt.AcceptedRating Yellow (cxh) 064 */ 065public class DDFBooleanSelect extends TypedAtomicActor { 066 /** Construct an actor in the specified container with the specified 067 * name. 068 * @param container The container. 069 * @param name The name of this actor within the container. 070 * @exception IllegalActionException If the actor cannot be contained 071 * by the proposed container. 072 * @exception NameDuplicationException If the name coincides with 073 * an actor already in the container. 074 */ 075 public DDFBooleanSelect(CompositeEntity container, String name) 076 throws IllegalActionException, NameDuplicationException { 077 super(container, name); 078 079 trueInput = new TypedIOPort(this, "trueInput", true, false); 080 falseInput = new TypedIOPort(this, "falseInput", true, false); 081 control = new TypedIOPort(this, "control", true, false); 082 control.setTypeEquals(BaseType.BOOLEAN); 083 output = new TypedIOPort(this, "output", false, true); 084 output.setTypeAtLeast(trueInput); 085 output.setTypeAtLeast(falseInput); 086 087 trueInput_tokenConsumptionRate = new Parameter(trueInput, 088 "tokenConsumptionRate"); 089 trueInput_tokenConsumptionRate.setVisibility(Settable.NOT_EDITABLE); 090 trueInput_tokenConsumptionRate.setTypeEquals(BaseType.INT); 091 092 falseInput_tokenConsumptionRate = new Parameter(falseInput, 093 "tokenConsumptionRate"); 094 falseInput_tokenConsumptionRate.setVisibility(Settable.NOT_EDITABLE); 095 falseInput_tokenConsumptionRate.setTypeEquals(BaseType.INT); 096 097 control_tokenConsumptionRate = new Parameter(control, 098 "tokenConsumptionRate"); 099 control_tokenConsumptionRate.setVisibility(Settable.NOT_EDITABLE); 100 control_tokenConsumptionRate.setTypeEquals(BaseType.INT); 101 102 // Put the control input on the bottom of the actor. 103 StringAttribute controlCardinal = new StringAttribute(control, 104 "_cardinal"); 105 controlCardinal.setExpression("SOUTH"); 106 } 107 108 /////////////////////////////////////////////////////////////////// 109 //// ports and parameters //// 110 111 /** Input for tokens on the true path. The port type can be any type. 112 */ 113 public TypedIOPort trueInput; 114 115 /** Input for tokens on the false path. The port type can be any type. 116 */ 117 public TypedIOPort falseInput; 118 119 /** Input that selects one of the other input ports. The type is 120 * boolean. 121 */ 122 public TypedIOPort control; 123 124 /** The output port. The type is at least the type of 125 * <i>trueInput</i> and <i>falseInput</i> 126 */ 127 public TypedIOPort output; 128 129 /** This parameter provides token consumption rate for <i>trueInput</i>. 130 * The type is int. 131 */ 132 public Parameter trueInput_tokenConsumptionRate; 133 134 /** This parameter provides token consumption rate for <i>falseInput</i>. 135 * The type is int. 136 */ 137 public Parameter falseInput_tokenConsumptionRate; 138 139 /** This parameter provides token consumption rate for <i>control</i>. 140 * The type is int. 141 */ 142 public Parameter control_tokenConsumptionRate; 143 144 /////////////////////////////////////////////////////////////////// 145 //// public methods //// 146 147 /** Clone the actor into the specified workspace. This calls the 148 * base class and then sets the type constraints. 149 * @param workspace The workspace for the new object. 150 * @return A new actor. 151 * @exception CloneNotSupportedException If a derived class has 152 * an attribute that cannot be cloned. 153 */ 154 @Override 155 public Object clone(Workspace workspace) throws CloneNotSupportedException { 156 DDFBooleanSelect newObject = (DDFBooleanSelect) super.clone(workspace); 157 newObject.output.setTypeAtLeast(newObject.trueInput); 158 newObject.output.setTypeAtLeast(newObject.falseInput); 159 return newObject; 160 } 161 162 /** Fire the actor once. If the <i>control</i> port is not read in the 163 * previous iteration, read a new token from the <i>control</i> port 164 * and record the value of the token and this concludes the current 165 * firing. Otherwise output the token consumed from the <i>trueInput</i> 166 * port if the token read from the <i>control</i> port in the previous 167 * firing is true. Likewise with a false <i>control</i> input and the 168 * <i>falseInput</i> port. Then reset an internal variable so that 169 * it will read from the <i>control</i> port in the next iteration. 170 * @exception IllegalActionException If there is no director, and hence 171 * no receivers have been created. 172 */ 173 @Override 174 public void fire() throws IllegalActionException { 175 super.fire(); 176 177 if (_isControlRead) { 178 if (_control) { 179 output.send(0, trueInput.get(0)); 180 } else { 181 output.send(0, falseInput.get(0)); 182 } 183 184 _isControlRead = false; 185 } else { 186 _control = ((BooleanToken) control.get(0)).booleanValue(); 187 _isControlRead = true; 188 } 189 } 190 191 /** Initialize this actor and the rate parameters so that it will read 192 * from the <i>control</i> port in the first iteration. 193 * @exception IllegalActionException If setToken() throws it. 194 */ 195 @Override 196 public void initialize() throws IllegalActionException { 197 super.initialize(); 198 _isControlRead = false; 199 trueInput_tokenConsumptionRate.setToken(_zero); 200 falseInput_tokenConsumptionRate.setToken(_zero); 201 control_tokenConsumptionRate.setToken(_one); 202 } 203 204 /** Update rate parameters for the next iteration. 205 * Then return whatever the superclass returns. 206 * @return True if execution can continue into the next iteration. 207 * @exception IllegalActionException If setToken() throws it. 208 */ 209 @Override 210 public boolean postfire() throws IllegalActionException { 211 if (_isControlRead) { 212 if (_control) { 213 trueInput_tokenConsumptionRate.setToken(_one); 214 falseInput_tokenConsumptionRate.setToken(_zero); 215 control_tokenConsumptionRate.setToken(_zero); 216 } else { 217 trueInput_tokenConsumptionRate.setToken(_zero); 218 falseInput_tokenConsumptionRate.setToken(_one); 219 control_tokenConsumptionRate.setToken(_zero); 220 } 221 } else { 222 trueInput_tokenConsumptionRate.setToken(_zero); 223 falseInput_tokenConsumptionRate.setToken(_zero); 224 control_tokenConsumptionRate.setToken(_one); 225 } 226 227 return super.postfire(); 228 } 229 230 /** Return false if the port to read from in the current 231 * iteration does not have a token. If the <i>control</i> port is 232 * not read in the previous iteration, the port to read from 233 * in the current iteration is the <i>control</i> port. Otherwise, 234 * it is the <i>trueInput</i> port or the <i>falseInput</i> port 235 * depending on the <i>control</i> input value read in the 236 * previous iteration. 237 * @return False if there are not enough tokens to fire. 238 * @exception IllegalActionException If the receivers do not support 239 * the query, or if there is no director, and hence no receivers. 240 */ 241 @Override 242 public boolean prefire() throws IllegalActionException { 243 if (_isControlRead) { 244 if (_control) { 245 if (!trueInput.hasToken(0)) { 246 return false; 247 } 248 } else { 249 if (!falseInput.hasToken(0)) { 250 return false; 251 } 252 } 253 } else { 254 if (!control.hasToken(0)) { 255 return false; 256 } 257 } 258 259 return super.prefire(); 260 } 261 262 /////////////////////////////////////////////////////////////////// 263 //// private variables //// 264 265 /** The most recently read <i>control</i> token. 266 */ 267 private boolean _control; 268 269 /** The boolean to determine whether to read from the <i>control<i> 270 * port or the <i>trueInput</i>/<i>falseInput</i> port. 271 */ 272 private boolean _isControlRead; 273 274 /** A final static IntToken with value 0. 275 */ 276 private final static IntToken _zero = new IntToken(0); 277 278 /** A final static IntToken with value 1. 279 */ 280 private final static IntToken _one = new IntToken(1); 281}