001/* A commutator  that processes a single token per iteration.
002
003 Copyright (c) 2002-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.kernel.CompositeEntity;
031import ptolemy.kernel.util.IllegalActionException;
032import ptolemy.kernel.util.NameDuplicationException;
033
034///////////////////////////////////////////////////////////////////
035//// SingleTokenCommutator
036
037/**
038 The SingleTokenCommutator has a multiport input port and an output
039 port.  The types of the ports are undeclared and will be resolved by
040 the type resolution mechanism, with the constraint that the output
041 type must be greater than or equal to the input type. On each call to
042 the fire method, the actor reads one token from the current input,
043 and writes one token to an output channel.  If there is no token on
044 the input, then it will not produce a token on the output.  In the
045 next iteration of this actor, it will read the next channel.
046
047 @author Paul Whitaker, Mudit Goel, Edward A. Lee, Christopher Hylands, Jim Armstrong
048 @version $Id$
049 @since Ptolemy II 2.0
050 @Pt.ProposedRating Yellow (cxh)
051 @Pt.AcceptedRating Yellow (cxh)
052 */
053public class SingleTokenCommutator extends Transformer
054        implements SequenceActor {
055    // SingleTokenCommutator used to be in sr.lib, but
056    // ddf.lib.DDFSingleTokenCommutator depends on it, so we moved it
057    // to actor.lib
058
059    /** Construct an actor in the specified container with the specified
060     *  name. Create ports and make the input port a multiport. Create
061     *  the actor parameters.
062     *
063     *  @param container The container.
064     *  @param name This is the name of this distributor within the container.
065     *  @exception NameDuplicationException If an actor
066     *  with an identical name already exists in the container.
067     *  @exception IllegalActionException If the actor cannot be contained
068     *  by the proposed container.
069     */
070    public SingleTokenCommutator(CompositeEntity container, String name)
071            throws NameDuplicationException, IllegalActionException {
072        super(container, name);
073        input.setMultiport(true);
074    }
075
076    ///////////////////////////////////////////////////////////////////
077    ////                         public methods                    ////
078
079    /** Read at most one token from the current input channel and write that
080     *  token to the  output channel. If there is no token on the current
081     *  input channel, do nothing.
082     *  @exception IllegalActionException If there is no director.
083     */
084    @Override
085    public void fire() throws IllegalActionException {
086        super.fire();
087        if (input.hasToken(_currentInputPosition)) {
088            output.send(0, input.get(_currentInputPosition));
089        }
090    }
091
092    /** Begin execution by setting the current input channel to zero.
093     *  @exception IllegalActionException If there is no director.
094     */
095    @Override
096    public void initialize() throws IllegalActionException {
097        super.initialize();
098        _currentInputPosition = 0;
099    }
100
101    /** Update the input position to equal that determined by the most
102     *  recent invocation of the fire() method.  The input position is
103     *  the channel number of the input port from which the next input
104     *  will be read.
105     *  @exception IllegalActionException If there is no director.
106     */
107    @Override
108    public boolean postfire() throws IllegalActionException {
109        _currentInputPosition++;
110
111        if (_currentInputPosition >= input.getWidth()) {
112            _currentInputPosition = 0;
113        }
114
115        return super.postfire();
116    }
117
118    ///////////////////////////////////////////////////////////////////
119    ////                         protected methods                 ////
120
121    /** Get the current input position.
122     *  @return Current input position.
123     */
124
125    // This method is Added by Gang Zhou so that DDFSingleTokenCommutator
126    // can inherit this class.
127    protected int _getCurrentInputPosition() {
128        return _currentInputPosition;
129    }
130
131    ///////////////////////////////////////////////////////////////////
132    ////                         private variables                 ////
133    // The channel number for the next input.
134    private int _currentInputPosition;
135}