001/* Base class for source actors that will only a fire a limited number of times.
002
003 Copyright (c) 2007-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.IntToken;
031import ptolemy.data.expr.Parameter;
032import ptolemy.data.type.BaseType;
033import ptolemy.kernel.CompositeEntity;
034import ptolemy.kernel.util.Attribute;
035import ptolemy.kernel.util.IllegalActionException;
036import ptolemy.kernel.util.NameDuplicationException;
037import ptolemy.kernel.util.Settable;
038
039///////////////////////////////////////////////////////////////////
040//// LimitedFiringSource
041
042/**
043 Base class for source actors that will only fire a limited number of
044 times.  This actor has a parameter,
045 <i>firingCountLimit</i>, that optionally limits the number of iterations
046 for which the actor is fired.  If this number is <i>n</i> &gt; 0, then
047 the <i>n</i>-th invocation of postfire() returns false, which indicates
048 to the scheduler that it should stop invocations of this actor.
049 The default value of <i>firingCountLimit</i>
050 is NONE, which results in postfire always returning
051 true.  Derived classes must call super.postfire() for this mechanism to
052 work.
053
054 @author Edward A. Lee
055 @version $Id$
056 @since Ptolemy II 6.1
057 @Pt.ProposedRating Green (eal)
058 @Pt.AcceptedRating Green (bilung)
059 */
060public class LimitedFiringSource extends Source {
061    /** Construct an actor with the given container and name.
062     *  The <i>firingCountLimit</i> parameter is also constructed.
063     *  @param container The container.
064     *  @param name The name of this actor.
065     *  @exception IllegalActionException If the actor cannot be contained
066     *   by the proposed container.
067     *  @exception NameDuplicationException If the container already has an
068     *   actor with this name.
069     */
070    public LimitedFiringSource(CompositeEntity container, String name)
071            throws NameDuplicationException, IllegalActionException {
072        super(container, name);
073
074        firingCountLimit = new Parameter(this, "firingCountLimit");
075        firingCountLimit.setExpression("NONE");
076        firingCountLimit.setTypeEquals(BaseType.INT);
077
078        Parameter NONE = new Parameter(this, "NONE");
079
080        // Don't setExpression here, it breaks Copernicus, use setToken().
081        // NONE.setExpression("0");
082        NONE.setToken(IntToken.ZERO);
083
084        // Don't setTypeEquals here, it breaks Copernicus.
085        //NONE.setTypeEquals(BaseType.INT);
086        NONE.setVisibility(Settable.EXPERT);
087    }
088
089    ///////////////////////////////////////////////////////////////////
090    ////                     ports and parameters                  ////
091
092    /** If a positive integer, then the number of iterations before the
093     *  actor indicates to the scheduler that it is finished by returning
094     *  false in its postfire() method.
095     */
096    public Parameter firingCountLimit;
097
098    ///////////////////////////////////////////////////////////////////
099    ////                         public methods                    ////
100
101    /** Override the base class to determine which attribute is being
102     *  specified.
103     *  @param attribute The attribute that changed.
104     *  @exception IllegalActionException If the function is not recognized.
105     */
106    @Override
107    public void attributeChanged(Attribute attribute)
108            throws IllegalActionException {
109        if (attribute == firingCountLimit) {
110            _firingCountLimit = ((IntToken) firingCountLimit.getToken())
111                    .intValue();
112        }
113    }
114
115    /** Initialize the iteration counter.  A derived class must call
116     *  this method in its initialize() method or the <i>firingCountLimit</i>
117     *  feature will not work.
118     *  @exception IllegalActionException If the parent class throws it,
119     *   which could occur if, for example, the director will not accept
120     *   sequence actors.
121     */
122    @Override
123    public void initialize() throws IllegalActionException {
124        super.initialize();
125        _iterationCount = 0;
126    }
127
128    /** Increment the iteration counter, and if it equals the
129     *  value of the <i>firingCountLimit</i> parameter, return false.
130     *  Otherwise, return true.  Derived classes should call this
131     *  at the end of their postfire() method and return its returned
132     *  value.
133     *  @exception IllegalActionException If firingCountLimit has
134     *   an invalid expression.
135     */
136    @Override
137    public boolean postfire() throws IllegalActionException {
138        if (_firingCountLimit != 0) {
139            _iterationCount++;
140
141            if (_iterationCount == _firingCountLimit) {
142                return false;
143            }
144        }
145
146        return super.postfire();
147    }
148
149    ///////////////////////////////////////////////////////////////////
150    ////                         protected variables               ////
151
152    /** This is the value in parameter
153     * firingCountLimit.
154     * It may be convenient for derived classes to read this
155     *  variable in the iterate() method.
156     */
157    protected int _firingCountLimit;
158
159    /** The current number of elapsed iterations.
160     * It may be convenient for derived classes to read/set this
161     * variable in the iterate() method.
162     */
163    protected int _iterationCount = 0;
164}