Package umontreal.iro.lecuyer.simprocs

Source Code of umontreal.iro.lecuyer.simprocs.ThreadProcessSimulator


/*
* Class:        ThreadProcessSimulator
* Description:  process simulator using Java threads for process synchronization
* Environment:  Java
* Software:     SSJ
* Copyright (C) 2001  Pierre L'Ecuyer and Université de Montréal
* Organization: DIRO, Université de Montréal
* @author       Éric Buist
* @since

* SSJ is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License (GPL) as published by the
* Free Software Foundation, either version 3 of the License, or
* any later version.

* SSJ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.

* A copy of the GNU General Public License is available at
   <a href="http://www.gnu.org/licenses">GPL licence site</a>.
*/

package umontreal.iro.lecuyer.simprocs;

import umontreal.iro.lecuyer.simevents.Event;
import umontreal.iro.lecuyer.simevents.eventlist.EventList;
import umontreal.iro.lecuyer.simevents.Simulator;
import umontreal.iro.lecuyer.simprocs.SimProcess;

/**
* Represents a process simulator using Java threads for process synchronization.
* The simulation process threads are synchronized so only one process runs
* at a time.
*
*/
public class ThreadProcessSimulator extends ProcessSimulator  {

   private SimThread threadAllHead = null;
   //Tete de la liste des SimThread associated to this ThreadProcessSimulator


   /**
    * Creates a new {@link ThreadProcessSimulator} variable.
    *
    */
   public ThreadProcessSimulator()  {
   }

   /**
    * Initializes the thread process-driven simulation  using
    *  {@link umontreal.iro.lecuyer.simevents.eventlist.SplayTree SplayTree} algorithm
    *  as {@link umontreal.iro.lecuyer.simevents.eventlist.EventList EventList}.
    *    This kills all processes already associated with the current variable.
    *
    */
   public void init()  {
      super.init();
      /*if(threadAllHead != null)
         killAll();
      threadAllHead = null;                    //!!!!! utilisation de killAll instable !!!!!*/
   }


   /**
    * Initializes the thread process-driven simulation
    *    using <TT>evlist</TT> variable as {@link EventList}.
    *    This kills all processes already associated with the current variable.
    *
    * @param evlist EventList assigned to the current variable eventlist field
    *
    *
    */
   public void init (EventList evlist)  {
      super.init (evlist);
      /*if(threadAllHead != null)
         killAll();                            //!!!!! utilisation de killAll instable !!!!!*/
   }


   public SimThread createControlEvent (SimProcess process) {
      return SimThread.getThread(process, this);
   }

   public void delay (SimProcess process, double delay) {
      if (currentProcess != process)
         throw new IllegalStateException  ("Calling delay() for a process not in EXECUTING state");
      if (delay < 0.0)
         throw new IllegalArgumentException ("Calling delay() with negative delay");
      process.scheduledEvent().schedule (delay);
      dispatch();
      ((SimThread)process.scheduledEvent()).passivate();
   }

   public void suspend(SimProcess process) {
      SimThread ev = (SimThread)process.scheduledEvent();

      if (ev == null)             // DEAD state
         throw new IllegalStateException ("Calling suspend() for a dead process");

      if (currentProcess == process) {             // EXECUTING state
         dispatch();
         ev.passivate();
         return;
      }

      if (ev.time() >= 0.0 ) { // DELAYED state
         ev.cancel();
         ev.setTime (SimProcess.WAITING);
         return;
      }

      if (ev.time() == SimProcess.STARTING ) // INITIAL state
         throw new IllegalStateException
                   ("Calling suspend() for a process in INITIAL state");

                                         // SUSPENDED state
      throw new IllegalStateException ("Calling suspend() for a suspended process");
   }

   public void kill(SimProcess process) {
      if (process.scheduledEvent() == null)
         throw new IllegalStateException ("cannot kill a DEAD process");
      ((SimThread)process.scheduledEvent()).kill();
   }

   /**
    * Kills all threads linked to the current variable.
    *
    */
   public void killAll()  {
      SimThread.killAll(this);
   }



    // This method looks for the next process to give it the control.
    // If there are some event in the eventList, they will be executed
    // This method doesn't reactivate the executive.
    // Its behavior is the same of the executive (see the Sim.start method)
   protected void dispatch() {
      Event ev;
      while ((ev = removeFirstEvent()) != null) {
         if (ev instanceof SimThread) {
            // This is a process, the control will transfered to it.
            currentProcess = ((SimThread)ev).myProcess;
            ((SimThread)ev).activate();
            return;
         }
         else ev.actions();
         // This event is executed by the calling process.
      }
      SimThread.simActivate(this);                     // Simulation is over.
   }

