001/* A merge actor for the Continuous domain. 002 003 Copyright (c) 1997-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.continuous.lib; 029 030import java.util.LinkedList; 031import java.util.List; 032 033import ptolemy.actor.lib.Transformer; 034import ptolemy.data.BooleanToken; 035import ptolemy.data.Token; 036import ptolemy.data.expr.Parameter; 037import ptolemy.data.type.BaseType; 038import ptolemy.kernel.CompositeEntity; 039import ptolemy.kernel.util.IllegalActionException; 040import ptolemy.kernel.util.NameDuplicationException; 041 042/////////////////////////////////////////////////////////////////// 043//// ContinuousMerge 044 045/** 046 A merge actor for the Continuous domain. This port has a multiport 047 input and on each firing, sends the input from channel 0 to the 048 output, if the input at channel 0 is present. Otherwise, it sends 049 the input from channel 1, if it is present. It continues to search 050 the inputs in channel order until it finds one that is present 051 or it runs out of input channels. In the latter case, the output 052 will be absent. 053 <p> 054 By default, this actor discards data on all channels after 055 the first channel that has present data. If you set the <i>discard</i> 056 parameter to false, however, then it will collect all present 057 data in queue and output it in the next microstep until all 058 present inputs have been produced on the output. 059 Note that setting this to false creates a risk of a chattering 060 Zeno system if a continuous signal is provided as input. 061 <p> 062 Note that this actor can merge continuous signals with discrete 063 ones, but the resulting signal may not be piecewise continuous. 064 This will be a bit odd. It is most useful to merge discrete signals 065 or signals that are piecewise continuous. 066 067 @author Edward A. Lee 068 @version $Id$ 069 @since Ptolemy II 8.0 070 @Pt.ProposedRating Yellow (eal) 071 @Pt.AcceptedRating Red (eal) 072 */ 073public class ContinuousMerge extends Transformer { 074 /** Construct an actor in the specified container with the specified 075 * name. Create ports and make the input port a multiport. 076 * @param container The container. 077 * @param name The name. 078 * @exception NameDuplicationException If an actor 079 * with an identical name already exists in the container. 080 * @exception IllegalActionException If the actor cannot be contained 081 * by the proposed container. 082 */ 083 public ContinuousMerge(CompositeEntity container, String name) 084 throws NameDuplicationException, IllegalActionException { 085 super(container, name); 086 input.setMultiport(true); 087 088 _attachText("_iconDescription", 089 "<svg>\n" + "<polygon points=\"-10,20 10,10 10,-10, -10,-20\" " 090 + "style=\"fill:green\"/>\n" + "</svg>\n"); 091 092 discard = new Parameter(this, "discard"); 093 discard.setExpression("true"); 094 discard.setTypeEquals(BaseType.BOOLEAN); 095 } 096 097 /////////////////////////////////////////////////////////////////// 098 //// parameters //// 099 100 /** Indicator of whether to discard present inputs on channel numbers 101 * higher than the first one. This is a boolean that defaults to true. 102 */ 103 public Parameter discard; 104 105 /////////////////////////////////////////////////////////////////// 106 //// public methods //// 107 108 /** Read the input channels in order until either a present input 109 * is found or we run out of channels. In the former case, the first 110 * encountered input value is produced on the output. In the latter 111 * case, the output will be absent. 112 * @exception IllegalActionException If there is no director, or 113 * the input can not be read, or the output can not be sent. 114 */ 115 @Override 116 public void fire() throws IllegalActionException { 117 super.fire(); 118 boolean discardValue = ((BooleanToken) discard.getToken()) 119 .booleanValue(); 120 boolean outputProduced = false; 121 if (_pending != null && _pending.size() > 0) { 122 output.send(0, _pending.remove(0)); 123 outputProduced = true; 124 } 125 for (int i = 0; i < input.getWidth(); i++) { 126 if (input.hasToken(i)) { 127 if (!outputProduced) { 128 output.send(0, input.get(i)); 129 outputProduced = true; 130 } 131 if (discardValue) { 132 return; 133 } else { 134 if (_pending == null) { 135 _pending = new LinkedList<Token>(); 136 } 137 _pending.add(input.get(i)); 138 } 139 } 140 } 141 } 142 143 /** Initialize this actor by clearing memory of any pending outputs. 144 * @exception IllegalActionException If a derived class throws it. 145 */ 146 @Override 147 public void initialize() throws IllegalActionException { 148 super.initialize(); 149 if (_pending != null) { 150 _pending.clear(); 151 } 152 } 153 154 /** If there are any pending outputs, then request a refiring at the 155 * current time. 156 * @return True if execution can continue into the next iteration. 157 * @exception IllegalActionException Not thrown in this base class. 158 */ 159 @Override 160 public boolean postfire() throws IllegalActionException { 161 if (_pending != null && _pending.size() > 0) { 162 getDirector().fireAtCurrentTime(this); 163 } 164 return super.postfire(); 165 } 166 167 /////////////////////////////////////////////////////////////////// 168 //// private variables //// 169 170 /** Queue of pending output events. */ 171 private List<Token> _pending; 172}