[kepler-dev] Sleep actor sleeping more than it needs to

Edward A. Lee eal at eecs.berkeley.edu
Wed Oct 20 11:20:56 PDT 2004


I was able to replicate this in 4.0.1, but it appears to be fixed
in the CVS head.  There have been some changes to the Sleep actor.
I've attached the latest source for that actor...

Edward

At 06:21 PM 10/19/2004 -0700, xiaowen wrote:
>Hi All,
>
>In my testing, it appears that the Sleep actor (ptolemy.actor.lib.Sleep) 
>sleeps more than it needs to.  Attached is a workflow that demonstrates 
>what I mean.  The Sleep actor in this workflow never receives a token, and 
>yet, the workflow still appears to pause for the specified number of 
>seconds.  Ideally, since the fire() method should not be called on this 
>actor, the workflow should finish immediately.
>
>Is there a workaround for this?  Or am I misunderstanding something about 
>how the director or this actor works?
>
>I'm running Ptolemy 4.0.1 on Linux.
>
>Thanks!
>Xiaowen
>
>_______________________________________________
>kepler-dev mailing list
>kepler-dev at ecoinformatics.org
>http://www.ecoinformatics.org/mailman/listinfo/kepler-dev

------------
Edward A. Lee, Professor
518 Cory Hall, UC Berkeley, Berkeley, CA 94720
phone: 510-642-0455, fax: 510-642-2739
eal at eecs.Berkeley.EDU, http://ptolemy.eecs.berkeley.edu/~eal
-------------- next part --------------
/* An actor that delays the input for a certain amount of real time.

Copyright (c) 1998-2004 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.

IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.

PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY

*/

package ptolemy.actor.lib;

import ptolemy.actor.parameters.PortParameter;
import ptolemy.data.LongToken;
import ptolemy.data.Token;
import ptolemy.data.type.BaseType;
import ptolemy.kernel.CompositeEntity;
import ptolemy.kernel.Port;
import ptolemy.kernel.util.IllegalActionException;
import ptolemy.kernel.util.NameDuplicationException;
import ptolemy.kernel.util.StringAttribute;
import ptolemy.kernel.util.Workspace;

//////////////////////////////////////////////////////////////////////////
//// Sleep
/**
   On each firing, read at most one token from each input channel, sleep
   by the specified amount of real time, and then produce the same input
   tokens on the respective output channels. This actor calls Thread.sleep()
   in the fire() method, so the thread that calls fire() will be suspended.
   If fire() is called multiple times in one iteration, sleep is only called
   the first time.
   If the width of the output port is less than that of the input port,
   the tokens in the extra channels are lost.
   <p>
   The effect of this actor is different in different domains.
   In domains where all actors are iterated from within a single director
   thread (like SDF and DE), then multiple instances of this actor will
   result in cummulative time delays. That is, the time taken by an iteration
   of the model will be greater than the sum of the sleep times of all the
   instances. In domains where actors execute in their own thread (like PN
   and CSP), only the execution of the individual actor is slowed.
   Note that another way to slow down the execution of a model while running
   inside vergil is to turn on animation.

   @author Jie Liu, Christopher Hylands, Edward A. Lee
   @version $Id: Sleep.java,v 1.21 2004/08/29 23:31:26 eal Exp $
   @since Ptolemy II 1.0
   
   @Pt.ProposedRating Green (eal)
   @Pt.AcceptedRating Yellow (cxh)
*/
public class Sleep extends Transformer {

    /** Construct an actor with the given container and name.
     *  @param container The container.
     *  @param name The name of this actor.
     *  @exception IllegalActionException If the actor cannot be contained
     *   by the proposed container.
     *  @exception NameDuplicationException If the container already has an
     *   actor with this name.
     */
    public Sleep(CompositeEntity container, String name)
            throws NameDuplicationException, IllegalActionException  {
        super(container, name);
        sleepTime = new PortParameter(this, "sleepTime");
        sleepTime.setExpression("0L");
        sleepTime.setTypeEquals(BaseType.LONG);
        
        Port sleepPort = sleepTime.getPort();
        StringAttribute sleepCardinal
                = new StringAttribute(sleepPort, "_cardinal");
        sleepCardinal.setExpression("SOUTH");
        
        // Data type polymorphic, multiports.
        input.setMultiport(true);
        output.setMultiport(true);
        output.setTypeAtLeast(input);
    }

    ///////////////////////////////////////////////////////////////////
    ////                     ports and parameters                  ////

    /** The sleep time in milliseconds. This has type long and default
     *  "0L".
     */
    public PortParameter sleepTime;

    ///////////////////////////////////////////////////////////////////
    ////                         public methods                    ////

    /** Override the base class to set type constraints.
     *  @param workspace The workspace for the cloned object.
     *  @exception CloneNotSupportedException If cloned ports cannot have
     *   as their container the cloned entity (this should not occur), or
     *   if one of the attributes cannot be cloned.
     *  @return A new instance of Sleep.
     */
    public Object clone(Workspace workspace)
            throws CloneNotSupportedException {
        Sleep newObject = (Sleep)super.clone(workspace);
        newObject.output.setTypeAtLeast(newObject.input);
        return newObject;
    }
    
    /** Read input tokens, call Thread.sleep(), and then
     *  transfer tokens from inputs to outputs, at most one token from each
     *  channel.  If fire() is called twice in a row without an
     *  intervening call to either postfire() or prefire(), then no
     *  sleep is performed, an inputs are copied to the output immediately.
     *  <p>
     *  If the width of the output port is less than
     *  that of the input port, the tokens in the extra channels
     *  are lost.
     *  @exception IllegalActionException Not thrown in this base class
     */
    public void fire() throws IllegalActionException {
        int inputWidth = input.getWidth();
        Token[] inputs = new Token[inputWidth];
        for (int i = 0; i < inputWidth; i++) {
            if (input.hasToken(i)) {
                inputs[i] = input.get(i);
            }
        }
        if (!_wasSleepCalledInFireYet) {
            try {
                long sleepTimeValue
                        = ((LongToken)sleepTime.getToken()).longValue();
                if (_debugging) {
                    _debug(getName()
                            + ": Wait for "
                            + sleepTimeValue
                            + " milliseconds.");
                }
                Thread.sleep(sleepTimeValue);
            } catch (InterruptedException e) {
                // Ignore...
            }
        }
        int outputWidth = output.getWidth();
        for (int i = 0; i < inputWidth; i++) {
            if (inputs[i] != null) {
                if ( i < outputWidth) {
                    output.send(i, inputs[i]);
                }
            }
        }
    }

    /** Reset the flag that fire() checks so that fire() only sleeps once
     *  per iteration.
     *  @exception IllegalActionException If the parent class throws it.
     *  @return Whatever the superclass returns (probably true).
     */
    public boolean postfire() throws IllegalActionException {
        _wasSleepCalledInFireYet = false;
        return super.postfire();
    }

    /** Reset the flag that fire() checks so that fire() only sleeps once
     *  per iteration.
     *  @exception IllegalActionException If the parent class throws it.
     *  @return Whatever the superclass returns (probably true).
     */
    public boolean prefire() throws IllegalActionException {
        _wasSleepCalledInFireYet = false;
        return super.prefire();
    }

    ///////////////////////////////////////////////////////////////////
    ////                         private variables                 ////

    // True if sleep was called in fire().  Sleep should only
    // be called once in fire() per iteration.
    private boolean _wasSleepCalledInFireYet = false;
}


More information about the Kepler-dev mailing list