001/* An actor that produces a copy of the most recent input each time 002 the inhibit input does not receive an event. 003 004 Copyright (c) 2001-2014 The Regents of the University of California. 005 All rights reserved. 006 Permission is hereby granted, without written agreement and without 007 license or royalty fees, to use, copy, modify, and distribute this 008 software and its documentation for any purpose, provided that the above 009 copyright notice and the following two paragraphs appear in all copies 010 of this software. 011 012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 016 SUCH DAMAGE. 017 018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 023 ENHANCEMENTS, OR MODIFICATIONS. 024 025 PT_COPYRIGHT_VERSION_2 026 COPYRIGHTENDKEY 027 028 */ 029package ptolemy.domains.de.lib; 030 031import ptolemy.actor.TypedIOPort; 032import ptolemy.actor.lib.Transformer; 033import ptolemy.data.Token; 034import ptolemy.data.type.BaseType; 035import ptolemy.kernel.CompositeEntity; 036import ptolemy.kernel.util.IllegalActionException; 037import ptolemy.kernel.util.NameDuplicationException; 038import ptolemy.kernel.util.StringAttribute; 039import ptolemy.kernel.util.Workspace; 040 041/////////////////////////////////////////////////////////////////// 042//// Inhibit 043 044/** 045 Output a received input token, unless the <i>inhibit</i> port receives a 046 token at the same time. If no token has been received on the <i>input</i> 047 port when a token is received on the <i>inhibit</i> port, then no output is 048 produced. The inputs can be of any token type, and the output 049 is constrained to be of a type at least that of the input. 050 <p> 051 Both the <i>input</i> port and the <i>output</i> port are multiports. 052 Generally, their widths should match. Otherwise, if the width of the 053 <i>input</i> is greater than 054 the width of the <i>output</i>, the extra input tokens will 055 not appear on any output, although they will be consumed from 056 the input port. If the width of the <i>output</i> is greater 057 than that of the <i>input</i>, then the last few 058 channels of the <i>output</i> will never emit tokens. 059 <p> 060 This actor is similar to the Sampler actor in that it modifies a 061 stream of events based on the presence or absence of events from another 062 input. This actor reacts to the absence of the other event, whereas 063 Sampler reacts to the presence of it. 064 065 @author Steve Neuendorffer and Edward A. Lee 066 @version $Id$ 067 @since Ptolemy II 2.0 068 @Pt.ProposedRating Yellow (neuendor) 069 @Pt.AcceptedRating Yellow (neuendor) 070 @see ptolemy.domains.de.lib.MostRecent 071 */ 072public class Inhibit extends Transformer { 073 /** Construct an actor with the given container and name. 074 * @param container The container. 075 * @param name The name of this actor. 076 * @exception IllegalActionException If the actor cannot be contained 077 * by the proposed container. 078 * @exception NameDuplicationException If the container already has an 079 * actor with this name. 080 */ 081 public Inhibit(CompositeEntity container, String name) 082 throws NameDuplicationException, IllegalActionException { 083 super(container, name); 084 input.setMultiport(true); 085 output.setMultiport(true); 086 output.setTypeAtLeast(input); 087 output.setWidthEquals(input, true); 088 089 inhibit = new TypedIOPort(this, "inhibit", true, false); 090 inhibit.setMultiport(true); 091 inhibit.setTypeEquals(BaseType.GENERAL); 092 StringAttribute cardinality = new StringAttribute(inhibit, "_cardinal"); 093 cardinality.setExpression("SOUTH"); 094 095 _attachText("_iconDescription", "<svg>\n" + "<rect x=\"-30\" y=\"-20\" " 096 + "width=\"60\" height=\"40\" " + "style=\"fill:white\"/>\n" 097 + "<polyline points=\"0,20 0,0\"/>\n" 098 + "<polyline points=\"-30,-0 -10,0\"/>\n" 099 + "<polyline points=\"-10,-10 10,10\" style=\"stroke:red\"/>\n" 100 + "<polyline points=\"-10,10 10,-10\" style=\"stroke:red\"/>\n" 101 + "<polyline points=\"10,0 30,0\"/>\n" + "</svg>\n"); 102 } 103 104 /////////////////////////////////////////////////////////////////// 105 //// ports and parameters //// 106 107 /** The inhibit port, which has type Token. If this port 108 * does not receive a token, then the most recent token from the 109 * <i>input</i> port will be emitted on the <i>output</i> port. 110 */ 111 public TypedIOPort inhibit; 112 113 /////////////////////////////////////////////////////////////////// 114 //// public methods //// 115 116 /** Clone the actor into the specified workspace. This calls the 117 * base class and then sets the ports. 118 * @param workspace The workspace for the new object. 119 * @return A new actor. 120 * @exception CloneNotSupportedException If a derived class has 121 * has an attribute that cannot be cloned. 122 */ 123 @Override 124 public Object clone(Workspace workspace) throws CloneNotSupportedException { 125 Inhibit newObject = (Inhibit) super.clone(workspace); 126 newObject.output.setTypeAtLeast(newObject.input); 127 return newObject; 128 } 129 130 /** Consume at most one token from each channel of the 131 * <i>input</i> port. If there is a token on the <i>inhibit</i> 132 * port, then consume it and discard the input tokens. If no 133 * token is present on the <i>inhibit</i> port, then emit the 134 * input tokens on the <i>output</i> port. If there are no 135 * input tokens then no output is produced. 136 * @exception IllegalActionException If there is no director. 137 */ 138 @Override 139 public void fire() throws IllegalActionException { 140 super.fire(); 141 boolean hasInhibit = false; 142 for (int i = 0; i < inhibit.getWidth(); i++) { 143 if (inhibit.hasToken(i)) { 144 // Consume the inhibit token. 145 inhibit.get(i); 146 hasInhibit = true; 147 } 148 } 149 // Consume the inputs. 150 int outputWidth = output.getWidth(); 151 for (int i = 0; i < input.getWidth(); i++) { 152 if (input.hasToken(i)) { 153 Token token = input.get(i); 154 if (!hasInhibit && i < outputWidth) { 155 output.send(i, token); 156 } 157 } 158 } 159 } 160}