001/*
002 @Copyright (c) 1998-2014 The Regents of the University of California.
003 All rights reserved.
004
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
008 above copyright notice and the following two paragraphs appear in all
009 copies 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.sdf.kernel.test;
029
030import ptolemy.actor.TypedAtomicActor;
031import ptolemy.actor.TypedIOPort;
032import ptolemy.data.IntToken;
033import ptolemy.data.expr.Parameter;
034import ptolemy.data.type.BaseType;
035import ptolemy.kernel.CompositeEntity;
036import ptolemy.kernel.util.IllegalActionException;
037import ptolemy.kernel.util.NameDuplicationException;
038
039/**
040 * This actor copies one token from its input to its output when fired.
041 *
042 * @author Steve Neuendorffer
043 * @version $Id$
044 * @since Ptolemy II 0.4
045 * @Pt.ProposedRating Red
046 * @Pt.AcceptedRating Red
047 */
048public class SDFTestDelay extends TypedAtomicActor {
049    /*
050     * Object constructor. This creates an object of class SDFTestDelay.
051     * The object will have a name given by the 'name' argument and will
052     * be contained within the composite actor given by the 'container'
053     * argument.   This method throws two exceptions, which are error
054     * conditions that the method (or one of the methods it calls) has
055     * detected (notice the @exception tag).
056     */
057
058    /**
059     * Create an SDFTestDelay actor in the given container with the given name.
060     * This actor copies one token from the input port named "input" to the
061     * output port named "output" when fired.
062     * @exception IllegalActionException If the contained methods throw it
063     * @exception NameDuplicationException If the contained methods throw it
064     */
065    public SDFTestDelay(CompositeEntity container, String name)
066            throws IllegalActionException, NameDuplicationException {
067        /* This starts out by calling TypedAtomicActor's constructor.
068         * allows us to add some extra code specific to this actor, in
069         * addition to the regular initializer in TypedAtomicActor.
070         */
071        super(container, name);
072
073        /* This construct is called a "try-catch block".  It is used to
074         * detect exceptions that occurred during the execution of some
075         * other code.  In this case, we detect IllegalActionException and
076         * print a reasonable error message.  This is convenient under
077         * some environments which can destroy the debugging information from
078         * java
079         */
080        /* Create a new input port */
081        input = new TypedIOPort(this, "input", true, false);
082
083        /* Set the Consumption rate on the port.  A good way to think of
084         * this is that you are making a contract with the Ptolemy system.
085         * If you always consume one token from this port when fired,
086         * then Ptolemy will always guarantee that there will be a token
087         * ready when you are fired.
088         */
089        input_tokenConsumptionRate = new Parameter(input,
090                "tokenConsumptionRate", new IntToken(1));
091
092        /* The getPort method (in ptolemy.kernel.Entity) finds a port by
093         * name.  It returns a Port object, but all the ports in the
094         * actor package are of type TypedIOPort,
095         * which extends Port.   So, we
096         * have to upcast the return value to the appropriate type.
097         * The setDeclaredType calls use the type system to define what
098         * types of tokens are valid for this actor.
099         */
100        input.setTypeEquals(BaseType.INT);
101
102        /* Similarly for the output port */
103        output = new TypedIOPort(this, "output", false, true);
104        output_tokenProductionRate = new Parameter(output,
105                "tokenProductionRate", new IntToken(1));
106
107        output.setTypeEquals(BaseType.INT);
108    }
109
110    public TypedIOPort input;
111
112    public TypedIOPort output;
113
114    public Parameter input_tokenConsumptionRate;
115
116    public Parameter output_tokenProductionRate;
117
118    /* Notice that constructors start the file.  Public methods should follow,
119     * in alphabetical order, followed by protected and private methods.
120     * Instance variables come at the end of the class.
121     */
122    /* The fire method is where the bulk of the action takes place.   In
123     * SDF, fire will be called exactly once between prefire and postfire.
124     * In this class, we get an input port, print its value, and put the
125     * same token back on the output port.
126     */
127
128    /** This fires an actor and may be invoked several times between
129     *  invocations of prefire() and postfire(). It may produce output
130     *  data. Typically, the fire() method performs the computation associated
131     *  with an actor.
132     *
133     *  @exception IllegalActionException If firing is not permitted.
134     */
135    @Override
136    public void fire() throws IllegalActionException {
137        /* First we declare a variable that is a Token that can carry
138         * integer data (ptolemy.data.IntToken).
139         */
140        IntToken message;
141
142        /* Figure out how many tokens should be copied from the input to the
143         * output.
144         */
145        int tokens = ((IntToken) input_tokenConsumptionRate.getToken())
146                .intValue();
147
148        if (((IntToken) output_tokenProductionRate.getToken())
149                .intValue() != tokens) {
150            throw new IllegalActionException(
151                    "SDFTestDelay: Rates on input port and output port "
152                            + "must match!");
153        }
154
155        int i;
156
157        for (i = 0; i < tokens; i++) {
158            /* now that we have the port, we can get a token from it.
159             * The argument to get is known as the channel.
160             * The channel must be
161             * zero, since there can only be one IORelation connected to this
162             * input.  Multiple channels are useful with Multiports, which
163             * allow more than one relation to be connected to a port.
164             */
165            message = (IntToken) input.get(0);
166
167            /* After looking at the token, pass it along to the next actor
168             */
169            output.send(0, message);
170        }
171    }
172
173    /* Postfire is the last step in an iteration.   This actor returns
174     * true, since it places no limit on how execution may proceed.   In
175     * practice this method can be used to define a stopping condition,
176     * where execution will stop once some condition has been met.
177     */
178
179    /** This method should be invoked once per iteration, after the last
180     *  invocation of fire() in that iteration. It may produce output data.
181     *  It returns true if the execution can proceed into the next iteration.
182     *  This method typically wraps up an iteration, which may involve
183     *  updating local state. In an opaque, non-atomic entity, it may also
184     *  transfer output data.
185     *
186     *  @return True if the execution can continue.
187     *  @exception IllegalActionException If postfiring is not permitted.
188     */
189    @Override
190    public boolean postfire() throws IllegalActionException {
191        return true;
192    }
193
194    /* Prefire is the first step in every iteration.  This method returns
195     * true if the actor can perform useful work by being fired.   For
196     * example, an actor could return false if it was waiting for a certain
197     * amount of data for a calculation, but that amount of data was not
198     * yet present.  Most actors under SDF will just return true, since they
199     * have made a contract with the SDF domain to be fired when enough data
200     * is present.
201     */
202
203    /** This method should be invoked once per iteration, before the first
204     *  invocation of fire() in that iteration.  It returns true if the
205     *  iteration can proceed (the fire() method can be invoked). Thus
206     *  this method will typically check preconditions for an iteration, if
207     *  there are any. In an opaque, non-atomic entity,
208     *  it may move data into an inner subsystem.
209     *
210     *  @return True if the iteration can proceed.
211     *  @exception IllegalActionException If prefiring is not permitted.
212     */
213    @Override
214    public boolean prefire() throws IllegalActionException {
215        return true;
216    }
217
218    /* When this method is called, the actor must do everything in its power
219     * to immediately stop whatever it is doing.   This is primarily
220     * called under
221     * two circumstances.  The first is a user initiated break, such as
222     * via CTRL-C.  The second is if an error occurs during wrapup() that
223     * cannot be recovered from.
224     */
225
226    /** This method is invoked to immediately terminate any execution
227     *  within an actor.
228     */
229    @Override
230    public void terminate() {
231        return;
232    }
233
234    /* This method is called at the end of an execution, to allow the
235     * actor to cleanup after itself.  Often this will involve destroying
236     * graphical windows,  flushing buffers, etc.   This method will also get
237     * called under most abnormal termination conditions.
238     * This actor has nothing to do here.
239     */
240
241    /** This method should be invoked exactly once per execution
242     *  of an application.  None of the other action methods should be
243     *  be invoked after it.  It finalizes an execution, typically closing
244     *  files, displaying final results, etc.
245     *
246     *  @exception IllegalActionException If wrapup is not permitted.
247     */
248    @Override
249    public void wrapup() throws IllegalActionException {
250        return;
251    }
252}