001/* A schedule element that contains a reference to an actor. 002 003 Copyright (c) 1998-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.sched; 029 030import java.util.Collections; 031import java.util.ConcurrentModificationException; 032import java.util.Iterator; 033import java.util.List; 034import java.util.NoSuchElementException; 035 036import ptolemy.actor.Actor; 037import ptolemy.kernel.util.InvalidStateException; 038 039/////////////////////////////////////////////////////////////////// 040//// Firing 041 042/** 043 This class is a schedule element that contains a reference to an 044 actor and an iteration count. This class is used together 045 with the Schedule class to construct a static schedule. 046 This class is used to represent a single actor repeated some 047 number of times, whereas Schedule is used for multi-actor schedules. 048 The setActor() method is used to 049 create the reference to an actor, and the setIterationCount() method 050 to set the iteration count. The getActor() method will return 051 a reference to this actor, and getIterationCount() will return 052 the iteration count. <p> 053 054 It is more efficient to use this class than to simply maintain a list of 055 actors since actors will often fire multiple times consecutively. Using 056 this class (and the Schedule data structure in general) greatly reduces the 057 memory requirements of most large schedules. 058 059 @author Brian K. Vogel, Steve Neuendorffer 060 @version $Id$ 061 @since Ptolemy II 1.0 062 @Pt.ProposedRating Green (vogel) 063 @Pt.AcceptedRating Yellow (chf) 064 @see ptolemy.actor.sched.Schedule 065 @see ptolemy.actor.sched.ScheduleElement 066 */ 067public class Firing extends ScheduleElement { 068 /** Construct a firing with a default iteration count equal to one 069 * and with no parent schedule. 070 */ 071 public Firing() { 072 super(); 073 } 074 075 /** Construct a firing with a actor, an iteration count equal to one 076 * and no parent schedule. 077 * @param actor The actor in the firing. 078 */ 079 public Firing(Actor actor) { 080 super(); 081 _actor = actor; 082 } 083 084 /////////////////////////////////////////////////////////////////// 085 //// public methods //// 086 087 /** Return the actor invocation sequence of the schedule in the 088 * form of a sequence of actors. For a valid schedule, all of the 089 * lowest-level nodes should be an instance of Actor. If the 090 * schedule is not valid, then the returned iterator will contain 091 * null elements. 092 * <p> 093 * A runtime exception is thrown if the 094 * underlying schedule structure is modified while the iterator 095 * is active. 096 * 097 * @return An iterator over a sequence of actors. 098 * @exception ConcurrentModificationException If the 099 * underlying schedule structure is modified while the iterator 100 * is active. 101 */ 102 @Override 103 public Iterator actorIterator() { 104 return new ActorIterator(getIterationCount()); 105 } 106 107 /** Return the actor invocation sequence in the form 108 * of a sequence of firings. 109 * Since this ScheduleElement is a Firing, which 110 * represents an Actor and an iteration count. the 111 * iterator returned will contain exactly one Firing (this Firing). 112 * <p> 113 * A runtime exception is thrown if the 114 * underlying schedule structure is modified while the iterator 115 * is active. 116 * 117 * @return An iterator over a sequence of firings. 118 * @exception ConcurrentModificationException If the 119 * underlying schedule structure is modified while the iterator 120 * is active. 121 */ 122 @Override 123 public Iterator firingIterator() { 124 // FIXME: a ConcurrentModificationException will not necessarily 125 // be thrown, see the failing tests. 126 if (_firing == null) { 127 _firing = Collections.singletonList(this); 128 } 129 130 return _firing.iterator(); 131 } 132 133 /** Get the actor associated with this Firing. The setActor() 134 * method is used to set the actor that this method returns. 135 * If setActor() was never called, then throw an exception. 136 * 137 * @return The actor associated with this Firing. 138 * @see #setActor(Actor) 139 */ 140 public Actor getActor() { 141 return _actor; 142 } 143 144 /** Set the actor associated with this firing. This actor will 145 * then be returned when the getActor() method is invoked. If this 146 * firing already contains a reference to an actor, then the 147 * reference will overwritten. 148 * 149 * @param actor The actor to associate with this firing. 150 * @see #getActor() 151 */ 152 public void setActor(Actor actor) { 153 _incrementVersion(); 154 _actor = actor; 155 } 156 157 /** 158 * Output a string representation of this Firing. 159 */ 160 @Override 161 public String toString() { 162 String result = "Fire Actor " + _actor; 163 int iterationCount = getIterationCount(); 164 165 if (iterationCount > 1) { 166 result += " " + iterationCount + " times"; 167 } 168 169 return result; 170 } 171 172 /////////////////////////////////////////////////////////////////// 173 //// inner classes //// 174 175 /** An adapter class for iterating over the elements of this 176 * schedule. An exception is thrown if the schedule structure 177 * changes while this iterator is active. 178 */ 179 private class ActorIterator implements Iterator { 180 // As of 8/02, it seems like this inner class is not really 181 // used except by the test suite. 182 183 /** Construct a ScheduleIterator. 184 */ 185 public ActorIterator(int iterationCount) { 186 _startingVersion = _getVersion(); 187 _currentElement = 0; 188 _iterationCount = iterationCount; 189 } 190 191 /** Return true if the iteration has more elements. 192 * 193 * @exception ConcurrentModificationException If the schedule 194 * data structure has changed since this iterator 195 * was created. 196 * @return true if the iterator has more elements. 197 */ 198 @Override 199 public boolean hasNext() { 200 if (_startingVersion != _getVersion()) { 201 throw new ConcurrentModificationException( 202 "Schedule structure changed while iterator is active."); 203 } else { 204 return _currentElement <= _iterationCount; 205 } 206 } 207 208 /** Return the next object in the iteration. 209 * 210 * @exception InvalidStateException If the schedule 211 * data structure has changed since this iterator 212 * was created. 213 * @return the next object in the iteration. 214 */ 215 @Override 216 public Object next() throws NoSuchElementException { 217 if (!hasNext()) { 218 throw new NoSuchElementException("No element to return."); 219 } else { 220 _currentElement++; 221 return getActor(); 222 } 223 } 224 225 /** Throw an exception, since removal is not allowed. It really 226 * doesn't make sense to remove an actor from an actor invocation 227 * sequence anyway. 228 */ 229 @Override 230 public void remove() { 231 throw new UnsupportedOperationException(); 232 } 233 234 private long _startingVersion; 235 236 private int _currentElement; 237 238 private int _iterationCount; 239 } 240 241 /////////////////////////////////////////////////////////////////// 242 //// private variables //// 243 // The actor associated with this firing. 244 private Actor _actor; 245 246 // The list containing this firing as the only element. 247 private List _firing = null; 248}