Processes Step by StepModel Implementation (2)
The Dynamic Model Components |
||
After finishing the model class we have to implement the dynamic model components of our model. Using the process-oriented modelling style, dynamic model components are represented as simulation processes. In our model, we have identified the trucks, the van carriers and the truck generator to be dynamic model components (also called active entities). For each type of active entity we will derive a class from desmoj.core.simulator.SimProcess and specify its behaviour in the lifeCycle() method. Let's start with the easiest one, the truck generator. It just loops continually through (i) generating a new truck, (ii) activating that truck, and (iii) determining the next arrival time and schedule itself for reactivation for this point in time. Refer to the conceptual model if you need to look up the details of its life cycle again. First of all, derive a class named TruckGenerator from SimProcess. Don't forget to import the desmoj.core.simulator package. Add the constructor, which is equally straightforward as the one in our model class as it only passes all parameters to the constructor of the superclass. import desmoj.core.simulator.*; import co.paralleluniverse.fibers.SuspendExecution; /** * This class represents a process source, which continually generates * trucks in order to keep the simulation running. * * It will create a new truck, activate it (so that it arrives at * the terminal) and then wait until the next truck arrival is * due. */ public class TruckGenerator extends SimProcess { /** * TruckGenerator constructor comment. * @param owner the model this truck generator belongs to * @param name this truck generator's name * @param showInTrace flag to indicate if this process shall produce output * for the trace */ public TruckGenerator(Model owner, String name, boolean showInTrace) { super(owner, name, showInTrace); } ... } /* end of process class */ Now all left to do is actually define what the truck generator does, i.e. implement its lifeCycle() method. /** * describes this process's life cycle: continually generate new trucks. */ public void lifeCycle() throws SuspendExecution { // get a reference to the model ProcessesExample model = (ProcessesExample)getModel(); // endless loop: while (true) { // create a new truck // Parameters: // model = it's part of this model // "Truck" = name of the object // true = yes please, show the truck in trace file Truck truck = new Truck(model, "Truck", true); // now let the newly created truck roll on the parking-lot // which means we will activate it after this truck generator truck.activateAfter(this); // wait until next truck arrival is due hold(new TimeSpan(model.getTruckArrivalTime(), TimeUnit.MINUTES)); // from inside to outside... // we draw a new inter-arrival time // we make a TimeSpan object out of it and // we wait for exactly this period of time } } The activities performed inside the endless while() loop are:
Observe that lifeCycle() method is declared to throw a SuspendExecution. This is required for the internal process scheduling logic, putting a "mark" where process execution can be interrupted. One detail remains to be explained: What is the purpose of the first statement inside the lifeCycle() method? The answer is simple: It's there to provide us with a convenient reference to the model so that we can access its static model components. In this case, we need to draw a sample from the truck arrival time distribution by calling the getTruckArrival() method of our model. To be able to do so, we need a reference to the model object. DESMO-J provides the getModel() method as a member of the ModelComponent class for this aim. All subclasses of ModelComponent like SimProcess or Model inherit this method. The problem we run into when using the method is that it returns an object of type Model while we need an object of the more specialised type ProcessesExample. Thus we are forced to perform a type cast, resulting in rather awkward code. For example, the hold() statement in the above life cycle would look like this:
This is rather cumbersome to type, especially if we have to access model components more than once during a life cycle, and doesn't make the code easy to read. So calling getModel() and performing the requested type cast once at the beginning of the lifeCycle() method provides for a good shortcut. Alternatively, you may add a field to the process class and assign it the associated model inside the constructor. We will use this approach in the two remaining classes. |
||
http://desmoj.sourceforge.net/tutorial/processes/impl20.html |