001/* Output the elapsed time in seconds. 002 003 @Copyright (c) 1998-2015 The Regents of the University of California. 004 All rights reserved. 005 006 Permission is hereby granted, without written agreement and without 007 license or royalty fees, to use, copy, modify, and distribute this 008 software and its documentation for any purpose, provided that the 009 above copyright notice and the following two paragraphs appear in all 010 copies of this software. 011 012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 016 SUCH DAMAGE. 017 018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 023 ENHANCEMENTS, OR MODIFICATIONS. 024 025 PT_COPYRIGHT_VERSION 2 026 COPYRIGHTENDKEY 027 */ 028package ptolemy.actor.lib; 029 030import ptolemy.actor.Director; 031import ptolemy.actor.TypedIOPort; 032import ptolemy.data.DoubleToken; 033import ptolemy.data.Token; 034import ptolemy.data.type.BaseType; 035import ptolemy.kernel.CompositeEntity; 036import ptolemy.kernel.util.IllegalActionException; 037import ptolemy.kernel.util.NameDuplicationException; 038import ptolemy.kernel.util.Workspace; 039 040/** 041 Upon firing, this actor outputs the elapsed real time in seconds 042 since the start time of the model, as reported by the director. 043 The output type is double. 044 The resolution of time depends on the implementation of the Java 045 virtual machine, but with Sun's JDK 1.3 under Windows 2000, it is 046 10 milliseconds. 047 <p> 048 Note that relying on the data produced by this actor is tricky 049 in domains where you do not have precise control over the 050 scheduling, since the output reflects the wall-clock time at 051 which this actor is fired, which may or may not be indicative 052 of the times at which other actors fire. So that you can get 053 more control over the schedule, the input provided at the 054 <i>trigger</i> port is passed through to the <i>passThrough</i> 055 output port. This can be used to ensure that this actor 056 fires before another downstream actor. 057 058 @see Director#elapsedTimeSinceStart() 059 @author Edward A. Lee 060 @version $Id$ 061 @since Ptolemy II 2.0 062 @Pt.ProposedRating Red (eal) 063 @Pt.AcceptedRating Red (cxh) 064 */ 065public class WallClockTime extends Source { 066 /** Construct an actor with the given container and name. 067 * @param container The container. 068 * @param name The name of this actor. 069 * @exception IllegalActionException If the actor cannot be contained 070 * by the proposed container. 071 * @exception NameDuplicationException If the container already has an 072 * actor with this name. 073 */ 074 public WallClockTime(CompositeEntity container, String name) 075 throws IllegalActionException, NameDuplicationException { 076 super(container, name); 077 078 output.setTypeEquals(BaseType.DOUBLE); 079 080 passThrough = new TypedIOPort(this, "passThrough", false, true); 081 passThrough.setTypeAtLeast(trigger); 082 passThrough.setMultiport(true); 083 passThrough.setWidthEquals(trigger, true); 084 085 // Override the clock to make it look a bit 086 // different from the DiscreteClock and PoissonClock. 087 _attachText("_iconDescription", "<svg>\n" + "<rect x=\"-20\" y=\"-20\" " 088 + "width=\"40\" height=\"40\" " + "style=\"fill:lightGrey\"/>\n" 089 + "<circle cx=\"0\" cy=\"0\" r=\"17\"" 090 + "style=\"fill:black\"/>\n" 091 + "<line x1=\"0\" y1=\"-15\" x2=\"0\" y2=\"-13\" style=\"stroke:white\"/>\n" 092 + "<line x1=\"0\" y1=\"14\" x2=\"0\" y2=\"16\" style=\"stroke:white\"/>\n" 093 + "<line x1=\"-15\" y1=\"0\" x2=\"-13\" y2=\"0\" style=\"stroke:white\"/>\n" 094 + "<line x1=\"14\" y1=\"0\" x2=\"16\" y2=\"0\" style=\"stroke:white\"/>\n" 095 + "<line x1=\"0\" y1=\"-8\" x2=\"0\" y2=\"0\" style=\"stroke:white\"/>\n" 096 + "<line x1=\"0\" y1=\"0\" x2=\"11.26\" y2=\"-6.5\" style=\"stroke:white\"/>\n" 097 + "</svg>\n"); 098 } 099 100 /////////////////////////////////////////////////////////////////// 101 //// ports and parameters //// 102 103 /** The output port to which the <i>trigger</i> input is passed. 104 * The type is the same as the type of the <i>trigger</i> port, 105 * which is undeclared, meaning that it will resolve to any type. 106 */ 107 public TypedIOPort passThrough; 108 109 /////////////////////////////////////////////////////////////////// 110 //// public methods //// 111 112 /** Override the base class to set the type constraints on the ports. 113 * @param workspace The workspace for the cloned object. 114 * @return A new instance of WallClockTime. 115 * @exception CloneNotSupportedException If a derived class includes 116 * an attribute that cannot be cloned. 117 */ 118 @Override 119 public Object clone(Workspace workspace) throws CloneNotSupportedException { 120 WallClockTime newObject = (WallClockTime) super.clone(workspace); 121 newObject.passThrough.setTypeAtLeast(newObject.trigger); 122 newObject.passThrough.setWidthEquals(newObject.trigger, true); 123 return newObject; 124 } 125 126 /** Output the elapsed time in seconds since the invocation 127 * of the initialize() method. 128 * @exception IllegalActionException If there is no director, or 129 * if the base class throws it. 130 */ 131 @Override 132 public void fire() throws IllegalActionException { 133 // NOTE: Do not call super.fire() because it reads the trigger 134 // input. 135 if (_debugging) { 136 _debug("Called fire()"); 137 } 138 139 output.broadcast(new DoubleToken(_getCurrentTime())); 140 141 for (int i = 0; i < trigger.getWidth(); i++) { 142 if (trigger.hasToken(i)) { 143 Token token = trigger.get(i); 144 145 if (i < passThrough.getWidth()) { 146 passThrough.send(i, token); 147 } 148 } 149 } 150 } 151 152 /////////////////////////////////////////////////////////////////// 153 //// protected methods //// 154 155 /** Get the elapsed time since the model starts. 156 * @return A double value representing the elapsed time. 157 */ 158 protected double _getCurrentTime() { 159 // Note that we need not to use the actor.util.Time class 160 // here because if we do, it breaks deep codegen because 161 // deep codegen removes the Actor classes, and actor.util.Time 162 // needs to keep track of the Director. 163 return getDirector().elapsedTimeSinceStart() / 1000.0; 164 } 165}