/* An optional base class for DDE actors.
Copyright (c) 1997-2006 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.domains.dde.kernel;
import ptolemy.actor.TypedAtomicActor;
import ptolemy.data.Token;
import ptolemy.kernel.CompositeEntity;
import ptolemy.kernel.util.IllegalActionException;
import ptolemy.kernel.util.NameDuplicationException;
import ptolemy.kernel.util.Workspace;
//////////////////////////////////////////////////////////////////////////
//// DDEActor
/**
An optional base class for DDE actors. DDEActors are intended to
execute as autonomous processes that maintain a distributed notion
of time. In a DDE model, each actor is controlled by a unique
DDEThread. Each DDEThread maintains its actor's local notion of
time. Local time information is dependent on the time stamps
associated with tokens that are consumed by an actor. More
precisely, an actor's local notion of time is equivalent to the
maximum time stamp of all tokens that the actor has consumed.
Constraints on the consumption of tokens are described in the
documentation for DDEThread. Note that consumed tokens may include
NullTokens. A NullToken is a subclass of Token that is communicated
solely for the purpose of advancing the local notion of time of the
actor that consumes the NullToken.
<P>
The DDE model of computation supports typed, polymorphic actors and
does not require this base class for implementation; this class is
purely optional. This class provides convenient syntactic shortcuts
for developing actors that operate according to DDE semantics.
@author John S. Davis II
@version $Id: DDEActor.java,v 1.47 2007/12/07 06:27:04 cxh Exp $
@since Ptolemy II 0.3
@Pt.ProposedRating Yellow (davisj)
@Pt.AcceptedRating Yellow (yuhong)
@see ptolemy.domains.dde.kernel.DDEThread
@see ptolemy.domains.dde.kernel.NullToken
*/
public class DDEActor extends TypedAtomicActor {
/** Construct a DDEActor with no container and a name that
* is an empty string.
*/
public DDEActor() {
super();
}
/** Construct a DDEActor with the specified workspace and a
* name that is an empty string.
* @param workspace The workspace for this DDEActor.
*/
public DDEActor(Workspace workspace) {
super(workspace);
}
/** Construct a DDEActor with the specified container and name.
* The name must be unique with respect to the container or an
* exception is thrown.
* @param container The container of this DDEActor.
* @param name The name of this DDEActor.
* @exception IllegalActionException If the constructor of the
* superclass throws an IllegalActionException.
* @exception NameDuplicationException If the constructor of the
* superclass throws a NameDuplicationException .
*/
public DDEActor(CompositeEntity container, String name)
throws IllegalActionException, NameDuplicationException {
super(container, name);
}
///////////////////////////////////////////////////////////////////
//// package friendly methods ////
/** Return a token from the receiver that has the minimum
* receiver time of all receivers contained by this actor.
* The returned token will have the lowest time stamp of
* all pending tokens for this actor. If there exists a
* set of multiple receivers that share a common minimum
* receiver time, then return the token contained by the
* highest priority receiver within this set. If this actor
* contains no receivers then return null.
* <P>
* The primary difference between this method and getNextToken()
* is that this method returns all types of tokens including
* NullTokens while getNextToken only returns real tokens.
*
* @return The token with the smallest time stamp of all tokens
* contained by this actor. If multiple tokens share the smallest
* time stamp this token will come from the highest priority
* receiver that has the minimum receiver time. If all receivers
* have expired then throw a TerminateProcessException.
* @see ptolemy.domains.dde.kernel.DDEReceiver
* @see ptolemy.domains.dde.kernel.TimeKeeper
* @see ptolemy.domains.dde.kernel.DDEThread
*/
Token _getNextInput() throws IllegalActionException {
Thread thread = Thread.currentThread();
if (thread instanceof DDEThread) {
TimeKeeper timeKeeper = ((DDEThread) thread).getTimeKeeper();
DDEReceiver lowestReceiver = (DDEReceiver) timeKeeper
.getFirstReceiver();
if (lowestReceiver.hasToken()) {
return lowestReceiver.get();
} else {
return _getNextInput();
}
} else {
throw new IllegalActionException(this, "Illegal attempt "
+ "to execute a DDEActor by a non-DDEThread.");
}
}
/** Return a non-NullToken from the receiver that has the minimum,
* non-negative receiver time of all receivers contained by this
* actor. If there exists a set of multiple receivers that share
* a common minimum receiver time, then return the token contained
* by the highest priority receiver within this set. If this actor
* contains no receivers then return null. This method may block
* as it calls several blocking methods.
* @return Return a non-NullToken that has the minimum, nonnegative
* receiver time of all receivers contained by this actor.
* @exception IllegalActionException If there is a problem getting
* the next input.
*/
public Token getNextToken() throws IllegalActionException {
// FIXME: This method is used by HelloWorld.PrintString()
// Is this method necessary
Token token = _getNextInput();
if (token instanceof NullToken) {
return getNextToken();
}
return token;
}
}