   protected SimThread threadAllHead() {
      return threadAllHead;
   }

   protected void setThreadAllHead(SimThread thread) {
      threadAllHead = thread;
   }
}





// %%%%%%%%%%%%%%%%%%%%%%%%%%%%   SimThread   %%%%%%%%%%%%%%%%%%%%%%%%%%%%
// thrown by the passivate() method and caught by the run() method.
// used to kill a process and recycle its associated thread.
// This empty class allows to control which Errors are thrown.
// If the JVM happens to throw an Error, it must not be caught
// by the SimThread class.
final class SimThreadError extends Error {
   public SimThreadError() {}
}


final class SimThread extends Event implements Runnable {
   static SimThreadError error = new SimThreadError();
    // thrown by the passivate() method and caught by the run() method.
    // used to kill a process and recycle its associated thread.

   private int n = 0;
    // Semaphore: if n < 0 this thread must wait.

   SimProcess myProcess;
    // The Process to which this thread is associated.

   private Thread myThread;
   // The Thread in which this SimThread object will run.

    // link with the next thread in the list headed by sim.threadAllHead, used by killAll().
   private SimThread nextAll = null;

   // Head of the free SimThread list
   private static SimThread threadFreeHead = null;
    // link with the next thread in the list
   private SimThread nextFree = null;

    // Constructor.
   private SimThread (SimProcess p, ThreadProcessSimulator inSim) {
      super(inSim);
      eventTime = SimProcess.STARTING;
      myProcess = p;
      myThread = new Thread (this);
      myThread.setDaemon (true);
      myThread.start();
      nextAll = ((ThreadProcessSimulator)sim).threadAllHead();
      ((ThreadProcessSimulator)sim).setThreadAllHead(this);
    }

   public static final SimThread getThread (SimProcess p, ThreadProcessSimulator inSim) {
      if (threadFreeHead == null) return new SimThread (p, inSim);
      SimThread th = threadFreeHead;   threadFreeHead = threadFreeHead.nextFree;
      th.myProcess = p;
      th.eventTime = SimProcess.STARTING;
      th.sim       = inSim;
      th.priority  = 1.0;
      return th;
    }

   // A SimThread object created and started is never destroyed
   // till the end of the simulation.
   // if the associated process is killed, an error exception will be thrown.
   // this exception will be caught here and the thread will be
   // passivated (in the next iteration).

   public final void run() {
       while(true) {
           try {
               passivate();
               myProcess.actions()// myProcess starts its life.
               ((ThreadProcessSimulator)sim).dispatch(); // Give control to another process.
           } catch (SimThreadError e) {} // An SimThreadError exception is thrown because
                                // the process is killed.
           myProcess.setScheduledEvent(null);
           myProcess = null;
           nextFree = threadFreeHead;   threadFreeHead = this;
       }
   }

   public void actions() {
   // This method will be executed only once.
   // It transfers the control from the executive to this thread.
   // The control will then be passed from process to process,
   // which will execute the events if any.
   // Control will be returned to the executive only at the end of simulation.
      ((ThreadProcessSimulator)sim).setCurrentProcess(myProcess);
      activate()// Notify this thread to be ready to take control
                   // as soon as the caller's thread is passivated.
      simPassivate(((ThreadProcessSimulator)sim))// Passivate the main thread (executive).
   }


   protected synchronized final void activate() {
   // Notifies this thread to be ready to take control.
   // It will take control when the calling thread passivates.
      n++;   notify();
   }


   protected synchronized final void passivate() {
      try {n--;  if (n<0wait();}
         catch (InterruptedException e) {
            n++;   throw error;
             // This thread is waken up and interrupted because
             // the kill() method was called on its associated process.
             // Throws a SimThreadError that
             // will be caught by run() method.
         }
   }


   protected static final void simActivate(ThreadProcessSimulator sim) {
      EventList evl = sim.getEventList();
      synchronized (evl) {evl.notify(); }
   }

   protected static final void simPassivate(ThreadProcessSimulator sim) {
      EventList evl = sim.getEventList();
      synchronized (evl) {
         try { evl.wait(); } catch (InterruptedException e) {}
      }
   }

   // The following methods are called by kill and killAll
   // of the Process class.

   protected void kill() {
        if (eventTime >= 0.0)
           cancel();
        myThread.interrupt();
   }

   protected static void  killAll(ThreadProcessSimulator sim) {
       SimThread th = sim.threadAllHead();
       while (th != null) {
           if (th.myProcess != null) th.kill();
           th = th.nextAll;

       }
   }

   public String toString() {
      // To get something useful when printing the event list
      return "Start or resume process " + myProcess.toString();
   }
}

TOP

Related Classes of umontreal.iro.lecuyer.simprocs.ThreadProcessSimulator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.