.\" @(#)wormhole	1.8	12/12/92
.H1 "The Wormhole Class"
.pp
.IE "wormhole design"
A wormhole for a domain is much like a star belonging to that domain,
but it contains pointers to a subsystem that operates in a different
domain.  The interface to that other domain is through a "universal
event horizon".
.IE "universal event horizon"
The wormhole design, therefore, does not depend on the domain
it contains, but only on the domain in which it is used as a block.
It must look like a star in that outer domain.
.pp
The base
.c Wormhole
class is derived from class
.c Runnable ,
just like the class
.c Universe .
Every member of the
.c Runnable
class has a pointer to a component
.c Galaxy
and a
.c Target .
The
.c Target ,
in turn, has a pointer to a
.c Scheduler .
Like a
.c Universe ,
a 
.c Wormhole
can perform the scheduling actions on the component
.c Galaxy.
A
.c Wormhole
is different from a
.c Universe
in that it is not a stand-alone object.  Instead, it is triggered
from the outer domain to initiate the scheduling.
.pp
Each domain has a derived
.c Wormhole
class.
For example, the SDF domain has class
.c SDFWormhole .
This domain-specific
.c Wormhole
is derived from not only the base
.c Wormhole
class but also from the domain-specific star class,
.c SDFStar .
This multiple inheritance realizes the inherent nature of the
.c Wormhole .
First, the
.c Wormhole
behaves exactly like a
.c Star
from the outer domain (SDF) since it is derived from 
.c SDFStar .
Second, internally it can encapsulate an entire foreign domain
with a separate 
.c Galaxy
and a separate
.c Scheduler .
.pp
The 
.c Scheduler 
executes a star by calling its
.c run() method.
This method first causes
data packets 
.c (Particles )
to be delivered to the 
.c Star
by invoking the
.c receiveData()
method of the input ports.
.IE "receiveData()"
The
.c go()
method of the star is then invoked, which does whatever computation
is associated with this particular star.
After the execution of
.c go() ,
the
.c run()
method then
sends particles to other stars
by calling the
.c sendData()
.IE "sendData()"
method of the output ports.
Thus, the
.c run()
method
calls a sequence of methods to execute a star:
.c receiveData()
on the input ports,
.c go()
on the 
.c Star ,
and
.c sendData()
on the output ports.
The same sequence of calls are also used when the star happens
to be a wormhole.
In this case 
.c receiveData()
and 
.c sendData()
operate
via the event horizon.
The design of these methods will be discussed in the 
next section.
.pp
The main part of the domain interface is performed in the

.c go()
method of the
.c Wormhole .
As an example, the 
.c go()
method of the
.c SDFWormhole
class
is defined as follows.
.(c
void SDFWormhole :: go() {
	// set the currentTime of the inner domain.
	target->setCurrentTime(arrivalTime);
	// run
	Wormhole::run();
}
.)c
After getting the input data packets (
.c receiveData() ),
the
.c Wormhole
first synchronizes the inner domain with the outer domain.
The 
.c currentTime
of the inner 
.IE "currentTime, scheduler"
target and scheduler is set to the arrival time of the data packets
.c (arrivalTime) .
Since the SDF domain is untimed, the decision on the arrival time of the
data packets is trivial.
The next step is to call the 
.c run()
method of the base
.c Wormhole
class.
Here is a part of the definition\** of the
.c Wormhole
class.
.(f
\** We omit the members that are not relevant to the domain interface such
as the constructor and print methods.
.)f
.(c
class Wormhole : public Runnable {
public:
	void setup() { initTarget(); }
	int run() {
		if (!checkReady()) return TRUE;
		setStopTime(1.0);    // dummy value
		if (!Runnable :: run()) return FALSE;
		sumUp();
		return TRUE;
	}

	// redefine setStopTime()
	void setStopTime(double) { target->resetStopTime(getStopTime()); }
protected :
	// get the stopping condition for the inner domain.
	// Must be redefined in the derived class.
	virtual double getStopTime() = 0;

	// arrange things after run if necessary
	virtual void sumUp() {}

private :
	// check ready
	int checkReady() const;
};
.)c
The 
.c run()
method of the
.c Wormhole
class consists of four method calls.
The first one, 
.c checkReady() ,
checks the readiness of the input data.
Suppose the wormhole is a
DE wormhole,
and the inner domain is an SDF domain.  If there is an input event to the
wormhole, then the wormhole
is runnable\** from the point of view of the DE domain, and the 
.c go()
method is called.
.IE "runnable"
.(f
\**The decision of runnability of a wormhole is indistinguishable
from those of other stars.  For example, an
.c SDFWormhole
is runnable when all input ports have sufficient data packets.
.)f
However, the inner SDF domain may not be fired before all input 
.c PortHole s
have enough particles.  In this case, the 
.c checkReady()
method
will return FALSE to terminate the execution.
This method is discussed in more detail below.
.pp
When all input data packets are ready, we can initiate the
inner scheduler
by calling the 
.c run()
method of the
.c Runnable
class which is the base class of the
.c Wormhole .
Before initiating the inner scheduler,
we should specify its stopping condition
using the 
.c setStopTime()
method of the wormhole,
which invokes the 
.c resetStopTime()
method of the scheduler.
How to set the value of the stop time is discussed above.
.pp
In the initialization stage of the outer
galaxy,
the 
.c setup()
method is called.  The 
.c setup()
method of a
wormhole calls the 
.c setup()
method of the base
.c Wormhole
class (see for instance the source code
for 
.c SDFWormhole :: setup()
in ~ptolemy/src/domains/sdf/kernel).
In the 
.c setup()
method, the inner domain is not only initialized
but also any compile-time scheduling for the inner domain is performed.
Also, the flag 
.c stopBeforeDeadlocked
is set FALSE by default.
The flag will be set TRUE by the inner scheduler
when the inner domain suspends execution before
being deadlocked (meaning that one or more stars
in the domain is runnable).
.IE "deadlock"
.IE "stopBeforeDeadlocked"
