Processes Step by Step

Model Implementation (2)

The Truck Process

   
 

Implementing the truck simulation process starts out quite similar to implementing the van carrier process. First, derive a class named Truck from SimProcess, add the appropriate import statement and define the constructor. Then define a field (attribute) to store a reference to the model in and assign it a value inside the constructor.

import desmoj.core.simulator.*;
import co.paralleluniverse.fibers.SuspendExecution;
/**
 * This class represents the truck in the ProcessesExample
 * model.
 *
 * A truck arrives at the container terminal and requests
 * loading of a container. If possible, it is served
 * by the van carrier immediately. Otherwise it waits in the
 * parking area for its turn.
 * After service is completed, it leaves the system.
 */
public class Truck extends SimProcess {

   /** a reference to the model this process is a part of
    *  useful shortcut to access the model's static components
    */
   private ProcessesExample myModel;
   /**
    * Constructor of the truck process
    *
    * Used to create a new truck to be serviced by a van carrier.
    *
    * @param owner the model this process belongs to
    * @param name this truck's name
    * @param showInTrace flag to indicate if this process shall produce
    *                    output for the trace
    */
   public Truck(Model owner, String name, boolean showInTrace) {

      super(owner, name, showInTrace);
      // store a reference to the model this truck is associated with
      myModel = (ProcessesExample)owner;
   }

   ...

} /* end of process class */

Now we have to implement the lifeCycle() method. Please refer to the conceptual model if you need a reminder of what a truck does. On arrival at the terminal, the truck enters the truck queue. It then checks if there is an idle VC available. If so, it activates the van carrier to service it. It then waits in the queue until it is reactivated by the van carrier after service is completed.

Let us start with driving our truck onto the parking lot:

   /**
    * Describes this truck's life cycle:
    *
    * On arrival, the truck will enter the queue (parking lot).
    * It will then check if the van carrier is available.
    * If this is the case, it will activate the van carrier to
    * get serviced and transfer the control to the VC.
    * Otherwise it just passivates (waits).
    * After service it leaves the system.
    */
   public void lifeCycle() throws SuspendExecution {

      // enter parking-lot
      myModel.truckQueue.insert(this);
      sendTraceNote("TruckQueuelength: "+ myModel.truckQueue.length());

      ...

By inserting the truck into the queue we make the queue keeping track of the statistical data automatically. Each queue is generating a report from the statistical data collected during the simulation run.

The sendTraceNote() statement, a method of the ModelComponent class, is used to insert additional text into the trace file output. This is a very handy way of making the trace file better understandable to the reader. Every infomation added here will help you to understand the behaviour of the entities in your model. This might be very useful when debugging your code. You can add every accessable program information via this method to the trace file output.

Next we have to implement the if-statement to test whether there is a van carrier available or not:

      // ... lifeCycle() continued

      // check if a VC is available
      if (!myModel.idleVCQueue.isEmpty()) {
         // yes, it is

         // get a reference to the first  VC from the idle VC queue
         VanCarrier vanCarrier = myModel.idleVCQueue.first();
         // remove the van carrier from the queue
         myModel.idleVCQueue.remove(vanCarrier);

         // place the VC on the eventlist right after me,
         // to ensure that I will be the next customer to get serviced
         vanCarrier.activateAfter(this);
      }

      ...

Note the inverse query starting with not ("!") due to the question style of the isEmpty() method. To remove an idle van carrier from the queue we again have to first get a reference to it by calling the first() method and then actually remove it by calling remove().

With the activateAfter() statement above we ensure that the van carrier will be activated by the scheduler right after the currently active truck process. The van carrier will then look into the truckQueue and service the first truck in line. It should be the one just having activated the VC.

      // ... lifeCycle() continued

      // wait for service
      passivate();

      // Ok, I am back online again, which means I was serviced
      // by the VC. I can leave the systems now.
      // Luckily I don't have to do anything more than sending
      // a message to the trace file, because the
      // Java VM garbage collector will get the job done.
      // Bye!
      sendTraceNote("Truck was serviced and leaves system.");
   }

The truck can now "sit back and wait" until it gets serviced by the van carrier. The passivate() statement above

  • stops the execution of this process at this point,
  • stores its status somewhere so it can be continued right from this point and
  • hands the control over to the scheduler,

which now activates the next entity on its internal event list (the VC).

When the scheduler returns control back to our truck object, the truck will just send a message to the trace output before it ends its life cycle. There is nothing more for it to do.



   
  http://desmoj.sourceforge.net/tutorial/processes/impl22.html