/* SCCS - @(#)NslMultiClockScheduler.java 1.4 - 02/22/99 - 14:29:33 */
// Copyright: Copyright (c) 1997 University of Southern California Brain Project.
// Copyright: This software may be freely copied provided the toplevel
// Copyright: COPYRIGHT file is included with each such copy.
// Copyright: Email nsl@java.usc.edu.
/*
* $Log: NslMultiClockScheduler.java,v $
* Revision 1.4 1997/11/18 01:18:18 erhan
* *** empty log message ***
*
* Revision 1.3 1997/11/06 03:15:28 erhan
* nsl3.0.b
*
* Revision 1.2 1997/07/30 21:19:44 erhan
* nsl3.0
*
* Revision 1.1.1.1 1997/03/12 22:52:21 nsl
* new dir structure
*
* Revision 1.1.1.1 1997/02/08 00:40:40 nsl
* Imported the Source directory
*
*/
//
// NslMultiClockScheduler.java
//
//////////////////////////////////////////////////////////////////////
/**
* NslMultiClockScheduler - a multi-clocked scheduler.
In NslMultiClockScheduler, each module can have its
run_step_size, or each has different run time
interval. In the currnt implementation, the run_step_size
must be set by setRunStepSize in makeinst
in NslModule. Otherwise, the module will have system
default time step and in order to activate this parameter,
the whole model has to be removed from the scheduler and
re-initialize.
The run step size of each module should be the maximum possible
step size without making chaotic behaviour in the model.
Run step size of modules without execution part, like top-level
modules, should be 0. This could improve the performance of
simulation
* @see NslModule#setRunStepSize, NslModule#getRunStepSize
*/
package nslj.src.system;
import nslj.src.lang.NslModule;
import nslj.src.display.*;
import java.lang.*;
import java.util.Vector;
import java.util.Enumeration;
public class NslMultiClockScheduler extends NslScheduler {
Vector clock_list; // a list of vectors, in which contains
// modules with a same run time step size
NslSystem system;
// it keep checking the minimum run step size in the module.
// it is used to warn the system the possibility that the
// system run step size is larger than the required run step
// size.
double _min_step_size=Double.MAX_VALUE;
public NslMultiClockScheduler(NslSystem sys) {
clock_list = new Vector(10,10);
system = sys;
simulationSuspended = true;
//setDaemon(true);
}
/**
* Add module into the scheduler.
* If there exists a list of
* modules with the same run step size as the object module,
* the module will be added to the corresponding list.
* Otherwise, a list of module with that run step size will be created.
* There is no maximum number of those lists, but keeping it
* minimal can significantly speed up the simulation.
* @param module - module to be added.
*
*/
void addSorted(NslClockSchedulerModuleVector V, NslModule m)
{
int pos;
NslModule first,second;
Enumeration E = V.elements(); //the different loops
/* empty: insert wherever */
if (V.size()==0) {
V.addElement(m);
return;
}
first=(NslModule)E.nextElement(); pos=0;
/* insert at front */
if ((first.getorder_str()).compareTo(m.getorder_str()) >= 0 )
{
V.insertElementAt(m,pos);
return;
}
/* insert between two modules */
while(E.hasMoreElements()) {
second = (NslModule)E.nextElement(); pos++;
if ((first.getorder_str()).compareTo(m.getorder_str()) <= 0 )
if ((second.getorder_str()).compareTo(m.getorder_str()) >= 0 )
{
V.insertElementAt(m,pos);
return;
}
first=second;
}
/* insert at the rear */
V.addElement(m);
}
public void addModule(NslModule module) {
/* TOD0: change from comparing string lenght to actually looking at
the system.schedulerMethod string.
*/
NslModule d;
if(module==null)
throw new NullPointerException();
Enumeration E = clock_list.elements();
NslClockSchedulerModuleVector V;
double stepsize = module.getRunStepSize();
while (E.hasMoreElements()) {
V = (NslClockSchedulerModuleVector)E.nextElement();
if(V.getRunStepSize() == stepsize) {
addSorted(V,module); // V.addElement(module);
/* System.out.println("#debug: NslMultiClockScheduler: Added "+module.getName()+" into the scheduler:");
for (Enumeration e = V.elements() ; e.hasMoreElements() ;) {
d=(NslModule)e.nextElement();
//System.out.println(d.getName()+" ["+d.getorder_str()+"] (pre:"+d.getID_str()+")" );}
//System.out.println("\n");
*/
return;
}
}
// no module vector or step size is new
if (stepsize>0 && stepsize < _min_step_size) {
_min_step_size = stepsize;
system.setRunStepSize(stepsize);
}
V = new NslClockSchedulerModuleVector(stepsize);
addSorted(V,module); // V.addElement(module);
/*
//System.out.println("debug: NslMultiClockScheduler: Adding "+module.getName()+" into the scheduler");
for (Enumeration e = V.elements() ; e.hasMoreElements() ;){
d=(NslModule)e.nextElement();
//System.out.println(d.getName()+" ["+d.getorder_str()+"]");}
//System.out.println("added (V newly created)\n");
*/
clock_list.addElement(V);
return;
}
/**
* Do nothing.
* @param link - link to be added.
*/
public void addConnection(/*NslConnection link*/) {}
/**
* Run the active modules until the NslSystem.end_time
*/
public void run() {
run(system.getRunEndTime());
}
/**
* Run the active modules until time time
in the basic step size specified in NslSystem
The modules registered in the scheduler will run
with an interval specified by the run step size.
* @param time - end time for running
*/
public void run(double end_time) {
double dt = system.getRunStepSize();
contEndTime=actualEndTime=originalEndTime=end_time;
NslDisplaySystemVector dsv = system.display_system_list;
Enumeration E = clock_list.elements();
NslClockSchedulerModuleVector V;
while (E.hasMoreElements()) {
V = (NslClockSchedulerModuleVector)E.nextElement();
V.init_run();
}
// scheduler
for (; ;) {
try {
//System.out.println(getClass().getName()+": Waiting for message");
synchronized (this) {
while (simulationSuspended || system.train_or_run!='R')
wait();
if (actualEndTimecontEndTime)
wait();
if (actualEndTime